[Intel-gfx] [PATCH 5/7] drm/i915/wm: split out SKL+ watermark regs to a separate file

2023-03-16 Thread Jani Nikula
Clean up i915_reg.h by splitting out SKL+ watermark regs to
display/skl_watermark_regs.h.

Signed-off-by: Jani Nikula 
---
 .../drm/i915/display/intel_display_power.c|   1 +
 drivers/gpu/drm/i915/display/skl_watermark.c  |   1 +
 .../gpu/drm/i915/display/skl_watermark_regs.h | 165 ++
 drivers/gpu/drm/i915/gvt/handlers.c   |   1 +
 drivers/gpu/drm/i915/i915_reg.h   | 154 
 drivers/gpu/drm/i915/intel_gvt_mmio_table.c   |   1 +
 6 files changed, 169 insertions(+), 154 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/skl_watermark_regs.h

diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c 
b/drivers/gpu/drm/i915/display/intel_display_power.c
index dedfc837b727..10ea7656e6c8 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power.c
@@ -22,6 +22,7 @@
 #include "intel_pps_regs.h"
 #include "intel_snps_phy.h"
 #include "skl_watermark.h"
+#include "skl_watermark_regs.h"
 #include "vlv_sideband.h"
 
 #define for_each_power_domain_well(__dev_priv, __power_well, __domain) \
diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c 
b/drivers/gpu/drm/i915/display/skl_watermark.c
index 50a9a6adbe32..a9b3bdf94738 100644
--- a/drivers/gpu/drm/i915/display/skl_watermark.c
+++ b/drivers/gpu/drm/i915/display/skl_watermark.c
@@ -21,6 +21,7 @@
 #include "intel_pcode.h"
 #include "intel_wm.h"
 #include "skl_watermark.h"
+#include "skl_watermark_regs.h"
 
 static void skl_sagv_disable(struct drm_i915_private *i915);
 
diff --git a/drivers/gpu/drm/i915/display/skl_watermark_regs.h 
b/drivers/gpu/drm/i915/display/skl_watermark_regs.h
new file mode 100644
index ..5a3473a7844e
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/skl_watermark_regs.h
@@ -0,0 +1,165 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef __SKL_WATERMARK_REGS_H__
+#define __SKL_WATERMARK_REGS_H__
+
+#include "intel_display_reg_defs.h"
+
+#define _PIPEA_MBUS_DBOX_CTL   0x7003C
+#define _PIPEB_MBUS_DBOX_CTL   0x7103C
+#define PIPE_MBUS_DBOX_CTL(pipe)   _MMIO_PIPE(pipe, 
_PIPEA_MBUS_DBOX_CTL, \
+  _PIPEB_MBUS_DBOX_CTL)
+#define MBUS_DBOX_B2B_TRANSACTIONS_MAX_MASKREG_GENMASK(24, 20) /* tgl+ */
+#define MBUS_DBOX_B2B_TRANSACTIONS_MAX(x)  
REG_FIELD_PREP(MBUS_DBOX_B2B_TRANSACTIONS_MAX_MASK, x)
+#define MBUS_DBOX_B2B_TRANSACTIONS_DELAY_MASK  REG_GENMASK(19, 17) /* tgl+ */
+#define MBUS_DBOX_B2B_TRANSACTIONS_DELAY(x)
REG_FIELD_PREP(MBUS_DBOX_B2B_TRANSACTIONS_DELAY_MASK, x)
+#define MBUS_DBOX_REGULATE_B2B_TRANSACTIONS_EN REG_BIT(16) /* tgl+ */
+#define MBUS_DBOX_BW_CREDIT_MASK   REG_GENMASK(15, 14)
+#define MBUS_DBOX_BW_CREDIT(x) 
REG_FIELD_PREP(MBUS_DBOX_BW_CREDIT_MASK, x)
+#define MBUS_DBOX_BW_4CREDITS_MTL  
REG_FIELD_PREP(MBUS_DBOX_BW_CREDIT_MASK, 0x2)
+#define MBUS_DBOX_BW_8CREDITS_MTL  
REG_FIELD_PREP(MBUS_DBOX_BW_CREDIT_MASK, 0x3)
+#define MBUS_DBOX_B_CREDIT_MASKREG_GENMASK(12, 8)
+#define MBUS_DBOX_B_CREDIT(x)  
REG_FIELD_PREP(MBUS_DBOX_B_CREDIT_MASK, x)
+#define MBUS_DBOX_I_CREDIT_MASKREG_GENMASK(7, 5)
+#define MBUS_DBOX_I_CREDIT(x)  
REG_FIELD_PREP(MBUS_DBOX_I_CREDIT_MASK, x)
+#define MBUS_DBOX_A_CREDIT_MASKREG_GENMASK(3, 0)
+#define MBUS_DBOX_A_CREDIT(x)  
REG_FIELD_PREP(MBUS_DBOX_A_CREDIT_MASK, x)
+
+#define MBUS_UBOX_CTL  _MMIO(0x4503C)
+#define MBUS_BBOX_CTL_S1   _MMIO(0x45040)
+#define MBUS_BBOX_CTL_S2   _MMIO(0x45044)
+
+#define MBUS_CTL   _MMIO(0x4438C)
+#define MBUS_JOIN  REG_BIT(31)
+#define MBUS_HASHING_MODE_MASK REG_BIT(30)
+#define MBUS_HASHING_MODE_2x2  REG_FIELD_PREP(MBUS_HASHING_MODE_MASK, 
0)
+#define MBUS_HASHING_MODE_1x4  REG_FIELD_PREP(MBUS_HASHING_MODE_MASK, 
1)
+#define MBUS_JOIN_PIPE_SELECT_MASK REG_GENMASK(28, 26)
+#define MBUS_JOIN_PIPE_SELECT(pipe)
REG_FIELD_PREP(MBUS_JOIN_PIPE_SELECT_MASK, pipe)
+#define MBUS_JOIN_PIPE_SELECT_NONE MBUS_JOIN_PIPE_SELECT(7)
+
+/* Watermark register definitions for SKL */
+#define _CUR_WM_A_00x70140
+#define _CUR_WM_B_00x71140
+#define _CUR_WM_SAGV_A 0x70158
+#define _CUR_WM_SAGV_B 0x71158
+#define _CUR_WM_SAGV_TRANS_A   0x7015C
+#define _CUR_WM_SAGV_TRANS_B   0x7115C
+#define _CUR_WM_TRANS_A0x70168
+#define _CUR_WM_TRANS_B0x71168
+#define _PLANE_WM_1_A_00x70240
+#define _PLANE_WM_1_B_00x71240
+#define _PLANE_WM_2_A_00x70340
+#define _PLANE_WM_2_B_00x71340
+#define _PLANE_WM_SAGV_1_A 0x70258
+#define _PLANE_WM_SAGV_1_B 0x71258
+#define _PLANE_WM_SAGV_2_A 0x70358

[Intel-gfx] [PATCH 4/7] drm/i915/fdi: split out FDI regs to a separate file

2023-03-16 Thread Jani Nikula
Clean up i915_reg.h by splitting out FDI regs to
display/intel_fdi_regs.h.

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/i915/display/intel_crt.c  |   1 +
 drivers/gpu/drm/i915/display/intel_fdi.c  |   1 +
 drivers/gpu/drm/i915/display/intel_fdi_regs.h | 151 ++
 .../gpu/drm/i915/display/intel_pch_display.c  |   1 +
 drivers/gpu/drm/i915/gvt/handlers.c   |   1 +
 drivers/gpu/drm/i915/i915_irq.c   |   1 +
 drivers/gpu/drm/i915/i915_reg.h   | 141 
 drivers/gpu/drm/i915/intel_gvt_mmio_table.c   |   1 +
 8 files changed, 157 insertions(+), 141 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_fdi_regs.h

diff --git a/drivers/gpu/drm/i915/display/intel_crt.c 
b/drivers/gpu/drm/i915/display/intel_crt.c
index 8f2ebead0826..38e9c61c2344 100644
--- a/drivers/gpu/drm/i915/display/intel_crt.c
+++ b/drivers/gpu/drm/i915/display/intel_crt.c
@@ -44,6 +44,7 @@
 #include "intel_de.h"
 #include "intel_display_types.h"
 #include "intel_fdi.h"
+#include "intel_fdi_regs.h"
 #include "intel_fifo_underrun.h"
 #include "intel_gmbus.h"
 #include "intel_hotplug.h"
diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c 
b/drivers/gpu/drm/i915/display/intel_fdi.c
index c08c26a321b3..55283677c45a 100644
--- a/drivers/gpu/drm/i915/display/intel_fdi.c
+++ b/drivers/gpu/drm/i915/display/intel_fdi.c
@@ -12,6 +12,7 @@
 #include "intel_de.h"
 #include "intel_display_types.h"
 #include "intel_fdi.h"
+#include "intel_fdi_regs.h"
 
 struct intel_fdi_funcs {
void (*fdi_link_train)(struct intel_crtc *crtc,
diff --git a/drivers/gpu/drm/i915/display/intel_fdi_regs.h 
b/drivers/gpu/drm/i915/display/intel_fdi_regs.h
new file mode 100644
index ..853b834c35a9
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_fdi_regs.h
@@ -0,0 +1,151 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef __INTEL_FDI_REGS_H__
+#define __INTEL_FDI_REGS_H__
+
+#include "intel_display_reg_defs.h"
+
+#define FDI_PLL_BIOS_0  _MMIO(0x46000)
+#define  FDI_PLL_FB_CLOCK_MASK  0xff
+#define FDI_PLL_BIOS_1  _MMIO(0x46004)
+#define FDI_PLL_BIOS_2  _MMIO(0x46008)
+#define DISPLAY_PORT_PLL_BIOS_0 _MMIO(0x4600c)
+#define DISPLAY_PORT_PLL_BIOS_1 _MMIO(0x46010)
+#define DISPLAY_PORT_PLL_BIOS_2 _MMIO(0x46014)
+
+#define FDI_PLL_FREQ_CTL_MMIO(0x46030)
+#define  FDI_PLL_FREQ_CHANGE_REQUEST(1 << 24)
+#define  FDI_PLL_FREQ_LOCK_LIMIT_MASK   0xfff00
+#define  FDI_PLL_FREQ_DISABLE_COUNT_LIMIT_MASK  0xff
+
+#define _FDI_RXA_CHICKEN0xc200c
+#define _FDI_RXB_CHICKEN0xc2010
+#define  FDI_RX_PHASE_SYNC_POINTER_OVR (1 << 1)
+#define  FDI_RX_PHASE_SYNC_POINTER_EN  (1 << 0)
+#define FDI_RX_CHICKEN(pipe)   _MMIO_PIPE(pipe, _FDI_RXA_CHICKEN, 
_FDI_RXB_CHICKEN)
+
+/* CPU: FDI_TX */
+#define _FDI_TXA_CTL0x60100
+#define _FDI_TXB_CTL0x61100
+#define FDI_TX_CTL(pipe)   _MMIO_PIPE(pipe, _FDI_TXA_CTL, _FDI_TXB_CTL)
+#define  FDI_TX_DISABLE (0 << 31)
+#define  FDI_TX_ENABLE  (1 << 31)
+#define  FDI_LINK_TRAIN_PATTERN_1   (0 << 28)
+#define  FDI_LINK_TRAIN_PATTERN_2   (1 << 28)
+#define  FDI_LINK_TRAIN_PATTERN_IDLE(2 << 28)
+#define  FDI_LINK_TRAIN_NONE(3 << 28)
+#define  FDI_LINK_TRAIN_VOLTAGE_0_4V(0 << 25)
+#define  FDI_LINK_TRAIN_VOLTAGE_0_6V(1 << 25)
+#define  FDI_LINK_TRAIN_VOLTAGE_0_8V(2 << 25)
+#define  FDI_LINK_TRAIN_VOLTAGE_1_2V(3 << 25)
+#define  FDI_LINK_TRAIN_PRE_EMPHASIS_NONE (0 << 22)
+#define  FDI_LINK_TRAIN_PRE_EMPHASIS_1_5X (1 << 22)
+#define  FDI_LINK_TRAIN_PRE_EMPHASIS_2X   (2 << 22)
+#define  FDI_LINK_TRAIN_PRE_EMPHASIS_3X   (3 << 22)
+/* ILK always use 400mV 0dB for voltage swing and pre-emphasis level.
+   SNB has different settings. */
+/* SNB A-stepping */
+#define  FDI_LINK_TRAIN_400MV_0DB_SNB_A(0x38 << 22)
+#define  FDI_LINK_TRAIN_400MV_6DB_SNB_A(0x02 << 22)
+#define  FDI_LINK_TRAIN_600MV_3_5DB_SNB_A  (0x01 << 22)
+#define  FDI_LINK_TRAIN_800MV_0DB_SNB_A(0x0 << 22)
+/* SNB B-stepping */
+#define  FDI_LINK_TRAIN_400MV_0DB_SNB_B(0x0 << 22)
+#define  FDI_LINK_TRAIN_400MV_6DB_SNB_B(0x3a << 22)
+#define  FDI_LINK_TRAIN_600MV_3_5DB_SNB_B  (0x39 << 22)
+#define  FDI_LINK_TRAIN_800MV_0DB_SNB_B(0x38 << 22)
+#define  FDI_LINK_TRAIN_VOL_EMP_MASK   (0x3f << 22)
+#define  FDI_DP_PORT_WIDTH_SHIFT   19
+#define  FDI_DP_PORT_WIDTH_MASK(7 << 
FDI_DP_PORT_WIDTH_SHIFT)
+#define  FDI_DP_PORT_WIDTH(width)   (((width) - 1) << 
FDI_DP_PORT_WIDTH_SHIFT)
+#define  FDI_TX_ENHANCE_FRAME_ENABLE(1 << 18)
+/* Ironlake: hardwired to 1 */
+#define  FDI_TX_PLL_ENABLE  (1 << 14)
+
+/* Ivybridge has different bits for lolz */
+#define  FDI_LINK_TRAIN_PATTERN_1_IVB   (0 << 8)
+#define  FDI_LINK_TRAIN_PATTERN_2_IVB   (1 << 8)
+#define  

Re: [Intel-gfx] [PATCH 03/14] drm/i915/tc: Fix the ICL PHY ownership check in TC-cold state

2023-03-16 Thread Souza, Jose
On Thu, 2023-03-16 at 15:17 +0200, Imre Deak wrote:
> The commit renaming icl_tc_phy_is_in_safe_mode() to
> icl_tc_phy_take_ownership() didn't flip the function's return value
> accordingly, fix this up.
> 
> This didn't cause an actual problem besides state check errors, since
> the function is only used during HW readout.

Reviewed-by: José Roberto de Souza 

> 
> Cc: José Roberto de Souza 
> Fixes: f53979d68a77 ("drm/i915/display/tc: Rename safe_mode functions 
> ownership")
> Signed-off-by: Imre Deak 
> ---
>  drivers/gpu/drm/i915/display/intel_tc.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
> b/drivers/gpu/drm/i915/display/intel_tc.c
> index 0b6fe96ab4759..fd826b9657e93 100644
> --- a/drivers/gpu/drm/i915/display/intel_tc.c
> +++ b/drivers/gpu/drm/i915/display/intel_tc.c
> @@ -418,9 +418,9 @@ static bool icl_tc_phy_is_owned(struct intel_digital_port 
> *dig_port)
>   val = intel_de_read(i915, PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia));
>   if (val == 0x) {
>   drm_dbg_kms(>drm,
> - "Port %s: PHY in TCCOLD, assume safe mode\n",
> + "Port %s: PHY in TCCOLD, assume not owned\n",
>   dig_port->tc_port_name);
> - return true;
> + return false;
>   }
>  
>   return val & DP_PHY_MODE_STATUS_NOT_SAFE(dig_port->tc_phy_fia_idx);



[Intel-gfx] [PATCH 14/14] drm/i915/tc: Check the PLL type used by an enabled TC port

2023-03-16 Thread Imre Deak
The current way to determine during HW state sanitization if a PHY is
connected in the expected way doesn't work in all cases. The check for
this considers only the PHY ready/owned state and the initial TC mode
which was determined earlier by the TC port HW readout - using the
sink's HPD and the same PHY ready/owned states.

For instance for an enabled DP-alt/TBT port without the PHY ready/owned
flags set the initial mode will be TBT, and this will be regarded as a
valid PHY state. However it's possible that the port is actually enabled
in DP-alt mode, but for some reason the PHY ownership was not acquired.

Make sure the driver can detect invalid PHY states as in the above
example by checking the PHY ready/owned state wrt. the PLL type used.
This should be the TBT PLL if the PHY is not owned and the MG (non-TBT)
PLL if the PHY is owned.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_tc.c | 45 ++---
 1 file changed, 25 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
b/drivers/gpu/drm/i915/display/intel_tc.c
index 8481018d0fdaa..5f924608a523a 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -5,6 +5,7 @@
 
 #include "i915_drv.h"
 #include "i915_reg.h"
+#include "intel_ddi.h"
 #include "intel_de.h"
 #include "intel_display.h"
 #include "intel_display_power_map.h"
@@ -568,29 +569,29 @@ static bool tc_phy_is_ready_and_owned(struct 
intel_digital_port *dig_port,
return phy_is_ready && phy_is_owned;
 }
 
-static bool icl_tc_phy_is_connected(struct intel_digital_port *dig_port)
+static bool tc_phy_is_connected(struct intel_digital_port *dig_port,
+   enum icl_port_dpll_id port_pll_type)
 {
-   struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
-
-   if (!tc_phy_status_complete(dig_port)) {
-   drm_dbg_kms(>drm, "Port %s: PHY status not complete\n",
-   dig_port->tc_port_name);
-   return dig_port->tc_mode == TC_PORT_TBT_ALT;
-   }
-
-   /* On ADL-P the PHY complete flag is set in TBT mode as well. */
-   if (IS_ALDERLAKE_P(i915) && dig_port->tc_mode == TC_PORT_TBT_ALT)
-   return true;
+   struct intel_encoder *encoder = _port->base;
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+   bool phy_is_ready = tc_phy_status_complete(dig_port);
+   bool phy_is_owned = tc_phy_is_owned(dig_port);
+   bool is_connected;
 
-   if (!tc_phy_is_owned(dig_port)) {
-   drm_dbg_kms(>drm, "Port %s: PHY not owned\n",
-   dig_port->tc_port_name);
+   if (tc_phy_is_ready_and_owned(dig_port, phy_is_ready, phy_is_owned))
+   is_connected = port_pll_type == ICL_PORT_DPLL_MG_PHY;
+   else
+   is_connected = port_pll_type == ICL_PORT_DPLL_DEFAULT;
 
-   return false;
-   }
+   drm_dbg_kms(>drm,
+   "Port %s: PHY connected: %s (ready: %s, owned: %s, 
pll_type: %s)\n",
+   dig_port->tc_port_name,
+   str_yes_no(is_connected),
+   str_yes_no(phy_is_ready),
+   str_yes_no(phy_is_owned),
+   port_pll_type == ICL_PORT_DPLL_DEFAULT ? "tbt" : "non-tbt");
 
-   return dig_port->tc_mode == TC_PORT_DP_ALT ||
-  dig_port->tc_mode == TC_PORT_LEGACY;
+   return is_connected;
 }
 
 static void tc_phy_wait_for_ready(struct intel_digital_port *dig_port)
@@ -877,15 +878,19 @@ static bool tc_port_has_active_links(struct 
intel_digital_port *dig_port)
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
struct intel_encoder *encoder = _port->base;
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+   enum icl_port_dpll_id pll_type = ICL_PORT_DPLL_DEFAULT;
int active_links = 0;
 
if (dig_port->dp.is_mst) {
+   /* TODO: get the PLL type for MST, once HW readout is done for 
it. */
active_links = intel_dp_mst_encoder_active_links(dig_port);
} else if (crtc && crtc->active) {
+   pll_type = intel_ddi_port_pll_type(encoder,
+  
to_intel_crtc_state(crtc->base.state));
active_links = 1;
}
 
-   if (active_links && !icl_tc_phy_is_connected(dig_port))
+   if (active_links && !tc_phy_is_connected(dig_port, pll_type))
drm_err(>drm,
"Port %s: PHY disconnected with %d active link(s)\n",
dig_port->tc_port_name, active_links);
-- 
2.37.1



[Intel-gfx] [PATCH 10/14] drm/i915/tc: Make the TC mode readout consistent in all PHY states

2023-03-16 Thread Imre Deak
For consistency detect the initial TC mode in the PHY owned state the
same way this is done in the not owned state (w/o changing the
behavior). While at it, add more details to the PHY state debug print.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_tc.c | 43 +++--
 1 file changed, 33 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
b/drivers/gpu/drm/i915/display/intel_tc.c
index 35e6339caa32f..5d040f0c5f630 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -619,6 +619,26 @@ tc_phy_hpd_live_mode(struct intel_digital_port *dig_port)
return hpd_mask_to_tc_mode(live_status_mask);
 }
 
+static enum tc_port_mode
+get_tc_mode_in_phy_owned_state(struct intel_digital_port *dig_port,
+  enum tc_port_mode live_mode)
+{
+   switch (live_mode) {
+   case TC_PORT_LEGACY:
+   case TC_PORT_DP_ALT:
+   return live_mode;
+   default:
+   MISSING_CASE(live_mode);
+   fallthrough;
+   case TC_PORT_TBT_ALT:
+   case TC_PORT_DISCONNECTED:
+   if (dig_port->tc_legacy_port)
+   return TC_PORT_LEGACY;
+   else
+   return TC_PORT_DP_ALT;
+   }
+}
+
 static enum tc_port_mode
 get_tc_mode_in_phy_not_owned_state(struct intel_digital_port *dig_port,
   enum tc_port_mode live_mode)
@@ -660,13 +680,20 @@ intel_tc_port_get_current_mode(struct intel_digital_port 
*dig_port)
phy_is_ready = tc_phy_status_complete(dig_port);
phy_is_owned = tc_phy_is_owned(dig_port);
 
-   if (!tc_phy_is_ready_and_owned(dig_port, phy_is_ready, phy_is_owned))
-   return get_tc_mode_in_phy_not_owned_state(dig_port, live_mode);
+   if (!tc_phy_is_ready_and_owned(dig_port, phy_is_ready, phy_is_owned)) {
+   mode = get_tc_mode_in_phy_not_owned_state(dig_port, live_mode);
+   } else {
+   drm_WARN_ON(>drm, live_mode == TC_PORT_TBT_ALT);
+   mode = get_tc_mode_in_phy_owned_state(dig_port, live_mode);
+   }
 
-   mode = dig_port->tc_legacy_port ? TC_PORT_LEGACY : TC_PORT_DP_ALT;
-   if (live_mode != TC_PORT_DISCONNECTED &&
-   !drm_WARN_ON(>drm, live_mode == TC_PORT_TBT_ALT))
-   mode = live_mode;
+   drm_dbg_kms(>drm,
+   "Port %s: PHY mode: %s (ready: %s, owned: %s, HPD: %s)\n",
+   dig_port->tc_port_name,
+   tc_port_mode_name(mode),
+   str_yes_no(phy_is_ready),
+   str_yes_no(phy_is_owned),
+   tc_port_mode_name(live_mode));
 
return mode;
 }
@@ -842,10 +869,6 @@ void intel_tc_port_init_mode(struct intel_digital_port 
*dig_port)
 
tc_cold_unblock(dig_port, domain, tc_cold_wref);
 
-   drm_dbg_kms(>drm, "Port %s: init mode (%s)\n",
-   dig_port->tc_port_name,
-   tc_port_mode_name(dig_port->tc_mode));
-
mutex_unlock(_port->tc_lock);
 }
 
-- 
2.37.1



[Intel-gfx] [PATCH 09/14] drm/i915/tc: Fix initial TC mode on disabled legacy ports

2023-03-16 Thread Imre Deak
Atm, a TC port's initial mode will be read out as TBT mode in any case
the PHY ownership is not held. This isn't correct for legacy ports which
should be used only in legacy mode.

Fix the above initial mode to be disconnected mode for a legacy port and
TBT mode for DP-alt/TBT ports. Determine the port type by checking first
the HPD state and then the legacy VBT flag (so the HPD state can correct
a bogus VBT flag). If a sink is connected on a disabled port the PHY
will get also connected (switching it to legacy mode on a legacy port).

Also connect the PHY on a legacy port if it's enabled but BIOS
incorrectly left it in the disconnected state for some reason.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_tc.c | 67 ++---
 1 file changed, 61 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
b/drivers/gpu/drm/i915/display/intel_tc.c
index f66129494cc40..35e6339caa32f 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -558,6 +558,16 @@ static void icl_tc_phy_disconnect(struct 
intel_digital_port *dig_port)
}
 }
 
+static bool tc_phy_is_ready_and_owned(struct intel_digital_port *dig_port,
+ bool phy_is_ready, bool phy_is_owned)
+{
+   struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+
+   drm_WARN_ON(>drm, phy_is_owned && !phy_is_ready);
+
+   return phy_is_ready && phy_is_owned;
+}
+
 static bool icl_tc_phy_is_connected(struct intel_digital_port *dig_port)
 {
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
@@ -609,11 +619,34 @@ tc_phy_hpd_live_mode(struct intel_digital_port *dig_port)
return hpd_mask_to_tc_mode(live_status_mask);
 }
 
+static enum tc_port_mode
+get_tc_mode_in_phy_not_owned_state(struct intel_digital_port *dig_port,
+  enum tc_port_mode live_mode)
+{
+   switch (live_mode) {
+   case TC_PORT_LEGACY:
+   return TC_PORT_DISCONNECTED;
+   case TC_PORT_DP_ALT:
+   case TC_PORT_TBT_ALT:
+   return TC_PORT_TBT_ALT;
+   default:
+   MISSING_CASE(live_mode);
+   fallthrough;
+   case TC_PORT_DISCONNECTED:
+   if (dig_port->tc_legacy_port)
+   return TC_PORT_DISCONNECTED;
+   else
+   return TC_PORT_TBT_ALT;
+   }
+}
+
 static enum tc_port_mode
 intel_tc_port_get_current_mode(struct intel_digital_port *dig_port)
 {
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
enum tc_port_mode live_mode = tc_phy_hpd_live_mode(dig_port);
+   bool phy_is_ready;
+   bool phy_is_owned;
enum tc_port_mode mode;
 
/*
@@ -624,9 +657,11 @@ intel_tc_port_get_current_mode(struct intel_digital_port 
*dig_port)
if (dig_port->tc_legacy_port)
tc_phy_wait_for_ready(dig_port);
 
-   if (!tc_phy_is_owned(dig_port) ||
-   drm_WARN_ON(>drm, !tc_phy_status_complete(dig_port)))
-   return TC_PORT_TBT_ALT;
+   phy_is_ready = tc_phy_status_complete(dig_port);
+   phy_is_owned = tc_phy_is_owned(dig_port);
+
+   if (!tc_phy_is_ready_and_owned(dig_port, phy_is_ready, phy_is_owned))
+   return get_tc_mode_in_phy_not_owned_state(dig_port, live_mode);
 
mode = dig_port->tc_legacy_port ? TC_PORT_LEGACY : TC_PORT_DP_ALT;
if (live_mode != TC_PORT_DISCONNECTED &&
@@ -758,6 +793,7 @@ void intel_tc_port_init_mode(struct intel_digital_port 
*dig_port)
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
intel_wakeref_t tc_cold_wref;
enum intel_display_power_domain domain;
+   bool update_mode = false;
 
mutex_lock(_port->tc_lock);
 
@@ -773,14 +809,32 @@ void intel_tc_port_init_mode(struct intel_digital_port 
*dig_port)
 * intel_tc_port_sanitize_mode().
 */
dig_port->tc_init_mode = dig_port->tc_mode;
-   dig_port->tc_lock_wakeref = tc_cold_block(dig_port, 
_port->tc_lock_power_domain);
+   if (dig_port->tc_mode != TC_PORT_DISCONNECTED)
+   dig_port->tc_lock_wakeref =
+   tc_cold_block(dig_port, 
_port->tc_lock_power_domain);
 
/*
 * The PHY needs to be connected for AUX to work during HW readout and
 * MST topology resume, but the PHY mode can only be changed if the
 * port is disabled.
+*
+* An exception is the case where BIOS leaves the PHY incorrectly
+* disconnected on an enabled legacy port. Work around that by
+* connecting the PHY even though the port is enabled. This doesn't
+* cause a problem as the PHY ownership state is ignored by the
+* IOM/TCSS firmware (only display can own the PHY in that case).
 */
-   if (!tc_port_is_enabled(dig_port))
+   if (!tc_port_is_enabled(dig_port)) {
+ 

[Intel-gfx] [PATCH 13/14] drm/i915/tc: Factor out a function querying active links on a TC port

2023-03-16 Thread Imre Deak
For clarity factor out the function to determine if there are active
links on a TC port. This prepares for the next patch also checking the
port's PLL type.

No functional changes.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_tc.c | 35 -
 1 file changed, 22 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
b/drivers/gpu/drm/i915/display/intel_tc.c
index 5d040f0c5f630..8481018d0fdaa 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -872,6 +872,27 @@ void intel_tc_port_init_mode(struct intel_digital_port 
*dig_port)
mutex_unlock(_port->tc_lock);
 }
 
+static bool tc_port_has_active_links(struct intel_digital_port *dig_port)
+{
+   struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+   struct intel_encoder *encoder = _port->base;
+   struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+   int active_links = 0;
+
+   if (dig_port->dp.is_mst) {
+   active_links = intel_dp_mst_encoder_active_links(dig_port);
+   } else if (crtc && crtc->active) {
+   active_links = 1;
+   }
+
+   if (active_links && !icl_tc_phy_is_connected(dig_port))
+   drm_err(>drm,
+   "Port %s: PHY disconnected with %d active link(s)\n",
+   dig_port->tc_port_name, active_links);
+
+   return active_links;
+}
+
 /**
  * intel_tc_port_sanitize_mode: Sanitize the given port's TypeC mode
  * @dig_port: digital port
@@ -885,23 +906,11 @@ void intel_tc_port_init_mode(struct intel_digital_port 
*dig_port)
 void intel_tc_port_sanitize_mode(struct intel_digital_port *dig_port)
 {
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
-   struct intel_encoder *encoder = _port->base;
-   int active_links = 0;
 
mutex_lock(_port->tc_lock);
 
-   if (dig_port->dp.is_mst)
-   active_links = intel_dp_mst_encoder_active_links(dig_port);
-   else if (encoder->base.crtc)
-   active_links = to_intel_crtc(encoder->base.crtc)->active;
-
drm_WARN_ON(>drm, dig_port->tc_link_refcount != 1);
-   if (active_links) {
-   if (!icl_tc_phy_is_connected(dig_port))
-   drm_dbg_kms(>drm,
-   "Port %s: PHY disconnected with %d active 
link(s)\n",
-   dig_port->tc_port_name, active_links);
-   } else {
+   if (!tc_port_has_active_links(dig_port)) {
/*
 * TBT-alt is the default mode in any case the PHY ownership is 
not
 * held (regardless of the sink's connected live state), so
-- 
2.37.1



[Intel-gfx] [PATCH 12/14] drm/i915: Add encoder hook to get the PLL type used by TC ports

2023-03-16 Thread Imre Deak
Add an encoder hook, which can be called on enabled TC ports to
determine if the port uses a TBT or a non-TBT PLL. An upcoming patch
will use this to sanity check active TC port's PHY state wrt. the PLL
type used by the port.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_ddi.c  | 37 ++-
 drivers/gpu/drm/i915/display/intel_ddi.h  |  3 ++
 .../drm/i915/display/intel_display_types.h|  5 +++
 3 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index e79da640759c3..da4e1a047a806 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -3541,6 +3541,37 @@ static void icl_ddi_combo_get_config(struct 
intel_encoder *encoder,
intel_ddi_get_config(encoder, crtc_state);
 }
 
+static bool icl_ddi_tc_pll_is_tbt(const struct intel_shared_dpll *pll)
+{
+   return pll->info->id == DPLL_ID_ICL_TBTPLL;
+}
+
+static enum icl_port_dpll_id
+icl_ddi_tc_port_pll_type(struct intel_encoder *encoder,
+const struct intel_crtc_state *crtc_state)
+{
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+   const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
+
+   if (drm_WARN_ON(>drm, !pll))
+   return ICL_PORT_DPLL_DEFAULT;
+
+   if (icl_ddi_tc_pll_is_tbt(pll))
+   return ICL_PORT_DPLL_DEFAULT;
+   else
+   return ICL_PORT_DPLL_MG_PHY;
+}
+
+enum icl_port_dpll_id
+intel_ddi_port_pll_type(struct intel_encoder *encoder,
+   const struct intel_crtc_state *crtc_state)
+{
+   if (!encoder->port_pll_type)
+   return ICL_PORT_DPLL_DEFAULT;
+
+   return encoder->port_pll_type(encoder, crtc_state);
+}
+
 static void icl_ddi_tc_get_clock(struct intel_encoder *encoder,
 struct intel_crtc_state *crtc_state,
 struct intel_shared_dpll *pll)
@@ -3553,7 +3584,7 @@ static void icl_ddi_tc_get_clock(struct intel_encoder 
*encoder,
if (drm_WARN_ON(>drm, !pll))
return;
 
-   if (pll->info->id == DPLL_ID_ICL_TBTPLL)
+   if (icl_ddi_tc_pll_is_tbt(pll))
port_dpll_id = ICL_PORT_DPLL_DEFAULT;
else
port_dpll_id = ICL_PORT_DPLL_MG_PHY;
@@ -3566,7 +3597,7 @@ static void icl_ddi_tc_get_clock(struct intel_encoder 
*encoder,
 
icl_set_active_port_dpll(crtc_state, port_dpll_id);
 
-   if (crtc_state->shared_dpll->info->id == DPLL_ID_ICL_TBTPLL)
+   if (icl_ddi_tc_pll_is_tbt(crtc_state->shared_dpll))
crtc_state->port_clock = icl_calc_tbt_pll_link(i915, 
encoder->port);
else
crtc_state->port_clock = intel_dpll_get_freq(i915, 
crtc_state->shared_dpll,
@@ -4402,6 +4433,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, 
enum port port)
encoder->enable_clock = jsl_ddi_tc_enable_clock;
encoder->disable_clock = jsl_ddi_tc_disable_clock;
encoder->is_clock_enabled = jsl_ddi_tc_is_clock_enabled;
+   encoder->port_pll_type = icl_ddi_tc_port_pll_type;
encoder->get_config = icl_ddi_combo_get_config;
} else {
encoder->enable_clock = icl_ddi_combo_enable_clock;
@@ -4414,6 +4446,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, 
enum port port)
encoder->enable_clock = icl_ddi_tc_enable_clock;
encoder->disable_clock = icl_ddi_tc_disable_clock;
encoder->is_clock_enabled = icl_ddi_tc_is_clock_enabled;
+   encoder->port_pll_type = icl_ddi_tc_port_pll_type;
encoder->get_config = icl_ddi_tc_get_config;
} else {
encoder->enable_clock = icl_ddi_combo_enable_clock;
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.h 
b/drivers/gpu/drm/i915/display/intel_ddi.h
index 361f6874dde53..c85e74ae68e4d 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.h
+++ b/drivers/gpu/drm/i915/display/intel_ddi.h
@@ -40,6 +40,9 @@ void hsw_ddi_enable_clock(struct intel_encoder *encoder,
  const struct intel_crtc_state *crtc_state);
 void hsw_ddi_disable_clock(struct intel_encoder *encoder);
 bool hsw_ddi_is_clock_enabled(struct intel_encoder *encoder);
+enum icl_port_dpll_id
+intel_ddi_port_pll_type(struct intel_encoder *encoder,
+   const struct intel_crtc_state *crtc_state);
 void hsw_ddi_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state);
 struct intel_shared_dpll *icl_ddi_combo_get_pll(struct intel_encoder *encoder);
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 

[Intel-gfx] [PATCH 11/14] drm/i915/tc: Assume a TC port is legacy if VBT says the port has HDMI

2023-03-16 Thread Imre Deak
Since an HDMI output can only be enabled in legacy mode on TC ports,
assume that VBT is wrong and the port is legacy if VBT says the port is
non-legacy and has HDMI.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_ddi.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index c531fee888a49..e79da640759c3 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -4494,6 +4494,13 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, 
enum port port)
!intel_bios_encoder_supports_typec_usb(devdata) &&
!intel_bios_encoder_supports_tbt(devdata);
 
+   if (!is_legacy && init_hdmi) {
+   drm_dbg_kms(_priv->drm,
+   "VBT says port %c is non-legacy TC and has 
HDMI, assume it's legacy TC\n",
+   port_name(port));
+   is_legacy = true;
+   }
+
intel_tc_port_init(dig_port, is_legacy);
 
encoder->update_prepare = intel_ddi_update_prepare;
-- 
2.37.1



[Intel-gfx] [PATCH 08/14] drm/i915/tc: Fix TC mode for a legacy port if the PHY is not ready

2023-03-16 Thread Imre Deak
A legacy TC port can't be switched to TBT mode, even if the PHY
initialization wasn't ready yet for some reason, so prevent this.

This shouldn't normally happen as the driver waits for the IOM/TCSS
PHY initialization during driver loading and system resume.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_tc.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
b/drivers/gpu/drm/i915/display/intel_tc.c
index e39c8a870df06..f66129494cc40 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -482,7 +482,8 @@ static void icl_tc_phy_connect(struct intel_digital_port 
*dig_port,
u32 live_status_mask;
int max_lanes;
 
-   if (!tc_phy_status_complete(dig_port)) {
+   if (!tc_phy_status_complete(dig_port) &&
+   !drm_WARN_ON(>drm, dig_port->tc_legacy_port)) {
drm_dbg_kms(>drm, "Port %s: PHY not ready\n",
dig_port->tc_port_name);
goto out_set_tbt_alt_mode;
-- 
2.37.1



[Intel-gfx] [PATCH 07/14] drm/i915/tc: Fix target TC mode for a disconnected legacy port

2023-03-16 Thread Imre Deak
Atm, the target TC mode - which the PHY should be switched to at any
point it's used - is TBT in case there is no sink connected. However
legacy ports are only used in the legacy mode regardless of the sink
connected state. Fix the mode returned by
intel_tc_port_get_target_mode() accordingly.

Despite of the above issue, the PHY got disconnected as expected in
response to a sink disconnect event, causing only a redundant
PHY disconnect->reconnect sequence whenever the port was used.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_tc.c | 14 +++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
b/drivers/gpu/drm/i915/display/intel_tc.c
index 002e142cc746f..e39c8a870df06 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -635,15 +635,23 @@ intel_tc_port_get_current_mode(struct intel_digital_port 
*dig_port)
return mode;
 }
 
+static enum tc_port_mode default_tc_mode(struct intel_digital_port *dig_port)
+{
+   if (dig_port->tc_legacy_port)
+   return TC_PORT_LEGACY;
+
+   return TC_PORT_TBT_ALT;
+}
+
 static enum tc_port_mode
-hpd_mask_to_target_mode(u32 live_status_mask)
+hpd_mask_to_target_mode(struct intel_digital_port *dig_port, u32 
live_status_mask)
 {
enum tc_port_mode mode = hpd_mask_to_tc_mode(live_status_mask);
 
if (mode != TC_PORT_DISCONNECTED)
return mode;
 
-   return TC_PORT_TBT_ALT;
+   return default_tc_mode(dig_port);
 }
 
 static enum tc_port_mode
@@ -651,7 +659,7 @@ intel_tc_port_get_target_mode(struct intel_digital_port 
*dig_port)
 {
u32 live_status_mask = tc_port_live_status_mask(dig_port);
 
-   return hpd_mask_to_target_mode(live_status_mask);
+   return hpd_mask_to_target_mode(dig_port, live_status_mask);
 }
 
 static void intel_tc_port_reset_mode(struct intel_digital_port *dig_port,
-- 
2.37.1



[Intel-gfx] [PATCH 05/14] drm/i915/tc: Wait for IOM/FW PHY initialization of legacy TC ports

2023-03-16 Thread Imre Deak
During boot-up/system resume, the TC PHY on legacy ports will be
initialized by the IOM/TCSS firmware regardless of a sink being
connected or not (as opposed to DP-alt/TBT ports, which the FW only
inits once a sink is connected).

Wait for the above initialization to complete during HW readout, so that
connecting the PHY later will already see the expected PHY ready state.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_tc.c | 17 +
 1 file changed, 17 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
b/drivers/gpu/drm/i915/display/intel_tc.c
index e8cf3b506fb7f..2116c82831a53 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -582,6 +582,15 @@ static bool icl_tc_phy_is_connected(struct 
intel_digital_port *dig_port)
   dig_port->tc_mode == TC_PORT_LEGACY;
 }
 
+static void tc_phy_wait_for_ready(struct intel_digital_port *dig_port)
+{
+   struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+
+   if (wait_for(tc_phy_status_complete(dig_port), 100))
+   drm_err(>drm, "Port %s: timeout waiting for PHY ready\n",
+   dig_port->tc_port_name);
+}
+
 static enum tc_port_mode
 intel_tc_port_get_current_mode(struct intel_digital_port *dig_port)
 {
@@ -589,6 +598,14 @@ intel_tc_port_get_current_mode(struct intel_digital_port 
*dig_port)
u32 live_status_mask = tc_port_live_status_mask(dig_port);
enum tc_port_mode mode;
 
+   /*
+* For legacy ports the IOM firmware initializes the PHY during boot-up
+* and system resume whether or not a sink is connected. Wait here for
+* the initialization to get ready.
+*/
+   if (dig_port->tc_legacy_port)
+   tc_phy_wait_for_ready(dig_port);
+
if (!tc_phy_is_owned(dig_port) ||
drm_WARN_ON(>drm, !tc_phy_status_complete(dig_port)))
return TC_PORT_TBT_ALT;
-- 
2.37.1



[Intel-gfx] [PATCH 06/14] drm/i915/tc: Factor out helpers converting HPD mask to TC mode

2023-03-16 Thread Imre Deak
Factor out helpers used later in the patchset to convert an HPD
status mask to TC mode or target TC mode.

No functional changes.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_tc.c | 44 ++---
 1 file changed, 33 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
b/drivers/gpu/drm/i915/display/intel_tc.c
index 2116c82831a53..002e142cc746f 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -591,11 +591,28 @@ static void tc_phy_wait_for_ready(struct 
intel_digital_port *dig_port)
dig_port->tc_port_name);
 }
 
+static enum tc_port_mode
+hpd_mask_to_tc_mode(u32 live_status_mask)
+{
+   if (live_status_mask)
+   return fls(live_status_mask) - 1;
+
+   return TC_PORT_DISCONNECTED;
+}
+
+static enum tc_port_mode
+tc_phy_hpd_live_mode(struct intel_digital_port *dig_port)
+{
+   u32 live_status_mask = tc_port_live_status_mask(dig_port);
+
+   return hpd_mask_to_tc_mode(live_status_mask);
+}
+
 static enum tc_port_mode
 intel_tc_port_get_current_mode(struct intel_digital_port *dig_port)
 {
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
-   u32 live_status_mask = tc_port_live_status_mask(dig_port);
+   enum tc_port_mode live_mode = tc_phy_hpd_live_mode(dig_port);
enum tc_port_mode mode;
 
/*
@@ -611,27 +628,32 @@ intel_tc_port_get_current_mode(struct intel_digital_port 
*dig_port)
return TC_PORT_TBT_ALT;
 
mode = dig_port->tc_legacy_port ? TC_PORT_LEGACY : TC_PORT_DP_ALT;
-   if (live_status_mask) {
-   enum tc_port_mode live_mode = fls(live_status_mask) - 1;
-
-   if (!drm_WARN_ON(>drm, live_mode == TC_PORT_TBT_ALT))
-   mode = live_mode;
-   }
+   if (live_mode != TC_PORT_DISCONNECTED &&
+   !drm_WARN_ON(>drm, live_mode == TC_PORT_TBT_ALT))
+   mode = live_mode;
 
return mode;
 }
 
 static enum tc_port_mode
-intel_tc_port_get_target_mode(struct intel_digital_port *dig_port)
+hpd_mask_to_target_mode(u32 live_status_mask)
 {
-   u32 live_status_mask = tc_port_live_status_mask(dig_port);
+   enum tc_port_mode mode = hpd_mask_to_tc_mode(live_status_mask);
 
-   if (live_status_mask)
-   return fls(live_status_mask) - 1;
+   if (mode != TC_PORT_DISCONNECTED)
+   return mode;
 
return TC_PORT_TBT_ALT;
 }
 
+static enum tc_port_mode
+intel_tc_port_get_target_mode(struct intel_digital_port *dig_port)
+{
+   u32 live_status_mask = tc_port_live_status_mask(dig_port);
+
+   return hpd_mask_to_target_mode(live_status_mask);
+}
+
 static void intel_tc_port_reset_mode(struct intel_digital_port *dig_port,
 int required_lanes, bool force_disconnect)
 {
-- 
2.37.1



[Intel-gfx] [PATCH 01/14] drm/i915/tc: Abort DP AUX transfer on a disconnected TC port

2023-03-16 Thread Imre Deak
On TC ports the 4ms AUX timeout combined with the 5 * 32 retry
attempts during DPCD accesses adds a 640ms delay to each access if the
sink is disconnected. This in turn slows down a modeset during which the
sink is disconnected (for instance a disabling modeset).

Prevent the above delay by aborting AUX transfers on a TC port with a
disconnected sink.

The DP 1.4a link CTS (4.2.1.5 Source Device Inactive HPD / Inactive AUX
Test") also requires not to initiate AUX transfers on disconnected DP
ports in general, however this patch doesn't change the behavior on
non-TC ports, leaving that for a follow-up.

Reported-and-tested-by: Chris Chiu 
Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/8279
Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_dp_aux.c | 15 +--
 drivers/gpu/drm/i915/display/intel_tc.c | 15 +++
 drivers/gpu/drm/i915/display/intel_tc.h |  1 +
 3 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.c 
b/drivers/gpu/drm/i915/display/intel_dp_aux.c
index 96967e21c94c2..eb07dc5d87099 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_aux.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux.c
@@ -205,8 +205,19 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
for (i = 0; i < ARRAY_SIZE(ch_data); i++)
ch_data[i] = intel_dp->aux_ch_data_reg(intel_dp, i);
 
-   if (is_tc_port)
+   if (is_tc_port) {
intel_tc_port_lock(dig_port);
+   /*
+* Abort transfers on a disconnected port as required by
+* DP 1.4a link CTS 4.2.1.5, also avoiding the long AUX
+* timeouts that would otherwise happen.
+* TODO: abort the transfer on non-TC ports as well.
+*/
+   if (!intel_tc_port_connected_locked(_port->base)) {
+   ret = -ENXIO;
+   goto out_unlock;
+   }
+   }
 
aux_domain = intel_aux_power_domain(dig_port);
 
@@ -367,7 +378,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
 
intel_pps_unlock(intel_dp, pps_wakeref);
intel_display_power_put_async(i915, aux_domain, aux_wakeref);
-
+out_unlock:
if (is_tc_port)
intel_tc_port_unlock(dig_port);
 
diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
b/drivers/gpu/drm/i915/display/intel_tc.c
index f45328712bff1..050f998284592 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -768,16 +768,23 @@ void intel_tc_port_sanitize_mode(struct 
intel_digital_port *dig_port)
  * connected ports are usable, and avoids exposing to the users objects they
  * can't really use.
  */
+bool intel_tc_port_connected_locked(struct intel_encoder *encoder)
+{
+   struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+   struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+
+   drm_WARN_ON(>drm, !intel_tc_port_ref_held(dig_port));
+
+   return tc_port_live_status_mask(dig_port) & BIT(dig_port->tc_mode);
+}
+
 bool intel_tc_port_connected(struct intel_encoder *encoder)
 {
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
bool is_connected;
 
intel_tc_port_lock(dig_port);
-
-   is_connected = tc_port_live_status_mask(dig_port) &
-  BIT(dig_port->tc_mode);
-
+   is_connected = intel_tc_port_connected_locked(encoder);
intel_tc_port_unlock(dig_port);
 
return is_connected;
diff --git a/drivers/gpu/drm/i915/display/intel_tc.h 
b/drivers/gpu/drm/i915/display/intel_tc.h
index d54082e2d5e8d..93813056043a5 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.h
+++ b/drivers/gpu/drm/i915/display/intel_tc.h
@@ -17,6 +17,7 @@ bool intel_tc_port_in_dp_alt_mode(struct intel_digital_port 
*dig_port);
 bool intel_tc_port_in_legacy_mode(struct intel_digital_port *dig_port);
 
 bool intel_tc_port_connected(struct intel_encoder *encoder);
+bool intel_tc_port_connected_locked(struct intel_encoder *encoder);
 
 u32 intel_tc_port_get_lane_mask(struct intel_digital_port *dig_port);
 u32 intel_tc_port_get_pin_assignment_mask(struct intel_digital_port *dig_port);
-- 
2.37.1



[Intel-gfx] [PATCH 02/14] drm/i915/tc: Fix TC port link ref init for DP MST during HW readout

2023-03-16 Thread Imre Deak
An enabled TC MST port holds one TC port link reference, regardless of
the number of enabled streams on it, but the TC port HW readout takes
one reference for each active MST stream.

Fix the HW readout, taking only one reference for MST ports.

This didn't cause an actual problem, since the encoder HW readout doesn't
yet support reading out the MST HW state.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_tc.c | 20 +++-
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
b/drivers/gpu/drm/i915/display/intel_tc.c
index 050f998284592..0b6fe96ab4759 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -660,11 +660,14 @@ static void intel_tc_port_update_mode(struct 
intel_digital_port *dig_port,
tc_cold_unblock(dig_port, domain, wref);
 }
 
-static void
-intel_tc_port_link_init_refcount(struct intel_digital_port *dig_port,
-int refcount)
+static void __intel_tc_port_get_link(struct intel_digital_port *dig_port)
 {
-   dig_port->tc_link_refcount = refcount;
+   dig_port->tc_link_refcount++;
+}
+
+static void __intel_tc_port_put_link(struct intel_digital_port *dig_port)
+{
+   dig_port->tc_link_refcount--;
 }
 
 /**
@@ -690,7 +693,7 @@ void intel_tc_port_init_mode(struct intel_digital_port 
*dig_port)
 
dig_port->tc_mode = intel_tc_port_get_current_mode(dig_port);
/* Prevent changing dig_port->tc_mode until 
intel_tc_port_sanitize_mode() is called. */
-   intel_tc_port_link_init_refcount(dig_port, 1);
+   __intel_tc_port_get_link(dig_port);
dig_port->tc_lock_wakeref = tc_cold_block(dig_port, 
_port->tc_lock_power_domain);
 
tc_cold_unblock(dig_port, domain, tc_cold_wref);
@@ -726,8 +729,6 @@ void intel_tc_port_sanitize_mode(struct intel_digital_port 
*dig_port)
active_links = to_intel_crtc(encoder->base.crtc)->active;
 
drm_WARN_ON(>drm, dig_port->tc_link_refcount != 1);
-   intel_tc_port_link_init_refcount(dig_port, active_links);
-
if (active_links) {
if (!icl_tc_phy_is_connected(dig_port))
drm_dbg_kms(>drm,
@@ -746,6 +747,7 @@ void intel_tc_port_sanitize_mode(struct intel_digital_port 
*dig_port)
dig_port->tc_port_name,
tc_port_mode_name(dig_port->tc_mode));
icl_tc_phy_disconnect(dig_port);
+   __intel_tc_port_put_link(dig_port);
 
tc_cold_unblock(dig_port, dig_port->tc_lock_power_domain,
fetch_and_zero(_port->tc_lock_wakeref));
@@ -864,14 +866,14 @@ void intel_tc_port_get_link(struct intel_digital_port 
*dig_port,
int required_lanes)
 {
__intel_tc_port_lock(dig_port, required_lanes);
-   dig_port->tc_link_refcount++;
+   __intel_tc_port_get_link(dig_port);
intel_tc_port_unlock(dig_port);
 }
 
 void intel_tc_port_put_link(struct intel_digital_port *dig_port)
 {
intel_tc_port_lock(dig_port);
-   --dig_port->tc_link_refcount;
+   __intel_tc_port_put_link(dig_port);
intel_tc_port_unlock(dig_port);
 
/*
-- 
2.37.1



[Intel-gfx] [PATCH 03/14] drm/i915/tc: Fix the ICL PHY ownership check in TC-cold state

2023-03-16 Thread Imre Deak
The commit renaming icl_tc_phy_is_in_safe_mode() to
icl_tc_phy_take_ownership() didn't flip the function's return value
accordingly, fix this up.

This didn't cause an actual problem besides state check errors, since
the function is only used during HW readout.

Cc: José Roberto de Souza 
Fixes: f53979d68a77 ("drm/i915/display/tc: Rename safe_mode functions 
ownership")
Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_tc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
b/drivers/gpu/drm/i915/display/intel_tc.c
index 0b6fe96ab4759..fd826b9657e93 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -418,9 +418,9 @@ static bool icl_tc_phy_is_owned(struct intel_digital_port 
*dig_port)
val = intel_de_read(i915, PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia));
if (val == 0x) {
drm_dbg_kms(>drm,
-   "Port %s: PHY in TCCOLD, assume safe mode\n",
+   "Port %s: PHY in TCCOLD, assume not owned\n",
dig_port->tc_port_name);
-   return true;
+   return false;
}
 
return val & DP_PHY_MODE_STATUS_NOT_SAFE(dig_port->tc_phy_fia_idx);
-- 
2.37.1



[Intel-gfx] [PATCH 04/14] drm/i915/tc: Fix system resume MST mode restore for DP-alt sinks

2023-03-16 Thread Imre Deak
At least restoring the MST topology during system resume needs to use
AUX before the display HW readout->sanitization sequence is complete,
but on TC ports the PHY may be in the wrong mode for this, resulting in
the AUX transfers to fail.

The initial TC port mode is kept fixed as BIOS left it for the above HW
readout sequence (to prevent changing the mode on an enabled port).  If
the port is disabled this initial mode is TBT - as in any case the PHY
ownership is not held - even if a DP-alt sink is connected. Thus, the
AUX transfers during this time will use TBT mode instead of the expected
DP-alt mode and so time out.

Fix the above by connecting the PHY during port initialization if the
port is disabled, which will switch to the expected mode (DP-alt in the
above case).

As the encoder/pipe HW state isn't read-out yet at this point, check if
the port is enabled based on the DDI_BUF enabled flag. Save the read-out
initial mode, so intel_tc_port_sanitize_mode() can check this wrt. the
read-out encoder HW state.

Signed-off-by: Imre Deak 
---
 .../drm/i915/display/intel_display_types.h|  1 +
 drivers/gpu/drm/i915/display/intel_tc.c   | 48 +--
 2 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index c32bfba06ca1f..06bbfd426ac70 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1783,6 +1783,7 @@ struct intel_digital_port {
bool tc_legacy_port:1;
char tc_port_name[8];
enum tc_port_mode tc_mode;
+   enum tc_port_mode tc_init_mode;
enum phy_fia tc_phy_fia;
u8 tc_phy_fia_idx;
 
diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
b/drivers/gpu/drm/i915/display/intel_tc.c
index fd826b9657e93..e8cf3b506fb7f 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -118,6 +118,24 @@ assert_tc_cold_blocked(struct intel_digital_port *dig_port)
drm_WARN_ON(>drm, !enabled);
 }
 
+static enum intel_display_power_domain
+tc_port_power_domain(struct intel_digital_port *dig_port)
+{
+   struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+   enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port);
+
+   return POWER_DOMAIN_PORT_DDI_LANES_TC1 + tc_port - TC_PORT_1;
+}
+
+static void
+assert_tc_port_power_enabled(struct intel_digital_port *dig_port)
+{
+   struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+
+   drm_WARN_ON(>drm,
+   !intel_display_power_is_enabled(i915, 
tc_port_power_domain(dig_port)));
+}
+
 u32 intel_tc_port_get_lane_mask(struct intel_digital_port *dig_port)
 {
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
@@ -670,6 +688,16 @@ static void __intel_tc_port_put_link(struct 
intel_digital_port *dig_port)
dig_port->tc_link_refcount--;
 }
 
+static bool tc_port_is_enabled(struct intel_digital_port *dig_port)
+{
+   struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+
+   assert_tc_port_power_enabled(dig_port);
+
+   return intel_de_read(i915, DDI_BUF_CTL(dig_port->base.port)) &
+  DDI_BUF_CTL_ENABLE;
+}
+
 /**
  * intel_tc_port_init_mode: Read out HW state and init the given port's TypeC 
mode
  * @dig_port: digital port
@@ -692,9 +720,23 @@ void intel_tc_port_init_mode(struct intel_digital_port 
*dig_port)
tc_cold_wref = tc_cold_block(dig_port, );
 
dig_port->tc_mode = intel_tc_port_get_current_mode(dig_port);
+   /*
+* Save the initial mode for the state check in
+* intel_tc_port_sanitize_mode().
+*/
+   dig_port->tc_init_mode = dig_port->tc_mode;
+   dig_port->tc_lock_wakeref = tc_cold_block(dig_port, 
_port->tc_lock_power_domain);
+
+   /*
+* The PHY needs to be connected for AUX to work during HW readout and
+* MST topology resume, but the PHY mode can only be changed if the
+* port is disabled.
+*/
+   if (!tc_port_is_enabled(dig_port))
+   intel_tc_port_update_mode(dig_port, 1, false);
+
/* Prevent changing dig_port->tc_mode until 
intel_tc_port_sanitize_mode() is called. */
__intel_tc_port_get_link(dig_port);
-   dig_port->tc_lock_wakeref = tc_cold_block(dig_port, 
_port->tc_lock_power_domain);
 
tc_cold_unblock(dig_port, domain, tc_cold_wref);
 
@@ -741,11 +783,11 @@ void intel_tc_port_sanitize_mode(struct 
intel_digital_port *dig_port)
 * we'll just switch to disconnected mode from it here without
 * a note.
 */
-   if (dig_port->tc_mode != TC_PORT_TBT_ALT)
+   if (dig_port->tc_init_mode != TC_PORT_TBT_ALT)
drm_dbg_kms(>drm,
"Port %s: PHY left in %s mode on disabled 
port, 

[Intel-gfx] [PATCH 00/14] drm/i915/tc: Fix a few TypeC / MST issues

2023-03-16 Thread Imre Deak
This patchset fixes a few issues on TypeC ports, related to the legacy
port handling, HW state readout/verification. It also fixes an issue on
TC port/MST outputs during system suspend/resume, where the modeset
restoring the pre-suspend state fails atm.

Tested on ICL, TGL, ADLP.

Imre Deak (14):
  drm/i915/tc: Abort DP AUX transfer on a disconnected TC port
  drm/i915/tc: Fix TC port link ref init for DP MST during HW readout
  drm/i915/tc: Fix the ICL PHY ownership check in TC-cold state
  drm/i915/tc: Fix system resume MST mode restore for DP-alt sinks
  drm/i915/tc: Wait for IOM/FW PHY initialization of legacy TC ports
  drm/i915/tc: Factor out helpers converting HPD mask to TC mode
  drm/i915/tc: Fix target TC mode for a disconnected legacy port
  drm/i915/tc: Fix TC mode for a legacy port if the PHY is not ready
  drm/i915/tc: Fix initial TC mode on disabled legacy ports
  drm/i915/tc: Make the TC mode readout consistent in all PHY states
  drm/i915/tc: Assume a TC port is legacy if VBT says the port has HDMI
  drm/i915: Add encoder hook to get the PLL type used by TC ports
  drm/i915/tc: Factor out a function querying active links on a TC port
  drm/i915/tc: Check the PLL type used by an enabled TC port

 drivers/gpu/drm/i915/display/intel_ddi.c  |  44 ++-
 drivers/gpu/drm/i915/display/intel_ddi.h  |   3 +
 .../drm/i915/display/intel_display_types.h|   6 +
 drivers/gpu/drm/i915/display/intel_dp_aux.c   |  15 +-
 drivers/gpu/drm/i915/display/intel_tc.c   | 319 ++
 drivers/gpu/drm/i915/display/intel_tc.h   |   1 +
 6 files changed, 320 insertions(+), 68 deletions(-)

-- 
2.37.1



[Intel-gfx] [PATCH 3/7] drm/i915/aux: split out DP AUX regs to a separate file

2023-03-16 Thread Jani Nikula
Clean up i915_reg.h by splitting out DP AUX regs to
display/intel_dp_aux_regs.h.

Signed-off-by: Jani Nikula 
---
 .../i915/display/intel_display_power_well.c   |  1 +
 drivers/gpu/drm/i915/display/intel_dp_aux.c   |  1 +
 .../gpu/drm/i915/display/intel_dp_aux_regs.h  | 84 +++
 drivers/gpu/drm/i915/gvt/edid.c   |  1 +
 drivers/gpu/drm/i915/gvt/handlers.c   |  1 +
 drivers/gpu/drm/i915/i915_reg.h   | 73 
 drivers/gpu/drm/i915/intel_gvt_mmio_table.c   |  1 +
 7 files changed, 89 insertions(+), 73 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_dp_aux_regs.h

diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c 
b/drivers/gpu/drm/i915/display/intel_display_power_well.c
index 1676df1dc066..9accc24db7f7 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power_well.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c
@@ -15,6 +15,7 @@
 #include "intel_dkl_phy.h"
 #include "intel_dkl_phy_regs.h"
 #include "intel_dmc.h"
+#include "intel_dp_aux_regs.h"
 #include "intel_dpio_phy.h"
 #include "intel_dpll.h"
 #include "intel_hotplug.h"
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.c 
b/drivers/gpu/drm/i915/display/intel_dp_aux.c
index 96967e21c94c..83317115b51b 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_aux.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux.c
@@ -10,6 +10,7 @@
 #include "intel_de.h"
 #include "intel_display_types.h"
 #include "intel_dp_aux.h"
+#include "intel_dp_aux_regs.h"
 #include "intel_pps.h"
 #include "intel_tc.h"
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_regs.h 
b/drivers/gpu/drm/i915/display/intel_dp_aux_regs.h
new file mode 100644
index ..5702f318d537
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux_regs.h
@@ -0,0 +1,84 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef __INTEL_DP_AUX_REGS_H__
+#define __INTEL_DP_AUX_REGS_H__
+
+#include "intel_display_reg_defs.h"
+
+/*
+ * The aux channel provides a way to talk to the signal sink for DDC etc. Max
+ * packet size supported is 20 bytes in each direction, hence the 5 fixed data
+ * registers
+ */
+#define _DPA_AUX_CH_CTL(DISPLAY_MMIO_BASE(dev_priv) + 0x64010)
+#define _DPA_AUX_CH_DATA1  (DISPLAY_MMIO_BASE(dev_priv) + 0x64014)
+
+#define _DPB_AUX_CH_CTL(DISPLAY_MMIO_BASE(dev_priv) + 0x64110)
+#define _DPB_AUX_CH_DATA1  (DISPLAY_MMIO_BASE(dev_priv) + 0x64114)
+
+#define DP_AUX_CH_CTL(aux_ch)  _MMIO_PORT(aux_ch, _DPA_AUX_CH_CTL, 
_DPB_AUX_CH_CTL)
+#define DP_AUX_CH_DATA(aux_ch, i)  _MMIO(_PORT(aux_ch, _DPA_AUX_CH_DATA1, 
_DPB_AUX_CH_DATA1) + (i) * 4) /* 5 registers */
+
+#define _XELPDP_USBC1_AUX_CH_CTL   0x16F210
+#define _XELPDP_USBC2_AUX_CH_CTL   0x16F410
+#define _XELPDP_USBC3_AUX_CH_CTL   0x16F610
+#define _XELPDP_USBC4_AUX_CH_CTL   0x16F810
+
+#define XELPDP_DP_AUX_CH_CTL(aux_ch)   _MMIO(_PICK(aux_ch, \
+  _DPA_AUX_CH_CTL, \
+  _DPB_AUX_CH_CTL, \
+  0, /* port/aux_ch C is 
non-existent */ \
+  
_XELPDP_USBC1_AUX_CH_CTL, \
+  
_XELPDP_USBC2_AUX_CH_CTL, \
+  
_XELPDP_USBC3_AUX_CH_CTL, \
+  
_XELPDP_USBC4_AUX_CH_CTL))
+
+#define _XELPDP_USBC1_AUX_CH_DATA1  0x16F214
+#define _XELPDP_USBC2_AUX_CH_DATA1  0x16F414
+#define _XELPDP_USBC3_AUX_CH_DATA1  0x16F614
+#define _XELPDP_USBC4_AUX_CH_DATA1  0x16F814
+
+#define XELPDP_DP_AUX_CH_DATA(aux_ch, i)   _MMIO(_PICK(aux_ch, \
+  _DPA_AUX_CH_DATA1, \
+  _DPB_AUX_CH_DATA1, \
+  0, /* port/aux_ch C is 
non-existent */ \
+  
_XELPDP_USBC1_AUX_CH_DATA1, \
+  
_XELPDP_USBC2_AUX_CH_DATA1, \
+  
_XELPDP_USBC3_AUX_CH_DATA1, \
+  
_XELPDP_USBC4_AUX_CH_DATA1) + (i) * 4)
+
+#define   DP_AUX_CH_CTL_SEND_BUSY  (1 << 31)
+#define   DP_AUX_CH_CTL_DONE   (1 << 30)
+#define   DP_AUX_CH_CTL_INTERRUPT  (1 << 29)
+#define   DP_AUX_CH_CTL_TIME_OUT_ERROR (1 << 28)
+#define   DP_AUX_CH_CTL_TIME_OUT_400us (0 << 26)
+#define   DP_AUX_CH_CTL_TIME_OUT_600us (1 << 26)
+#define   DP_AUX_CH_CTL_TIME_OUT_800us (2 << 26)
+#define   DP_AUX_CH_CTL_TIME_OUT_MAX   (3 << 26) /* Varies per platform */
+#define   DP_AUX_CH_CTL_TIME_OUT_MASK  (3 << 26)
+#define   

[Intel-gfx] [PATCH 2/7] drm/i915/tv: split out TV regs to a separate file

2023-03-16 Thread Jani Nikula
Clean up i915_reg.h by splitting out TV regs to display/intel_tv_regs.h.

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/i915/display/intel_tv.c  |   3 +-
 drivers/gpu/drm/i915/display/intel_tv_regs.h | 490 +++
 drivers/gpu/drm/i915/i915_reg.h  | 479 --
 3 files changed, 492 insertions(+), 480 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_tv_regs.h

diff --git a/drivers/gpu/drm/i915/display/intel_tv.c 
b/drivers/gpu/drm/i915/display/intel_tv.c
index 3b5ff84dc615..557ec5b62afa 100644
--- a/drivers/gpu/drm/i915/display/intel_tv.c
+++ b/drivers/gpu/drm/i915/display/intel_tv.c
@@ -35,8 +35,8 @@
 #include 
 
 #include "i915_drv.h"
-#include "i915_reg.h"
 #include "i915_irq.h"
+#include "i915_reg.h"
 #include "intel_connector.h"
 #include "intel_crtc.h"
 #include "intel_de.h"
@@ -44,6 +44,7 @@
 #include "intel_dpll.h"
 #include "intel_hotplug.h"
 #include "intel_tv.h"
+#include "intel_tv_regs.h"
 
 enum tv_margin {
TV_MARGIN_LEFT, TV_MARGIN_TOP,
diff --git a/drivers/gpu/drm/i915/display/intel_tv_regs.h 
b/drivers/gpu/drm/i915/display/intel_tv_regs.h
new file mode 100644
index ..ab25aeb3c423
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_tv_regs.h
@@ -0,0 +1,490 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef __INTEL_TV_REGS_H__
+#define __INTEL_TV_REGS_H__
+
+#include "intel_display_reg_defs.h"
+
+/* TV port control */
+#define TV_CTL _MMIO(0x68000)
+/* Enables the TV encoder */
+# define TV_ENC_ENABLE (1 << 31)
+/* Sources the TV encoder input from pipe B instead of A. */
+# define TV_ENC_PIPE_SEL_SHIFT 30
+# define TV_ENC_PIPE_SEL_MASK  (1 << 30)
+# define TV_ENC_PIPE_SEL(pipe) ((pipe) << 30)
+/* Outputs composite video (DAC A only) */
+# define TV_ENC_OUTPUT_COMPOSITE   (0 << 28)
+/* Outputs SVideo video (DAC B/C) */
+# define TV_ENC_OUTPUT_SVIDEO  (1 << 28)
+/* Outputs Component video (DAC A/B/C) */
+# define TV_ENC_OUTPUT_COMPONENT   (2 << 28)
+/* Outputs Composite and SVideo (DAC A/B/C) */
+# define TV_ENC_OUTPUT_SVIDEO_COMPOSITE(3 << 28)
+# define TV_TRILEVEL_SYNC  (1 << 21)
+/* Enables slow sync generation (945GM only) */
+# define TV_SLOW_SYNC  (1 << 20)
+/* Selects 4x oversampling for 480i and 576p */
+# define TV_OVERSAMPLE_4X  (0 << 18)
+/* Selects 2x oversampling for 720p and 1080i */
+# define TV_OVERSAMPLE_2X  (1 << 18)
+/* Selects no oversampling for 1080p */
+# define TV_OVERSAMPLE_NONE(2 << 18)
+/* Selects 8x oversampling */
+# define TV_OVERSAMPLE_8X  (3 << 18)
+# define TV_OVERSAMPLE_MASK(3 << 18)
+/* Selects progressive mode rather than interlaced */
+# define TV_PROGRESSIVE(1 << 17)
+/* Sets the colorburst to PAL mode.  Required for non-M PAL modes. */
+# define TV_PAL_BURST  (1 << 16)
+/* Field for setting delay of Y compared to C */
+# define TV_YC_SKEW_MASK   (7 << 12)
+/* Enables a fix for 480p/576p standard definition modes on the 915GM only */
+# define TV_ENC_SDP_FIX(1 << 11)
+/*
+ * Enables a fix for the 915GM only.
+ *
+ * Not sure what it does.
+ */
+# define TV_ENC_C0_FIX (1 << 10)
+/* Bits that must be preserved by software */
+# define TV_CTL_SAVE   ((1 << 11) | (3 << 9) | (7 << 6) | 0xf)
+# define TV_FUSE_STATE_MASK(3 << 4)
+/* Read-only state that reports all features enabled */
+# define TV_FUSE_STATE_ENABLED (0 << 4)
+/* Read-only state that reports that Macrovision is disabled in hardware*/
+# define TV_FUSE_STATE_NO_MACROVISION  (1 << 4)
+/* Read-only state that reports that TV-out is disabled in hardware. */
+# define TV_FUSE_STATE_DISABLED(2 << 4)
+/* Normal operation */
+# define TV_TEST_MODE_NORMAL   (0 << 0)
+/* Encoder test pattern 1 - combo pattern */
+# define TV_TEST_MODE_PATTERN_1(1 << 0)
+/* Encoder test pattern 2 - full screen vertical 75% color bars */
+# define TV_TEST_MODE_PATTERN_2(2 << 0)
+/* Encoder test pattern 3 - full screen horizontal 75% color bars */
+# define TV_TEST_MODE_PATTERN_3(3 << 0)
+/* Encoder test pattern 4 - random noise */
+# define TV_TEST_MODE_PATTERN_4(4 << 0)
+/* Encoder test pattern 5 - linear color ramps */
+# define TV_TEST_MODE_PATTERN_5(5 << 0)
+/*
+ * This test mode forces the DACs to 50% of full output.
+ *
+ * This is used for load detection in combination with TVDAC_SENSE_MASK
+ */
+# define TV_TEST_MODE_MONITOR_DETECT   (7 << 0)
+# define TV_TEST_MODE_MASK (7 << 0)
+
+#define TV_DAC _MMIO(0x68004)
+# define TV_DAC_SAVE   0x0000
+/*
+ * Reports that DAC state change logic has reported change (RO).
+ *
+ * This gets cleared when TV_DAC_STATE_EN 

[Intel-gfx] [PATCH 1/7] drm/i915/pps: split out PPS regs to a separate file

2023-03-16 Thread Jani Nikula
Clean up i915_reg.h by splitting out PPS regs to
display/intel_pps_regs.h.

Signed-off-by: Jani Nikula 
---
 .../drm/i915/display/intel_display_power.c|  1 +
 drivers/gpu/drm/i915/display/intel_dsi_vbt.c  |  1 +
 drivers/gpu/drm/i915/display/intel_lvds.c |  1 +
 drivers/gpu/drm/i915/display/intel_pps.c  |  1 +
 drivers/gpu/drm/i915/display/intel_pps_regs.h | 78 +++
 drivers/gpu/drm/i915/gvt/handlers.c   |  1 +
 drivers/gpu/drm/i915/i915_reg.h   | 67 
 7 files changed, 83 insertions(+), 67 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_pps_regs.h

diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c 
b/drivers/gpu/drm/i915/display/intel_display_power.c
index f86060195987..dedfc837b727 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power.c
@@ -19,6 +19,7 @@
 #include "intel_mchbar_regs.h"
 #include "intel_pch_refclk.h"
 #include "intel_pcode.h"
+#include "intel_pps_regs.h"
 #include "intel_snps_phy.h"
 #include "skl_watermark.h"
 #include "vlv_sideband.h"
diff --git a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c 
b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
index 2cbc1292ab38..695b0d69a4cb 100644
--- a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
+++ b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
@@ -46,6 +46,7 @@
 #include "intel_dsi.h"
 #include "intel_dsi_vbt.h"
 #include "intel_gmbus_regs.h"
+#include "intel_pps_regs.h"
 #include "vlv_dsi.h"
 #include "vlv_dsi_regs.h"
 #include "vlv_sideband.h"
diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c 
b/drivers/gpu/drm/i915/display/intel_lvds.c
index a504b3a7fbd5..0de44b3631cd 100644
--- a/drivers/gpu/drm/i915/display/intel_lvds.c
+++ b/drivers/gpu/drm/i915/display/intel_lvds.c
@@ -51,6 +51,7 @@
 #include "intel_lvds.h"
 #include "intel_lvds_regs.h"
 #include "intel_panel.h"
+#include "intel_pps_regs.h"
 
 /* Private structure for the integrated LVDS support */
 struct intel_lvds_pps {
diff --git a/drivers/gpu/drm/i915/display/intel_pps.c 
b/drivers/gpu/drm/i915/display/intel_pps.c
index 24b5b12f7732..7f9926672a6a 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.c
+++ b/drivers/gpu/drm/i915/display/intel_pps.c
@@ -15,6 +15,7 @@
 #include "intel_lvds.h"
 #include "intel_lvds_regs.h"
 #include "intel_pps.h"
+#include "intel_pps_regs.h"
 #include "intel_quirks.h"
 
 static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv,
diff --git a/drivers/gpu/drm/i915/display/intel_pps_regs.h 
b/drivers/gpu/drm/i915/display/intel_pps_regs.h
new file mode 100644
index ..60edd2a27100
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_pps_regs.h
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef __INTEL_PPS_REGS_H__
+#define __INTEL_PPS_REGS_H__
+
+#include "intel_display_reg_defs.h"
+
+/* Panel power sequencing */
+#define PPS_BASE   0x61200
+#define VLV_PPS_BASE   (VLV_DISPLAY_BASE + PPS_BASE)
+#define PCH_PPS_BASE   0xC7200
+
+#define _MMIO_PPS(pps_idx, reg)
_MMIO(dev_priv->display.pps.mmio_base - \
+ PPS_BASE + (reg) +\
+ (pps_idx) * 0x100)
+
+#define _PP_STATUS 0x61200
+#define PP_STATUS(pps_idx) _MMIO_PPS(pps_idx, _PP_STATUS)
+#define   PP_ONREG_BIT(31)
+/*
+ * Indicates that all dependencies of the panel are on:
+ *
+ * - PLL enabled
+ * - pipe enabled
+ * - LVDS/DVOB/DVOC on
+ */
+#define   PP_READY REG_BIT(30)
+#define   PP_SEQUENCE_MASK REG_GENMASK(29, 28)
+#define   PP_SEQUENCE_NONE REG_FIELD_PREP(PP_SEQUENCE_MASK, 0)
+#define   PP_SEQUENCE_POWER_UP REG_FIELD_PREP(PP_SEQUENCE_MASK, 1)
+#define   PP_SEQUENCE_POWER_DOWN   REG_FIELD_PREP(PP_SEQUENCE_MASK, 2)
+#define   PP_CYCLE_DELAY_ACTIVEREG_BIT(27)
+#define   PP_SEQUENCE_STATE_MASK   REG_GENMASK(3, 0)
+#define   PP_SEQUENCE_STATE_OFF_IDLE   REG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 
0x0)
+#define   PP_SEQUENCE_STATE_OFF_S0_1   REG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 
0x1)
+#define   PP_SEQUENCE_STATE_OFF_S0_2   REG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 
0x2)
+#define   PP_SEQUENCE_STATE_OFF_S0_3   REG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 
0x3)
+#define   PP_SEQUENCE_STATE_ON_IDLEREG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 
0x8)
+#define   PP_SEQUENCE_STATE_ON_S1_1REG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 
0x9)
+#define   PP_SEQUENCE_STATE_ON_S1_2REG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 
0xa)
+#define   PP_SEQUENCE_STATE_ON_S1_3REG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 
0xb)
+#define   PP_SEQUENCE_STATE_RESET  REG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 
0xf)
+
+#define _PP_CONTROL0x61204
+#define PP_CONTROL(pps_idx)_MMIO_PPS(pps_idx, 

[Intel-gfx] [PATCH 0/7] drm/i915/regs: split display regs by function

2023-03-16 Thread Jani Nikula
Shave off 1.2k lines from i915_reg.h.

Jani Nikula (7):
  drm/i915/pps: split out PPS regs to a separate file
  drm/i915/tv: split out TV regs to a separate file
  drm/i915/aux: split out DP AUX regs to a separate file
  drm/i915/fdi: split out FDI regs to a separate file
  drm/i915/wm: split out SKL+ watermark regs to a separate file
  drm/i915/psr: split out PSR regs to a separate file
  drm/i915/dsb: split out DSB regs to a separate file

 drivers/gpu/drm/i915/display/intel_crt.c  |1 +
 .../drm/i915/display/intel_display_debugfs.c  |1 +
 .../drm/i915/display/intel_display_power.c|2 +
 .../i915/display/intel_display_power_well.c   |1 +
 drivers/gpu/drm/i915/display/intel_dp_aux.c   |1 +
 .../gpu/drm/i915/display/intel_dp_aux_regs.h  |   84 ++
 drivers/gpu/drm/i915/display/intel_dsb.c  |1 +
 drivers/gpu/drm/i915/display/intel_dsb_regs.h |   67 +
 drivers/gpu/drm/i915/display/intel_dsi_vbt.c  |1 +
 drivers/gpu/drm/i915/display/intel_fdi.c  |1 +
 drivers/gpu/drm/i915/display/intel_fdi_regs.h |  151 ++
 drivers/gpu/drm/i915/display/intel_lvds.c |1 +
 .../gpu/drm/i915/display/intel_pch_display.c  |1 +
 drivers/gpu/drm/i915/display/intel_pps.c  |1 +
 drivers/gpu/drm/i915/display/intel_pps_regs.h |   78 ++
 drivers/gpu/drm/i915/display/intel_psr.c  |1 +
 drivers/gpu/drm/i915/display/intel_psr_regs.h |  260 
 drivers/gpu/drm/i915/display/intel_tv.c   |3 +-
 drivers/gpu/drm/i915/display/intel_tv_regs.h  |  490 +++
 drivers/gpu/drm/i915/display/skl_watermark.c  |1 +
 .../gpu/drm/i915/display/skl_watermark_regs.h |  165 +++
 drivers/gpu/drm/i915/gvt/edid.c   |1 +
 drivers/gpu/drm/i915/gvt/handlers.c   |5 +
 drivers/gpu/drm/i915/i915_irq.c   |2 +
 drivers/gpu/drm/i915/i915_reg.h   | 1219 -
 drivers/gpu/drm/i915/intel_gvt_mmio_table.c   |4 +
 26 files changed, 1323 insertions(+), 1220 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_dp_aux_regs.h
 create mode 100644 drivers/gpu/drm/i915/display/intel_dsb_regs.h
 create mode 100644 drivers/gpu/drm/i915/display/intel_fdi_regs.h
 create mode 100644 drivers/gpu/drm/i915/display/intel_pps_regs.h
 create mode 100644 drivers/gpu/drm/i915/display/intel_psr_regs.h
 create mode 100644 drivers/gpu/drm/i915/display/intel_tv_regs.h
 create mode 100644 drivers/gpu/drm/i915/display/skl_watermark_regs.h

-- 
2.39.2



Re: [Intel-gfx] [PATCH v6 12/24] vfio/pci: Allow passing zero-length fd array in VFIO_DEVICE_PCI_HOT_RESET

2023-03-16 Thread Liu, Yi L
> From: Nicolin Chen 
> Sent: Thursday, March 16, 2023 2:49 PM
> 
> On Thu, Mar 16, 2023 at 06:28:28AM +, Liu, Yi L wrote:
> 
> > > Anyway let's not wait here. Send your v7 and we can have more
> > > focused discussion in your split series about hot reset.
> >
> > Sure. Once Nicolin's patch is updated, I can send v7 with the hot
> > reset series as well.
> 
> I've updated three commits and pushed here:
> https://github.com/nicolinc/iommufd/commits/wip/iommufd_nesting-
> 03152023
> 
> Please pull the following commit to the emulated series:
>   "iommufd: Create access in vfio_iommufd_emulated_bind()"
> 
> https://github.com/nicolinc/iommufd/commit/6467e332584de62d1c4d5daa
> b404a8c8d5a90a2d
> 
> Please pull the following commit to the cdev series or a place
> that you feel it'd be better -- it's required by the change of
> adding vfio_iommufd_emulated_detach_ioas():
>   "iommufd/device: Add iommufd_access_detach() API"
> 
> https://github.com/nicolinc/iommufd/commit/86346b5d06100640037cbb4a
> 14bd249476072dec

Thanks, I've taken them. v7 was sent out.

> The other one adding replace() will go with the replace series.
> 
> And regarding the new baseline for the replace series and the
> nesting series, it'd be nicer to have another one git-merging
> your cdev v7 branch on top of Jason's iommufd_hwpt branch. We
> could wait for him updating to 6.3-rc2, if that's necessary.

Yes. I cherry-pick his iommufd_hwpt to 6.3-rc2 and then try a
merge and then cherry-pick the replace and nesting series from
your above branch. Though the order between cdev and
iommufd_hwpt not perfect, we may use it as a wip baseline
when we try to address the comments w.r.t. nesting and
replace series.

https://github.com/yiliu1765/iommufd/tree/wip/iommufd_nesting-03162023

Regards,
Yi Liu


[Intel-gfx] [PULL] drm-intel-gt-next

2023-03-16 Thread Joonas Lahtinen
Hi Dave & Daniel,

Here's the first batch of drm-intel-gt-next towards v6.4.

There is an important performance monitoring fix (#6333), more
resiliency to pcode load delay and avoiding caching problems on LLC
systems for ring buffers. Stolen memory probing fix and a
missing register whitelisting for Gen12. Fix for potential OOB access
on SSEU max_subslices array.

Improvements to error capture on GuC, corrections to workarounds
power domains across Gen11/Gen12 with subject to runtime PM.

Then the regular bunch of smaller tweaks, restructuring and cleanups
not to forget documentation, sparse and selftest improvements.

Regards, Joonas

***

drm-intel-gt-next-2023-03-16:

Driver Changes:

- Fix issue #6333: "list_add corruption" and full system lockup from
  performance monitoring (Janusz)
- Give the punit time to settle before fatally failing (Aravind, Chris)
- Don't use stolen memory or BAR for ring buffers on LLC platforms (John)
- Add missing ecodes and correct timeline seqno on GuC error captures (John)
- Make sure DSM size has correct 1MiB granularity on Gen12+ (Nirmoy,
  Lucas)
- Fix potential SSEU max_subslices array-index-out-of-bounds access on Gen11 
(Andrea)
- Whitelist COMMON_SLICE_CHICKEN3 for UMD access on Gen12+ (Matt R.)
- Apply Wa_1408615072/Wa_1407596294 correctly on Gen11 (Matt R)
- Apply LNCF/LBCF workarounds correctly on XeHP SDV/PVC/DG2 (Matt R)
- Implement Wa_1606376872 for Xe_LP (Gustavo)
- Consider GSI offset when doing MCR lookups on Meteorlake+ (Matt R.)
- Add engine TLB invalidation for Meteorlake (Matt R.)
- Fix GSC Driver-FLR completion on Meteorlake (Alan)
- Fix GSC races on driver load/unload on Meteorlake+ (Daniele)
- Disable MC6 for MTL A step (Badal)

- Consolidate TLB invalidation flow (Tvrtko)
- Improve debug GuC/HuC debug messages (Michal Wa., John)
- Move fd_install after last use of fence (Rob)
- Initialize the obj flags for shmem objects (Aravind)
- Fix missing debug object activation (Nirmoy)
- Probe lmem before the stolen portion (Matt A)
- Improve clean up of GuC busyness stats worker (John)
- Fix missing return code checks in GuC submission init (John)
- Annotate two more workaround/tuning registers as MCR on PVC (Matt R)
- Fix GEN8_MISCCPCTL definition and remove unused INF_UNIT_LEVEL_CLKGATE (Lucas)
- Use sysfs_emit() and sysfs_emit_at() (Nirmoy)
- Make kobj_type structures constant (Thomas W.)
- make kobj attributes const on gt/ (Jani)
- Remove the unused virtualized start hack on buddy allocator (Matt A)
- Remove redundant check for DG1 (Lucas)
- Move DG2 tuning to the right function (Lucas)
- Rename dev_priv to i915 for private data naming consistency in gt/ (Andi)
- Remove unnecessary whitelisting of CS_CTX_TIMESTAMP on Xe_HP platforms (Matt 
R.)
-

- Escape wildcard in method names in kerneldoc (Bagas)
- Selftest improvements (Chris, Jonathan, Tvrtko, Anshuman, Tejas)
- Fix sparse warnings (Jani)
The following changes since commit 003e11ed2ef4af01b808f0f193eaa5a32f32383b:

  drm/i915/mtl: Wa_22011802037: don't complain about missing regs on MTL 
(2023-01-31 15:17:30 -0800)

are available in the Git repository at:

  git://anongit.freedesktop.org/drm/drm-intel tags/drm-intel-gt-next-2023-03-16

for you to fetch changes up to d2a9692ad4295e227e3352fdbf14b8491b01e1c9:

  drm/i915/gt: make kobj attributes const (2023-03-15 12:20:11 +0200)


Driver Changes:

- Fix issue #6333: "list_add corruption" and full system lockup from
  performance monitoring (Janusz)
- Give the punit time to settle before fatally failing (Aravind, Chris)
- Don't use stolen memory or BAR for ring buffers on LLC platforms (John)
- Add missing ecodes and correct timeline seqno on GuC error captures (John)
- Make sure DSM size has correct 1MiB granularity on Gen12+ (Nirmoy,
  Lucas)
- Fix potential SSEU max_subslices array-index-out-of-bounds access on Gen11 
(Andrea)
- Whitelist COMMON_SLICE_CHICKEN3 for UMD access on Gen12+ (Matt R.)
- Apply Wa_1408615072/Wa_1407596294 correctly on Gen11 (Matt R)
- Apply LNCF/LBCF workarounds correctly on XeHP SDV/PVC/DG2 (Matt R)
- Implement Wa_1606376872 for Xe_LP (Gustavo)
- Consider GSI offset when doing MCR lookups on Meteorlake+ (Matt R.)
- Add engine TLB invalidation for Meteorlake (Matt R.)
- Fix GSC Driver-FLR completion on Meteorlake (Alan)
- Fix GSC races on driver load/unload on Meteorlake+ (Daniele)
- Disable MC6 for MTL A step (Badal)

- Consolidate TLB invalidation flow (Tvrtko)
- Improve debug GuC/HuC debug messages (Michal Wa., John)
- Move fd_install after last use of fence (Rob)
- Initialize the obj flags for shmem objects (Aravind)
- Fix missing debug object activation (Nirmoy)
- Probe lmem before the stolen portion (Matt A)
- Improve clean up of GuC busyness stats worker (John)
- Fix missing return code checks in GuC submission init (John)
- Annotate two more workaround/tuning registers as MCR on PVC (Matt R)
- Fix GEN8_MISCCPCTL definition and remove unused 

[Intel-gfx] [PATCH v7 22/22] docs: vfio: Add vfio device cdev description

2023-03-16 Thread Yi Liu
This gives notes for userspace applications on device cdev usage.

Signed-off-by: Yi Liu 
---
 Documentation/driver-api/vfio.rst | 125 ++
 1 file changed, 125 insertions(+)

diff --git a/Documentation/driver-api/vfio.rst 
b/Documentation/driver-api/vfio.rst
index 363e12c90b87..287e1bdede04 100644
--- a/Documentation/driver-api/vfio.rst
+++ b/Documentation/driver-api/vfio.rst
@@ -239,6 +239,123 @@ group and can access them as follows::
/* Gratuitous device reset and go... */
ioctl(device, VFIO_DEVICE_RESET);
 
+IOMMUFD and vfio_iommu_type1
+
+
+IOMMUFD is the new user API to manage I/O page tables from userspace.
+It intends to be the portal of delivering advanced userspace DMA
+features (nested translation [5], PASID [6], etc.) while being backward
+compatible with the vfio_iommu_type1 driver.  Eventually vfio_iommu_type1
+will be deprecated.
+
+With the backward compatibility, no change is required for legacy VFIO
+drivers or applications to connect a VFIO device to IOMMUFD.
+
+   When CONFIG_IOMMUFD_VFIO_CONTAINER=n, VFIO container still provides
+   /dev/vfio/vfio which connects to vfio_iommu_type1.  To disable VFIO
+   container and vfio_iommu_type1, the administrator could symbol link
+   /dev/vfio/vfio to /dev/iommu to enable VFIO container emulation
+   in IOMMUFD.
+
+   When CONFIG_IOMMUFD_VFIO_CONTAINER=y, IOMMUFD directly provides
+   /dev/vfio/vfio while the VFIO container and vfio_iommu_type1 are
+   explicitly disabled.
+
+VFIO Device cdev
+
+
+Traditionally user acquires a device fd via VFIO_GROUP_GET_DEVICE_FD
+in a VFIO group.
+
+With CONFIG_VFIO_DEVICE_CDEV=y the user can now acquire a device fd
+by directly opening a character device /dev/vfio/devices/vfioX where
+"X" is the number allocated uniquely by VFIO for registered devices.
+
+The cdev only works with IOMMUFD.  Both VFIO drivers and applications
+must adapt to the new cdev security model which requires using
+VFIO_DEVICE_BIND_IOMMUFD to claim DMA ownership before starting to
+actually use the device.  Once BIND succeeds then a VFIO device can
+be fully accessed by the user.
+
+VFIO device cdev doesn't rely on VFIO group/container/iommu drivers.
+Hence those modules can be fully compiled out in an environment
+where no legacy VFIO application exists.
+
+So far SPAPR does not support IOMMUFD yet.  So it cannot support device
+cdev neither.
+
+Device cdev Example
+---
+
+Assume user wants to access PCI device :6a:01.0::
+
+   $ ls /sys/bus/pci/devices/:6a:01.0/vfio-dev/
+   vfio0
+
+This device is therefore represented as vfio0.  The user can verify
+its existence::
+
+   $ ls -l /dev/vfio/devices/vfio0
+   crw--- 1 root root 511, 0 Feb 16 01:22 /dev/vfio/devices/vfio0
+   $ cat /sys/bus/pci/devices/:6a:01.0/vfio-dev/vfio0/dev
+   511:0
+   $ ls -l /dev/char/511\:0
+   lrwxrwxrwx 1 root root 21 Feb 16 01:22 /dev/char/511:0 -> 
../vfio/devices/vfio0
+
+Then provide the user with access to the device if unprivileged
+operation is desired::
+
+   $ chown user:user /dev/vfio/devices/vfio0
+
+Finally the user could get cdev fd by::
+
+   cdev_fd = open("/dev/vfio/devices/vfio0", O_RDWR);
+
+An opened cdev_fd doesn't give the user any permission of accessing
+the device except binding the cdev_fd to an iommufd.  After that point
+then the device is fully accessible including attaching it to an
+IOMMUFD IOAS/HWPT to enable userspace DMA::
+
+   struct vfio_device_bind_iommufd bind = {
+   .argsz = sizeof(bind),
+   .flags = 0,
+   };
+   struct iommu_ioas_alloc alloc_data  = {
+   .size = sizeof(alloc_data),
+   .flags = 0,
+   };
+   struct vfio_device_attach_iommufd_pt attach_data = {
+   .argsz = sizeof(attach_data),
+   .flags = 0,
+   };
+   struct iommu_ioas_map map = {
+   .size = sizeof(map),
+   .flags = IOMMU_IOAS_MAP_READABLE |
+IOMMU_IOAS_MAP_WRITEABLE |
+IOMMU_IOAS_MAP_FIXED_IOVA,
+   .__reserved = 0,
+   };
+
+   iommufd = open("/dev/iommu", O_RDWR);
+
+   bind.iommufd = iommufd; // negative value means vfio-noiommu mode
+   ioctl(cdev_fd, VFIO_DEVICE_BIND_IOMMUFD, );
+
+   ioctl(iommufd, IOMMU_IOAS_ALLOC, _data);
+   attach_data.pt_id = alloc_data.out_ioas_id;
+   ioctl(cdev_fd, VFIO_DEVICE_ATTACH_IOMMUFD_PT, _data);
+
+   /* Allocate some space and setup a DMA mapping */
+   map.user_va = (int64_t)mmap(0, 1024 * 1024, PROT_READ | PROT_WRITE,
+   MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+   map.iova = 0; /* 1MB starting at 0x0 from device view */
+   map.length = 1024 * 1024;
+   map.ioas_id = alloc_data.out_ioas_id;;
+
+   ioctl(iommufd, IOMMU_IOAS_MAP, );
+
+   /* Other 

[Intel-gfx] [PATCH v7 21/22] vfio: Compile group optionally

2023-03-16 Thread Yi Liu
group code is not needed for vfio device cdev, so with vfio device cdev
introduced, the group infrastructures can be compiled out if only cdev
is needed.

Reviewed-by: Kevin Tian 
Signed-off-by: Yi Liu 
---
 drivers/iommu/iommufd/Kconfig |   4 +-
 drivers/vfio/Kconfig  |  16 -
 drivers/vfio/Makefile |   2 +-
 drivers/vfio/vfio.h   | 109 --
 include/linux/vfio.h  |  13 +++-
 5 files changed, 132 insertions(+), 12 deletions(-)

diff --git a/drivers/iommu/iommufd/Kconfig b/drivers/iommu/iommufd/Kconfig
index ada693ea51a7..1946eed1826a 100644
--- a/drivers/iommu/iommufd/Kconfig
+++ b/drivers/iommu/iommufd/Kconfig
@@ -14,8 +14,8 @@ config IOMMUFD
 if IOMMUFD
 config IOMMUFD_VFIO_CONTAINER
bool "IOMMUFD provides the VFIO container /dev/vfio/vfio"
-   depends on VFIO && !VFIO_CONTAINER
-   default VFIO && !VFIO_CONTAINER
+   depends on VFIO && VFIO_GROUP && !VFIO_CONTAINER
+   default VFIO && VFIO_GROUP && !VFIO_CONTAINER
help
  IOMMUFD will provide /dev/vfio/vfio instead of VFIO. This relies on
  IOMMUFD providing compatibility emulation to give the same ioctls.
diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig
index e2105b4dac2d..0942a19601a2 100644
--- a/drivers/vfio/Kconfig
+++ b/drivers/vfio/Kconfig
@@ -4,7 +4,9 @@ menuconfig VFIO
select IOMMU_API
depends on IOMMUFD || !IOMMUFD
select INTERVAL_TREE
-   select VFIO_CONTAINER if IOMMUFD=n
+   select VFIO_GROUP if SPAPR_TCE_IOMMU || !IOMMUFD
+   select VFIO_DEVICE_CDEV if !VFIO_GROUP
+   select VFIO_CONTAINER if IOMMUFD=n && VFIO_GROUP
help
  VFIO provides a framework for secure userspace device drivers.
  See Documentation/driver-api/vfio.rst for more details.
@@ -15,6 +17,7 @@ if VFIO
 config VFIO_DEVICE_CDEV
bool "Support for the VFIO cdev /dev/vfio/devices/vfioX"
depends on IOMMUFD
+   default !VFIO_GROUP
help
  The VFIO device cdev is another way for userspace to get device
  access. Userspace gets device fd by opening device cdev under
@@ -23,9 +26,20 @@ config VFIO_DEVICE_CDEV
 
  If you don't know what to do here, say N.
 
+config VFIO_GROUP
+   bool "Support for the VFIO group /dev/vfio/$group_id"
+   default y
+   help
+  VFIO group support provides the traditional model for accessing
+  devices through VFIO and is used by the majority of userspace
+  applications and drivers making use of VFIO.
+
+  If you don't know what to do here, say Y.
+
 config VFIO_CONTAINER
bool "Support for the VFIO container /dev/vfio/vfio"
select VFIO_IOMMU_TYPE1 if MMU && (X86 || S390 || ARM || ARM64)
+   depends on VFIO_GROUP
default y
help
  The VFIO container is the classic interface to VFIO for establishing
diff --git a/drivers/vfio/Makefile b/drivers/vfio/Makefile
index 245394aeb94b..57c3515af606 100644
--- a/drivers/vfio/Makefile
+++ b/drivers/vfio/Makefile
@@ -2,9 +2,9 @@
 obj-$(CONFIG_VFIO) += vfio.o
 
 vfio-y += vfio_main.o \
- group.o \
  iova_bitmap.o
 vfio-$(CONFIG_VFIO_DEVICE_CDEV) += device_cdev.o
+vfio-$(CONFIG_VFIO_GROUP) += group.o
 vfio-$(CONFIG_IOMMUFD) += iommufd.o
 vfio-$(CONFIG_VFIO_CONTAINER) += container.o
 vfio-$(CONFIG_VFIO_VIRQFD) += virqfd.o
diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h
index 907c12d53ce2..eda92f1949e1 100644
--- a/drivers/vfio/vfio.h
+++ b/drivers/vfio/vfio.h
@@ -36,6 +36,12 @@ vfio_allocate_device_file(struct vfio_device *device);
 
 extern const struct file_operations vfio_device_fops;
 
+#ifdef CONFIG_VFIO_NOIOMMU
+extern bool vfio_noiommu __read_mostly;
+#else
+enum { vfio_noiommu = false };
+#endif
+
 enum vfio_group_type {
/*
 * Physical device with IOMMU backing.
@@ -60,6 +66,7 @@ enum vfio_group_type {
VFIO_NO_IOMMU,
 };
 
+#if IS_ENABLED(CONFIG_VFIO_GROUP)
 struct vfio_group {
struct device   dev;
struct cdev cdev;
@@ -113,6 +120,102 @@ static inline bool vfio_device_is_noiommu(struct 
vfio_device *vdev)
return IS_ENABLED(CONFIG_VFIO_NOIOMMU) &&
   vdev->group->type == VFIO_NO_IOMMU;
 }
+#else
+struct vfio_group;
+
+static inline int vfio_device_block_group(struct vfio_device *device)
+{
+   return 0;
+}
+
+static inline void vfio_device_unblock_group(struct vfio_device *device)
+{
+}
+
+static inline int vfio_device_set_group(struct vfio_device *device,
+   enum vfio_group_type type)
+{
+   return 0;
+}
+
+static inline void vfio_device_remove_group(struct vfio_device *device)
+{
+}
+
+static inline void vfio_device_group_register(struct vfio_device *device)
+{
+}
+
+static inline void vfio_device_group_unregister(struct vfio_device *device)
+{
+}
+
+static inline bool vfio_device_group_uses_container(struct vfio_device_file 
*df)
+{

[Intel-gfx] [PATCH v7 13/22] vfio-iommufd: Split bind/attach into two steps

2023-03-16 Thread Yi Liu
to align with the coming vfio device cdev support.

Signed-off-by: Yi Liu 
---
 drivers/vfio/group.c   | 18 ++
 drivers/vfio/iommufd.c | 33 ++---
 drivers/vfio/vfio.h|  9 +
 3 files changed, 37 insertions(+), 23 deletions(-)

diff --git a/drivers/vfio/group.c b/drivers/vfio/group.c
index 1ad8df9b295f..70bdecff4785 100644
--- a/drivers/vfio/group.c
+++ b/drivers/vfio/group.c
@@ -203,9 +203,14 @@ static int vfio_device_group_open(struct vfio_device_file 
*df)
}
 
ret = vfio_device_open(df);
-   if (ret) {
-   df->iommufd = NULL;
+   if (ret)
goto out_put_kvm;
+
+   if (df->iommufd) {
+   ret = vfio_iommufd_attach_compat_ioas(device,
+ df->iommufd);
+   if (ret)
+   goto out_close_device;
}
 
/*
@@ -214,12 +219,17 @@ static int vfio_device_group_open(struct vfio_device_file 
*df)
 */
smp_store_release(>access_granted, true);
 
+   mutex_unlock(>dev_set->lock);
+   mutex_unlock(>group->group_lock);
+   return 0;
+
+out_close_device:
+   vfio_device_close(df);
 out_put_kvm:
+   df->iommufd = NULL;
if (device->open_count == 0)
vfio_device_put_kvm(device);
-
mutex_unlock(>dev_set->lock);
-
 out_unlock:
mutex_unlock(>group->group_lock);
return ret;
diff --git a/drivers/vfio/iommufd.c b/drivers/vfio/iommufd.c
index 7334b67dbb8a..2daef60fe439 100644
--- a/drivers/vfio/iommufd.c
+++ b/drivers/vfio/iommufd.c
@@ -30,33 +30,28 @@ int vfio_iommufd_enable_noiommu_compat(struct vfio_device 
*device,
 
 int vfio_iommufd_bind(struct vfio_device *vdev, struct iommufd_ctx *ictx)
 {
-   u32 ioas_id;
u32 device_id;
-   int ret;
 
lockdep_assert_held(>dev_set->lock);
 
-   ret = vdev->ops->bind_iommufd(vdev, ictx, _id);
-   if (ret)
-   return ret;
+   /* The legacy path has no way to return the device id */
+   return vdev->ops->bind_iommufd(vdev, ictx, _id);
+}
+
+int vfio_iommufd_attach_compat_ioas(struct vfio_device *vdev,
+   struct iommufd_ctx *ictx)
+{
+   u32 ioas_id;
+   int ret;
+
+   lockdep_assert_held(>dev_set->lock);
 
ret = iommufd_vfio_compat_ioas_get_id(ictx, _id);
if (ret)
-   goto err_unbind;
-   ret = vdev->ops->attach_ioas(vdev, _id);
-   if (ret)
-   goto err_unbind;
-
-   /*
-* The legacy path has no way to return the device id or the selected
-* pt_id
-*/
-   return 0;
+   return ret;
 
-err_unbind:
-   if (vdev->ops->unbind_iommufd)
-   vdev->ops->unbind_iommufd(vdev);
-   return ret;
+   /* The legacy path has no way to return the selected pt_id */
+   return vdev->ops->attach_ioas(vdev, _id);
 }
 
 void vfio_iommufd_unbind(struct vfio_device *vdev)
diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h
index 136137b8618d..abfaf85cc266 100644
--- a/drivers/vfio/vfio.h
+++ b/drivers/vfio/vfio.h
@@ -238,6 +238,8 @@ static inline void vfio_container_cleanup(void)
 #if IS_ENABLED(CONFIG_IOMMUFD)
 int vfio_iommufd_enable_noiommu_compat(struct vfio_device *device,
   struct iommufd_ctx *ictx);
+int vfio_iommufd_attach_compat_ioas(struct vfio_device *device,
+   struct iommufd_ctx *ictx);
 int vfio_iommufd_bind(struct vfio_device *device, struct iommufd_ctx *ictx);
 void vfio_iommufd_unbind(struct vfio_device *device);
 #else
@@ -248,6 +250,13 @@ vfio_iommufd_enable_noiommu_compat(struct vfio_device 
*device,
return -EOPNOTSUPP;
 }
 
+static inline int
+vfio_iommufd_attach_compat_ioas(struct vfio_device *device,
+   struct iommufd_ctx *ictx)
+{
+   return -EOPNOTSUPP;
+}
+
 static inline int vfio_iommufd_bind(struct vfio_device *device,
struct iommufd_ctx *ictx)
 {
-- 
2.34.1



[Intel-gfx] [PATCH v7 20/22] vfio: Add VFIO_DEVICE_AT[DE]TACH_IOMMUFD_PT

2023-03-16 Thread Yi Liu
This adds ioctl for userspace to attach device cdev fd to and detach
from IOAS/hw_pagetable managed by iommufd.

VFIO_DEVICE_ATTACH_IOMMUFD_PT: attach vfio device to IOAS, hw_pagetable
   managed by iommufd. Attach can be
   undo by VFIO_DEVICE_DETACH_IOMMUFD_PT
   or device fd close.
VFIO_DEVICE_DETACH_IOMMUFD_PT: detach vfio device from the current attached
   IOAS or hw_pagetable managed by iommufd.

Reviewed-by: Kevin Tian 
Tested-by: Terrence Xu 
Tested-by: Nicolin Chen 
Tested-by: Matthew Rosato 
Signed-off-by: Yi Liu 
---
 drivers/vfio/device_cdev.c | 85 ++
 drivers/vfio/vfio.h| 16 +++
 drivers/vfio/vfio_main.c   |  8 
 include/uapi/linux/vfio.h  | 52 +++
 4 files changed, 161 insertions(+)

diff --git a/drivers/vfio/device_cdev.c b/drivers/vfio/device_cdev.c
index 73430290e7d1..cb6a4b1ed7e7 100644
--- a/drivers/vfio/device_cdev.c
+++ b/drivers/vfio/device_cdev.c
@@ -197,6 +197,91 @@ long vfio_device_ioctl_bind_iommufd(struct 
vfio_device_file *df,
return ret;
 }
 
+int vfio_ioctl_device_attach(struct vfio_device_file *df,
+struct vfio_device_attach_iommufd_pt __user *arg)
+{
+   struct vfio_device *device = df->device;
+   struct vfio_device_attach_iommufd_pt attach;
+   unsigned long minsz;
+   int ret;
+
+   static_assert(__same_type(arg->pt_id, attach.pt_id));
+
+   minsz = offsetofend(struct vfio_device_attach_iommufd_pt, pt_id);
+
+   if (copy_from_user(, arg, minsz))
+   return -EFAULT;
+
+   if (attach.argsz < minsz || attach.flags)
+   return -EINVAL;
+
+   if (!device->ops->bind_iommufd)
+   return -ENODEV;
+
+   /* ATTACH only allowed for cdev fds */
+   if (df->group)
+   return -EINVAL;
+
+   mutex_lock(>dev_set->lock);
+   /* noiommufd mode doesn't allow attach */
+   if (!df->iommufd) {
+   ret = -EOPNOTSUPP;
+   goto out_unlock;
+   }
+
+   ret = device->ops->attach_ioas(device, _id);
+   if (ret)
+   goto out_unlock;
+
+   ret = copy_to_user(>pt_id, _id,
+  sizeof(attach.pt_id)) ? -EFAULT : 0;
+   if (ret)
+   goto out_detach;
+   mutex_unlock(>dev_set->lock);
+
+   return 0;
+
+out_detach:
+   device->ops->detach_ioas(device);
+out_unlock:
+   mutex_unlock(>dev_set->lock);
+   return ret;
+}
+
+int vfio_ioctl_device_detach(struct vfio_device_file *df,
+struct vfio_device_detach_iommufd_pt __user *arg)
+{
+   struct vfio_device *device = df->device;
+   struct vfio_device_detach_iommufd_pt detach;
+   unsigned long minsz;
+
+   minsz = offsetofend(struct vfio_device_detach_iommufd_pt, flags);
+
+   if (copy_from_user(, arg, minsz))
+   return -EFAULT;
+
+   if (detach.argsz < minsz || detach.flags)
+   return -EINVAL;
+
+   if (!device->ops->bind_iommufd)
+   return -ENODEV;
+
+   /* DETACH only allowed for cdev fds */
+   if (df->group)
+   return -EINVAL;
+
+   mutex_lock(>dev_set->lock);
+   /* noiommufd mode doesn't support detach */
+   if (!df->iommufd) {
+   mutex_unlock(>dev_set->lock);
+   return -EOPNOTSUPP;
+   }
+   device->ops->detach_ioas(device);
+   mutex_unlock(>dev_set->lock);
+
+   return 0;
+}
+
 static char *vfio_device_devnode(const struct device *dev, umode_t *mode)
 {
return kasprintf(GFP_KERNEL, "vfio/devices/%s", dev_name(dev));
diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h
index 87b536a06f91..907c12d53ce2 100644
--- a/drivers/vfio/vfio.h
+++ b/drivers/vfio/vfio.h
@@ -284,6 +284,10 @@ int vfio_device_fops_cdev_open(struct inode *inode, struct 
file *filep);
 void vfio_device_cdev_close(struct vfio_device_file *df);
 long vfio_device_ioctl_bind_iommufd(struct vfio_device_file *df,
struct vfio_device_bind_iommufd __user 
*arg);
+int vfio_ioctl_device_attach(struct vfio_device_file *df,
+struct vfio_device_attach_iommufd_pt __user *arg);
+int vfio_ioctl_device_detach(struct vfio_device_file *df,
+struct vfio_device_detach_iommufd_pt __user *arg);
 int vfio_cdev_init(struct class *device_class);
 void vfio_cdev_cleanup(void);
 #else
@@ -317,6 +321,18 @@ static inline long vfio_device_ioctl_bind_iommufd(struct 
vfio_device_file *df,
return -EOPNOTSUPP;
 }
 
+static inline int vfio_ioctl_device_attach(struct vfio_device_file *df,
+  struct vfio_device_attach_iommufd_pt 
__user *arg)
+{
+   return -EOPNOTSUPP;
+}
+
+static inline int vfio_ioctl_device_detach(struct vfio_device_file *df,
+  

[Intel-gfx] [PATCH v7 19/22] vfio: Add VFIO_DEVICE_BIND_IOMMUFD

2023-03-16 Thread Yi Liu
This adds ioctl for userspace to bind device cdev fd to iommufd.

VFIO_DEVICE_BIND_IOMMUFD: bind device to an iommufd, hence gain DMA
  control provided by the iommufd. open_device
  op is called after bind_iommufd op.
  VFIO no iommu mode is indicated by passing
  a negative iommufd value.

Signed-off-by: Yi Liu 
---
 drivers/vfio/device_cdev.c | 153 +
 drivers/vfio/vfio.h|  13 
 drivers/vfio/vfio_main.c   |   5 ++
 include/uapi/linux/vfio.h  |  37 +
 4 files changed, 208 insertions(+)

diff --git a/drivers/vfio/device_cdev.c b/drivers/vfio/device_cdev.c
index 1c640016a824..73430290e7d1 100644
--- a/drivers/vfio/device_cdev.c
+++ b/drivers/vfio/device_cdev.c
@@ -3,6 +3,7 @@
  * Copyright (c) 2023 Intel Corporation.
  */
 #include 
+#include 
 
 #include "vfio.h"
 
@@ -44,6 +45,158 @@ int vfio_device_fops_cdev_open(struct inode *inode, struct 
file *filep)
return ret;
 }
 
+static void vfio_device_get_kvm_safe(struct vfio_device_file *df)
+{
+   spin_lock(>kvm_ref_lock);
+   if (df->kvm)
+   _vfio_device_get_kvm_safe(df->device, df->kvm);
+   spin_unlock(>kvm_ref_lock);
+}
+
+void vfio_device_cdev_close(struct vfio_device_file *df)
+{
+   struct vfio_device *device = df->device;
+
+   /*
+* As df->access_granted writer is under dev_set->lock as well,
+* so this read no need to use smp_load_acquire() to pair with
+* smp_store_release() in the caller of vfio_device_open().
+*/
+   if (!df->access_granted)
+   return;
+
+   mutex_lock(>dev_set->lock);
+   vfio_device_close(df);
+   vfio_device_put_kvm(device);
+   if (df->iommufd)
+   iommufd_ctx_put(df->iommufd);
+   mutex_unlock(>dev_set->lock);
+   vfio_device_unblock_group(device);
+}
+
+static int vfio_device_cdev_enable_noiommu(struct vfio_device *device)
+{
+   if (!vfio_device_is_noiommu(device))
+   return -EINVAL;
+
+   if (!capable(CAP_SYS_RAWIO))
+   return -EPERM;
+
+   return 0;
+}
+
+static struct iommufd_ctx *vfio_get_iommufd_from_fd(int fd)
+{
+   struct fd f;
+   struct iommufd_ctx *iommufd;
+
+   f = fdget(fd);
+   if (!f.file)
+   return ERR_PTR(-EBADF);
+
+   iommufd = iommufd_ctx_from_file(f.file);
+
+   fdput(f);
+   return iommufd;
+}
+
+long vfio_device_ioctl_bind_iommufd(struct vfio_device_file *df,
+   struct vfio_device_bind_iommufd __user *arg)
+{
+   struct vfio_device *device = df->device;
+   struct vfio_device_bind_iommufd bind;
+   struct iommufd_ctx *iommufd = NULL;
+   unsigned long minsz;
+   int ret;
+
+   static_assert(__same_type(arg->out_devid, bind.out_devid));
+
+   minsz = offsetofend(struct vfio_device_bind_iommufd, out_devid);
+
+   if (copy_from_user(, arg, minsz))
+   return -EFAULT;
+
+   if (bind.argsz < minsz || bind.flags)
+   return -EINVAL;
+
+   if (!device->ops->bind_iommufd)
+   return -ENODEV;
+
+   /* BIND_IOMMUFD only allowed for cdev fds */
+   if (df->group)
+   return -EINVAL;
+
+   ret = vfio_device_block_group(device);
+   if (ret)
+   return ret;
+
+   mutex_lock(>dev_set->lock);
+   /* one device cannot be bound twice */
+   if (df->access_granted) {
+   ret = -EINVAL;
+   goto out_unlock;
+   }
+
+   /* iommufd < 0 means noiommu mode */
+   if (bind.iommufd < 0) {
+   ret = vfio_device_cdev_enable_noiommu(device);
+   if (ret)
+   goto out_unlock;
+   } else {
+   iommufd = vfio_get_iommufd_from_fd(bind.iommufd);
+   if (IS_ERR(iommufd)) {
+   ret = PTR_ERR(iommufd);
+   goto out_unlock;
+   }
+   }
+
+   /*
+* Before the device open, get the KVM pointer currently
+* associated with the device file (if there is) and obtain
+* a reference.  This reference is held until device closed.
+* Save the pointer in the device for use by drivers.
+*/
+   vfio_device_get_kvm_safe(df);
+
+   df->iommufd = iommufd;
+   ret = vfio_device_open(df);
+   if (ret)
+   goto out_put_kvm;
+
+   if (df->iommufd)
+   bind.out_devid = df->devid;
+
+   ret = copy_to_user(>out_devid, _devid,
+  sizeof(bind.out_devid)) ? -EFAULT : 0;
+   if (ret)
+   goto out_close_device;
+
+   if (bind.iommufd < 0)
+   dev_warn(device->dev, "device is bound to vfio-noiommu by user "
+"(%s:%d)\n", current->comm, task_pid_nr(current));
+
+   /*
+* Paired with 

[Intel-gfx] [PATCH v7 16/22] iommufd/device: Add iommufd_access_detach() API

2023-03-16 Thread Yi Liu
From: Nicolin Chen 

Previously, the detach routine is only done by the destroy(). And it was
called by vfio_iommufd_emulated_unbind() when the device runs close(), so
all the mappings in iopt were cleaned in that setup, when the call trace
reaches this detach() routine.

Now, there's a need of a detach uAPI, meaning that it does not only need
a new iommufd_access_detach() API, but also requires access->ops->unmap()
call as a cleanup. So add one.

However, leaving that unprotected can introduce some potential of a race
condition during the pin_/unpin_pages() call, where access->ioas->iopt is
getting referenced. So, add an ioas_lock to protect the context of iopt
referencings.

Also, to allow the iommufd_access_unpin_pages() callback to happen via
this unmap() call, add an ioas_unpin pointer, so the unpin routine won't
be affected by the "access->ioas = NULL" trick.

Signed-off-by: Nicolin Chen 
Signed-off-by: Yi Liu 
---
 drivers/iommu/iommufd/device.c  | 75 +++--
 drivers/iommu/iommufd/iommufd_private.h |  2 +
 include/linux/iommufd.h |  1 +
 3 files changed, 73 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c
index 2ca12716db98..404496ffd1d2 100644
--- a/drivers/iommu/iommufd/device.c
+++ b/drivers/iommu/iommufd/device.c
@@ -487,28 +487,68 @@ void iommufd_access_destroy(struct iommufd_access *access)
 }
 EXPORT_SYMBOL_NS_GPL(iommufd_access_destroy, IOMMUFD);
 
+static void __iommufd_access_detach(struct iommufd_access *access)
+{
+   struct iommufd_ioas *cur_ioas = access->ioas;
+
+   lockdep_assert_held(>ioas_lock);
+   /*
+* Set ioas to NULL to block any further iommufd_access_pin_pages().
+* iommufd_access_unpin_pages() can continue using access->ioas_unpin.
+*/
+   access->ioas = NULL;
+
+   if (access->ops->unmap) {
+   mutex_unlock(>ioas_lock);
+   access->ops->unmap(access->data, 0, ULONG_MAX);
+   mutex_lock(>ioas_lock);
+   }
+   iopt_remove_access(_ioas->iopt, access);
+   refcount_dec(_ioas->obj.users);
+}
+
+void iommufd_access_detach(struct iommufd_access *access)
+{
+   mutex_lock(>ioas_lock);
+   if (WARN_ON(!access->ioas))
+   goto out;
+   __iommufd_access_detach(access);
+out:
+   access->ioas_unpin = NULL;
+   mutex_unlock(>ioas_lock);
+}
+EXPORT_SYMBOL_NS_GPL(iommufd_access_detach, IOMMUFD);
+
 int iommufd_access_attach(struct iommufd_access *access, u32 ioas_id)
 {
struct iommufd_ioas *new_ioas;
struct iommufd_object *obj;
int rc = 0;
 
-   if (access->ioas != NULL && access->ioas->obj.id != ioas_id)
+   mutex_lock(>ioas_lock);
+   if (access->ioas != NULL && access->ioas->obj.id != ioas_id) {
+   mutex_unlock(>ioas_lock);
return -EINVAL;
+   }
 
obj = iommufd_get_object(access->ictx, ioas_id, IOMMUFD_OBJ_IOAS);
-   if (IS_ERR(obj))
+   if (IS_ERR(obj)) {
+   mutex_unlock(>ioas_lock);
return PTR_ERR(obj);
+   }
new_ioas = container_of(obj, struct iommufd_ioas, obj);
 
rc = iopt_add_access(_ioas->iopt, access);
if (rc) {
+   mutex_unlock(>ioas_lock);
iommufd_put_object(obj);
return rc;
}
iommufd_ref_to_users(obj);
 
access->ioas = new_ioas;
+   access->ioas_unpin = new_ioas;
+   mutex_unlock(>ioas_lock);
return 0;
 }
 EXPORT_SYMBOL_NS_GPL(iommufd_access_attach, IOMMUFD);
@@ -563,8 +603,8 @@ void iommufd_access_notify_unmap(struct io_pagetable *iopt, 
unsigned long iova,
 void iommufd_access_unpin_pages(struct iommufd_access *access,
unsigned long iova, unsigned long length)
 {
-   struct io_pagetable *iopt = >ioas->iopt;
struct iopt_area_contig_iter iter;
+   struct io_pagetable *iopt;
unsigned long last_iova;
struct iopt_area *area;
 
@@ -572,6 +612,13 @@ void iommufd_access_unpin_pages(struct iommufd_access 
*access,
WARN_ON(check_add_overflow(iova, length - 1, _iova)))
return;
 
+   mutex_lock(>ioas_lock);
+   if (!access->ioas_unpin) {
+   mutex_unlock(>ioas_lock);
+   return;
+   }
+   iopt = >ioas_unpin->iopt;
+
down_read(>iova_rwsem);
iopt_for_each_contig_area(, area, iopt, iova, last_iova)
iopt_area_remove_access(
@@ -581,6 +628,7 @@ void iommufd_access_unpin_pages(struct iommufd_access 
*access,
min(last_iova, iopt_area_last_iova(area;
up_read(>iova_rwsem);
WARN_ON(!iopt_area_contig_done());
+   mutex_unlock(>ioas_lock);
 }
 EXPORT_SYMBOL_NS_GPL(iommufd_access_unpin_pages, IOMMUFD);
 
@@ -626,8 +674,8 @@ int iommufd_access_pin_pages(struct iommufd_access *access, 
unsigned long iova,
 

[Intel-gfx] [PATCH v7 17/22] vfio-iommufd: Add detach_ioas support for emulated VFIO devices

2023-03-16 Thread Yi Liu
this prepares for adding DETACH ioctl for emulated VFIO devices.

Reviewed-by: Kevin Tian 
Tested-by: Terrence Xu 
Tested-by: Nicolin Chen 
Tested-by: Matthew Rosato 
Signed-off-by: Yi Liu 
---
 drivers/gpu/drm/i915/gvt/kvmgt.c  |  1 +
 drivers/s390/cio/vfio_ccw_ops.c   |  1 +
 drivers/s390/crypto/vfio_ap_ops.c |  1 +
 drivers/vfio/iommufd.c| 12 
 include/linux/vfio.h  |  3 +++
 samples/vfio-mdev/mbochs.c|  1 +
 samples/vfio-mdev/mdpy.c  |  1 +
 samples/vfio-mdev/mtty.c  |  1 +
 8 files changed, 21 insertions(+)

diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index de675d799c7d..9cd9e9da60dd 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -1474,6 +1474,7 @@ static const struct vfio_device_ops intel_vgpu_dev_ops = {
.bind_iommufd   = vfio_iommufd_emulated_bind,
.unbind_iommufd = vfio_iommufd_emulated_unbind,
.attach_ioas= vfio_iommufd_emulated_attach_ioas,
+   .detach_ioas= vfio_iommufd_emulated_detach_ioas,
 };
 
 static int intel_vgpu_probe(struct mdev_device *mdev)
diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c
index 5b53b94f13c7..cba4971618ff 100644
--- a/drivers/s390/cio/vfio_ccw_ops.c
+++ b/drivers/s390/cio/vfio_ccw_ops.c
@@ -632,6 +632,7 @@ static const struct vfio_device_ops vfio_ccw_dev_ops = {
.bind_iommufd = vfio_iommufd_emulated_bind,
.unbind_iommufd = vfio_iommufd_emulated_unbind,
.attach_ioas = vfio_iommufd_emulated_attach_ioas,
+   .detach_ioas = vfio_iommufd_emulated_detach_ioas,
 };
 
 struct mdev_driver vfio_ccw_mdev_driver = {
diff --git a/drivers/s390/crypto/vfio_ap_ops.c 
b/drivers/s390/crypto/vfio_ap_ops.c
index 72e10abb103a..9902e62e7a17 100644
--- a/drivers/s390/crypto/vfio_ap_ops.c
+++ b/drivers/s390/crypto/vfio_ap_ops.c
@@ -1844,6 +1844,7 @@ static const struct vfio_device_ops 
vfio_ap_matrix_dev_ops = {
.bind_iommufd = vfio_iommufd_emulated_bind,
.unbind_iommufd = vfio_iommufd_emulated_unbind,
.attach_ioas = vfio_iommufd_emulated_attach_ioas,
+   .detach_ioas = vfio_iommufd_emulated_detach_ioas,
 };
 
 static struct mdev_driver vfio_ap_matrix_driver = {
diff --git a/drivers/vfio/iommufd.c b/drivers/vfio/iommufd.c
index 563818340a18..f3fa03495a41 100644
--- a/drivers/vfio/iommufd.c
+++ b/drivers/vfio/iommufd.c
@@ -200,3 +200,15 @@ int vfio_iommufd_emulated_attach_ioas(struct vfio_device 
*vdev, u32 *pt_id)
return 0;
 }
 EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_attach_ioas);
+
+void vfio_iommufd_emulated_detach_ioas(struct vfio_device *vdev)
+{
+   lockdep_assert_held(>dev_set->lock);
+
+   if (WARN_ON(!vdev->iommufd_access) || !vdev->iommufd_attached)
+   return;
+
+   iommufd_access_detach(vdev->iommufd_access);
+   vdev->iommufd_attached = false;
+}
+EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_detach_ioas);
diff --git a/include/linux/vfio.h b/include/linux/vfio.h
index 4078133c0316..c70e5b021df9 100644
--- a/include/linux/vfio.h
+++ b/include/linux/vfio.h
@@ -126,6 +126,7 @@ int vfio_iommufd_emulated_bind(struct vfio_device *vdev,
   struct iommufd_ctx *ictx, u32 *out_device_id);
 void vfio_iommufd_emulated_unbind(struct vfio_device *vdev);
 int vfio_iommufd_emulated_attach_ioas(struct vfio_device *vdev, u32 *pt_id);
+void vfio_iommufd_emulated_detach_ioas(struct vfio_device *vdev);
 #else
 #define vfio_iommufd_physical_bind  \
((int (*)(struct vfio_device *vdev, struct iommufd_ctx *ictx,   \
@@ -145,6 +146,8 @@ int vfio_iommufd_emulated_attach_ioas(struct vfio_device 
*vdev, u32 *pt_id);
((void (*)(struct vfio_device *vdev)) NULL)
 #define vfio_iommufd_emulated_attach_ioas \
((int (*)(struct vfio_device *vdev, u32 *pt_id)) NULL)
+#define vfio_iommufd_emulated_detach_ioas \
+   ((void (*)(struct vfio_device *vdev)) NULL)
 #endif
 
 /**
diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c
index 19391dda5fba..47a2914b63d9 100644
--- a/samples/vfio-mdev/mbochs.c
+++ b/samples/vfio-mdev/mbochs.c
@@ -1377,6 +1377,7 @@ static const struct vfio_device_ops mbochs_dev_ops = {
.bind_iommufd   = vfio_iommufd_emulated_bind,
.unbind_iommufd = vfio_iommufd_emulated_unbind,
.attach_ioas= vfio_iommufd_emulated_attach_ioas,
+   .detach_ioas= vfio_iommufd_emulated_detach_ioas,
 };
 
 static struct mdev_driver mbochs_driver = {
diff --git a/samples/vfio-mdev/mdpy.c b/samples/vfio-mdev/mdpy.c
index 5f48aef36995..ce0e67f37406 100644
--- a/samples/vfio-mdev/mdpy.c
+++ b/samples/vfio-mdev/mdpy.c
@@ -666,6 +666,7 @@ static const struct vfio_device_ops mdpy_dev_ops = {
.bind_iommufd   = vfio_iommufd_emulated_bind,
.unbind_iommufd = vfio_iommufd_emulated_unbind,
.attach_ioas= vfio_iommufd_emulated_attach_ioas,
+   .detach_ioas= 

[Intel-gfx] [PATCH v7 18/22] vfio: Add cdev for vfio_device

2023-03-16 Thread Yi Liu
This allows user to directly open a vfio device w/o using the legacy
container/group interface, as a prerequisite for supporting new iommu
features like nested translation.

The device fd opened in this manner doesn't have the capability to access
the device as the fops open() doesn't open the device until the successful
BIND_IOMMUFD which be added in next patch.

With this patch, devices registered to vfio core have both group and device
interface created.

- group interface : /dev/vfio/$groupID
- device interface: /dev/vfio/devices/vfioX  (X is the minor number and
  is unique across devices)

Given a vfio device the user can identify the matching vfioX by checking
the sysfs path of the device. Take PCI device (:6a:01.0) for example,
/sys/bus/pci/devices/\:6a\:01.0/vfio-dev/vfio0/dev contains the
major:minor of the matching vfioX.

Userspace then opens the /dev/vfio/devices/vfioX and checks with fstat
that the major:minor matches.

The vfio_device cdev logic in this patch:
*) __vfio_register_dev() path ends up doing cdev_device_add() for each
   vfio_device if VFIO_DEVICE_CDEV configured.
*) vfio_unregister_group_dev() path does cdev_device_del();

Reviewed-by: Kevin Tian 
Tested-by: Terrence Xu 
Tested-by: Nicolin Chen 
Tested-by: Matthew Rosato 
Signed-off-by: Yi Liu 
---
 drivers/vfio/Kconfig   | 11 +++
 drivers/vfio/Makefile  |  1 +
 drivers/vfio/device_cdev.c | 62 ++
 drivers/vfio/vfio.h| 46 
 drivers/vfio/vfio_main.c   | 26 +++-
 include/linux/vfio.h   |  4 +++
 6 files changed, 143 insertions(+), 7 deletions(-)
 create mode 100644 drivers/vfio/device_cdev.c

diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig
index 89e06c981e43..e2105b4dac2d 100644
--- a/drivers/vfio/Kconfig
+++ b/drivers/vfio/Kconfig
@@ -12,6 +12,17 @@ menuconfig VFIO
  If you don't know what to do here, say N.
 
 if VFIO
+config VFIO_DEVICE_CDEV
+   bool "Support for the VFIO cdev /dev/vfio/devices/vfioX"
+   depends on IOMMUFD
+   help
+ The VFIO device cdev is another way for userspace to get device
+ access. Userspace gets device fd by opening device cdev under
+ /dev/vfio/devices/vfioX, and then bind the device fd with an iommufd
+ to set up secure DMA context for device access.
+
+ If you don't know what to do here, say N.
+
 config VFIO_CONTAINER
bool "Support for the VFIO container /dev/vfio/vfio"
select VFIO_IOMMU_TYPE1 if MMU && (X86 || S390 || ARM || ARM64)
diff --git a/drivers/vfio/Makefile b/drivers/vfio/Makefile
index 70e7dcb302ef..245394aeb94b 100644
--- a/drivers/vfio/Makefile
+++ b/drivers/vfio/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_VFIO) += vfio.o
 vfio-y += vfio_main.o \
  group.o \
  iova_bitmap.o
+vfio-$(CONFIG_VFIO_DEVICE_CDEV) += device_cdev.o
 vfio-$(CONFIG_IOMMUFD) += iommufd.o
 vfio-$(CONFIG_VFIO_CONTAINER) += container.o
 vfio-$(CONFIG_VFIO_VIRQFD) += virqfd.o
diff --git a/drivers/vfio/device_cdev.c b/drivers/vfio/device_cdev.c
new file mode 100644
index ..1c640016a824
--- /dev/null
+++ b/drivers/vfio/device_cdev.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2023 Intel Corporation.
+ */
+#include 
+
+#include "vfio.h"
+
+static dev_t device_devt;
+
+void vfio_init_device_cdev(struct vfio_device *device)
+{
+   device->device.devt = MKDEV(MAJOR(device_devt), device->index);
+   cdev_init(>cdev, _device_fops);
+   device->cdev.owner = THIS_MODULE;
+}
+
+/*
+ * device access via the fd opened by this function is blocked until
+ * .open_device() is called successfully during BIND_IOMMUFD.
+ */
+int vfio_device_fops_cdev_open(struct inode *inode, struct file *filep)
+{
+   struct vfio_device *device = container_of(inode->i_cdev,
+ struct vfio_device, cdev);
+   struct vfio_device_file *df;
+   int ret;
+
+   if (!vfio_device_try_get_registration(device))
+   return -ENODEV;
+
+   df = vfio_allocate_device_file(device);
+   if (IS_ERR(df)) {
+   ret = PTR_ERR(df);
+   goto err_put_registration;
+   }
+
+   filep->private_data = df;
+
+   return 0;
+
+err_put_registration:
+   vfio_device_put_registration(device);
+   return ret;
+}
+
+static char *vfio_device_devnode(const struct device *dev, umode_t *mode)
+{
+   return kasprintf(GFP_KERNEL, "vfio/devices/%s", dev_name(dev));
+}
+
+int vfio_cdev_init(struct class *device_class)
+{
+   device_class->devnode = vfio_device_devnode;
+   return alloc_chrdev_region(_devt, 0,
+  MINORMASK + 1, "vfio-dev");
+}
+
+void vfio_cdev_cleanup(void)
+{
+   unregister_chrdev_region(device_devt, MINORMASK + 1);
+}
diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h
index 

[Intel-gfx] [PATCH v7 15/22] vfio-iommufd: Add detach_ioas support for physical VFIO devices

2023-03-16 Thread Yi Liu
this prepares for adding DETACH ioctl for physical VFIO devices.

Reviewed-by: Kevin Tian 
Tested-by: Terrence Xu 
Tested-by: Nicolin Chen 
Tested-by: Matthew Rosato 
Signed-off-by: Yi Liu 
---
 Documentation/driver-api/vfio.rst |  8 +---
 drivers/vfio/fsl-mc/vfio_fsl_mc.c |  1 +
 drivers/vfio/iommufd.c| 20 +++
 .../vfio/pci/hisilicon/hisi_acc_vfio_pci.c|  2 ++
 drivers/vfio/pci/mlx5/main.c  |  1 +
 drivers/vfio/pci/vfio_pci.c   |  1 +
 drivers/vfio/platform/vfio_amba.c |  1 +
 drivers/vfio/platform/vfio_platform.c |  1 +
 drivers/vfio/vfio_main.c  |  3 ++-
 include/linux/vfio.h  |  8 +++-
 10 files changed, 41 insertions(+), 5 deletions(-)

diff --git a/Documentation/driver-api/vfio.rst 
b/Documentation/driver-api/vfio.rst
index 68abc089d6dd..363e12c90b87 100644
--- a/Documentation/driver-api/vfio.rst
+++ b/Documentation/driver-api/vfio.rst
@@ -279,6 +279,7 @@ similar to a file operations structure::
struct iommufd_ctx *ictx, u32 
*out_device_id);
void(*unbind_iommufd)(struct vfio_device *vdev);
int (*attach_ioas)(struct vfio_device *vdev, u32 *pt_id);
+   void(*detach_ioas)(struct vfio_device *vdev);
int (*open_device)(struct vfio_device *vdev);
void(*close_device)(struct vfio_device *vdev);
ssize_t (*read)(struct vfio_device *vdev, char __user *buf,
@@ -315,9 +316,10 @@ container_of().
- The [un]bind_iommufd callbacks are issued when the device is bound to
  and unbound from iommufd.
 
-   - The attach_ioas callback is issued when the device is attached to an
- IOAS managed by the bound iommufd. The attached IOAS is automatically
- detached when the device is unbound from iommufd.
+   - The [de]attach_ioas callback is issued when the device is attached to
+ and detached from an IOAS managed by the bound iommufd. However, the
+ attached IOAS can also be automatically detached when the device is
+ unbound from iommufd.
 
- The read/write/mmap callbacks implement the device region access 
defined
  by the device's own VFIO_DEVICE_GET_REGION_INFO ioctl.
diff --git a/drivers/vfio/fsl-mc/vfio_fsl_mc.c 
b/drivers/vfio/fsl-mc/vfio_fsl_mc.c
index c89a047a4cd8..d540cf683d93 100644
--- a/drivers/vfio/fsl-mc/vfio_fsl_mc.c
+++ b/drivers/vfio/fsl-mc/vfio_fsl_mc.c
@@ -594,6 +594,7 @@ static const struct vfio_device_ops vfio_fsl_mc_ops = {
.bind_iommufd   = vfio_iommufd_physical_bind,
.unbind_iommufd = vfio_iommufd_physical_unbind,
.attach_ioas= vfio_iommufd_physical_attach_ioas,
+   .detach_ioas= vfio_iommufd_physical_detach_ioas,
 };
 
 static struct fsl_mc_driver vfio_fsl_mc_driver = {
diff --git a/drivers/vfio/iommufd.c b/drivers/vfio/iommufd.c
index 32a3a57ebb34..563818340a18 100644
--- a/drivers/vfio/iommufd.c
+++ b/drivers/vfio/iommufd.c
@@ -107,6 +107,14 @@ int vfio_iommufd_physical_attach_ioas(struct vfio_device 
*vdev, u32 *pt_id)
 {
int rc;
 
+   lockdep_assert_held(>dev_set->lock);
+
+   if (WARN_ON(!vdev->iommufd_device))
+   return -EINVAL;
+
+   if (vdev->iommufd_attached)
+   return -EBUSY;
+
rc = iommufd_device_attach(vdev->iommufd_device, pt_id);
if (rc)
return rc;
@@ -115,6 +123,18 @@ int vfio_iommufd_physical_attach_ioas(struct vfio_device 
*vdev, u32 *pt_id)
 }
 EXPORT_SYMBOL_GPL(vfio_iommufd_physical_attach_ioas);
 
+void vfio_iommufd_physical_detach_ioas(struct vfio_device *vdev)
+{
+   lockdep_assert_held(>dev_set->lock);
+
+   if (WARN_ON(!vdev->iommufd_device) || !vdev->iommufd_attached)
+   return;
+
+   iommufd_device_detach(vdev->iommufd_device);
+   vdev->iommufd_attached = false;
+}
+EXPORT_SYMBOL_GPL(vfio_iommufd_physical_detach_ioas);
+
 /*
  * The emulated standard ops mean that vfio_device is going to use the
  * "mdev path" and will call vfio_pin_pages()/vfio_dma_rw(). Drivers using this
diff --git a/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c 
b/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c
index a117eaf21c14..b2f9778c8366 100644
--- a/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c
+++ b/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c
@@ -1373,6 +1373,7 @@ static const struct vfio_device_ops 
hisi_acc_vfio_pci_migrn_ops = {
.bind_iommufd = vfio_iommufd_physical_bind,
.unbind_iommufd = vfio_iommufd_physical_unbind,
.attach_ioas = vfio_iommufd_physical_attach_ioas,
+   .detach_ioas = vfio_iommufd_physical_detach_ioas,
 };
 
 static const struct vfio_device_ops hisi_acc_vfio_pci_ops = {
@@ -1391,6 +1392,7 @@ static const struct vfio_device_ops hisi_acc_vfio_pci_ops 
= {
.bind_iommufd = vfio_iommufd_physical_bind,

[Intel-gfx] [PATCH v7 10/22] vfio: Make vfio_device_open() single open for device cdev path

2023-03-16 Thread Yi Liu
VFIO group has historically allowed multi-open of the device FD. This
was made secure because the "open" was executed via an ioctl to the
group FD which is itself only single open.

However, no known use of multiple device FDs today. It is kind of a
strange thing to do because new device FDs can naturally be created
via dup().

When we implement the new device uAPI (only used in cdev path) there is
no natural way to allow the device itself from being multi-opened in a
secure manner. Without the group FD we cannot prove the security context
of the opener.

Thus, when moving to the new uAPI we block the ability of opening
a device multiple times. Given old group path still allows it we store
a vfio_group pointer in struct vfio_device_file to differentiate.

Reviewed-by: Kevin Tian 
Signed-off-by: Yi Liu 
---
 drivers/vfio/group.c | 2 ++
 drivers/vfio/vfio.h  | 2 ++
 drivers/vfio/vfio_main.c | 7 +++
 3 files changed, 11 insertions(+)

diff --git a/drivers/vfio/group.c b/drivers/vfio/group.c
index 4de7a8fc3be1..c0065e359db6 100644
--- a/drivers/vfio/group.c
+++ b/drivers/vfio/group.c
@@ -245,6 +245,8 @@ static struct file *vfio_device_open_file(struct 
vfio_device *device)
goto err_out;
}
 
+   df->group = device->group;
+
ret = vfio_device_group_open(df);
if (ret)
goto err_free;
diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h
index b2f20b78a707..f1a448f9d067 100644
--- a/drivers/vfio/vfio.h
+++ b/drivers/vfio/vfio.h
@@ -18,6 +18,8 @@ struct vfio_container;
 
 struct vfio_device_file {
struct vfio_device *device;
+   struct vfio_group *group;
+
bool access_granted;
spinlock_t kvm_ref_lock; /* protect kvm field */
struct kvm *kvm;
diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c
index b515bbda4c74..b3b7e2436aec 100644
--- a/drivers/vfio/vfio_main.c
+++ b/drivers/vfio/vfio_main.c
@@ -477,6 +477,13 @@ int vfio_device_open(struct vfio_device_file *df)
 
lockdep_assert_held(>dev_set->lock);
 
+   /*
+* Only the group path allows the device opened multiple times.
+* The device cdev path doesn't have a secure way for it.
+*/
+   if (device->open_count != 0 && !df->group)
+   return -EINVAL;
+
device->open_count++;
if (device->open_count == 1) {
ret = vfio_device_first_open(df);
-- 
2.34.1



[Intel-gfx] [PATCH v7 11/22] vfio: Make vfio_device_first_open() to accept NULL iommufd for noiommu

2023-03-16 Thread Yi Liu
vfio_device_first_open() requires the caller to provide either a valid
iommufd (the group path in iommufd compat mode) or a valid container
(the group path in legacy container mode). As preparation for noiommu
support in device cdev path it's extended to allow both being NULL. The
caller is expected to verify noiommu permission before passing NULL
to this function.

Signed-off-by: Yi Liu 
---
 drivers/vfio/group.c |  8 
 drivers/vfio/vfio.h  |  1 +
 drivers/vfio/vfio_main.c | 12 
 3 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/drivers/vfio/group.c b/drivers/vfio/group.c
index c0065e359db6..36e105960dd8 100644
--- a/drivers/vfio/group.c
+++ b/drivers/vfio/group.c
@@ -771,6 +771,14 @@ void vfio_device_group_unregister(struct vfio_device 
*device)
mutex_unlock(>group->device_lock);
 }
 
+/* No group lock since df->group and df->group->container cannot change */
+bool vfio_device_group_uses_container(struct vfio_device_file *df)
+{
+   if (WARN_ON(!df->group))
+   return false;
+   return READ_ONCE(df->group->container);
+}
+
 int vfio_device_group_use_iommu(struct vfio_device *device)
 {
struct vfio_group *group = device->group;
diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h
index f1a448f9d067..7d4108cbc185 100644
--- a/drivers/vfio/vfio.h
+++ b/drivers/vfio/vfio.h
@@ -95,6 +95,7 @@ int vfio_device_set_group(struct vfio_device *device,
 void vfio_device_remove_group(struct vfio_device *device);
 void vfio_device_group_register(struct vfio_device *device);
 void vfio_device_group_unregister(struct vfio_device *device);
+bool vfio_device_group_uses_container(struct vfio_device_file *df);
 int vfio_device_group_use_iommu(struct vfio_device *device);
 void vfio_device_group_unuse_iommu(struct vfio_device *device);
 void vfio_device_group_close(struct vfio_device_file *df);
diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c
index b3b7e2436aec..6739203873a6 100644
--- a/drivers/vfio/vfio_main.c
+++ b/drivers/vfio/vfio_main.c
@@ -423,16 +423,20 @@ static int vfio_device_first_open(struct vfio_device_file 
*df)
 {
struct vfio_device *device = df->device;
struct iommufd_ctx *iommufd = df->iommufd;
-   int ret;
+   int ret = 0;
 
lockdep_assert_held(>dev_set->lock);
 
if (!try_module_get(device->dev->driver->owner))
return -ENODEV;
 
+   /*
+* if neither iommufd nor container is used the device is in
+* noiommu mode then just go ahead to open it.
+*/
if (iommufd)
ret = vfio_iommufd_bind(device, iommufd);
-   else
+   else if (vfio_device_group_uses_container(df))
ret = vfio_device_group_use_iommu(device);
if (ret)
goto err_module_put;
@@ -447,7 +451,7 @@ static int vfio_device_first_open(struct vfio_device_file 
*df)
 err_unuse_iommu:
if (iommufd)
vfio_iommufd_unbind(device);
-   else
+   else if (vfio_device_group_uses_container(df))
vfio_device_group_unuse_iommu(device);
 err_module_put:
module_put(device->dev->driver->owner);
@@ -465,7 +469,7 @@ static void vfio_device_last_close(struct vfio_device_file 
*df)
device->ops->close_device(device);
if (iommufd)
vfio_iommufd_unbind(device);
-   else
+   else if (vfio_device_group_uses_container(df))
vfio_device_group_unuse_iommu(device);
module_put(device->dev->driver->owner);
 }
-- 
2.34.1



[Intel-gfx] [PATCH v7 12/22] vfio-iommufd: Move noiommu support out of vfio_iommufd_bind()

2023-03-16 Thread Yi Liu
into vfio_device_group_open(). This is also more consistent with what
will be done in vfio device cdev path.

Signed-off-by: Yi Liu 
---
 drivers/vfio/group.c   |  9 +
 drivers/vfio/iommufd.c | 35 ++-
 drivers/vfio/vfio.h|  9 +
 3 files changed, 36 insertions(+), 17 deletions(-)

diff --git a/drivers/vfio/group.c b/drivers/vfio/group.c
index 36e105960dd8..1ad8df9b295f 100644
--- a/drivers/vfio/group.c
+++ b/drivers/vfio/group.c
@@ -192,6 +192,15 @@ static int vfio_device_group_open(struct vfio_device_file 
*df)
vfio_device_group_get_kvm_safe(device);
 
df->iommufd = device->group->iommufd;
+   if (device->group->iommufd && vfio_device_is_noiommu(device)) {
+   if (device->open_count == 0) {
+   ret = vfio_iommufd_enable_noiommu_compat(device,
+
device->group->iommufd);
+   if (ret)
+   goto out_put_kvm;
+   }
+   df->iommufd = NULL;
+   }
 
ret = vfio_device_open(df);
if (ret) {
diff --git a/drivers/vfio/iommufd.c b/drivers/vfio/iommufd.c
index ca0c16bb747e..7334b67dbb8a 100644
--- a/drivers/vfio/iommufd.c
+++ b/drivers/vfio/iommufd.c
@@ -10,6 +10,24 @@
 MODULE_IMPORT_NS(IOMMUFD);
 MODULE_IMPORT_NS(IOMMUFD_VFIO);
 
+int vfio_iommufd_enable_noiommu_compat(struct vfio_device *device,
+  struct iommufd_ctx *ictx)
+{
+   u32 ioas_id;
+
+   if (!capable(CAP_SYS_RAWIO))
+   return -EPERM;
+
+   /*
+* Require no compat ioas to be assigned to proceed.  The basic
+* statement is that the user cannot have done something that
+* implies they expected translation to exist
+*/
+   if (!iommufd_vfio_compat_ioas_get_id(ictx, _id))
+   return -EPERM;
+   return 0;
+}
+
 int vfio_iommufd_bind(struct vfio_device *vdev, struct iommufd_ctx *ictx)
 {
u32 ioas_id;
@@ -18,20 +36,6 @@ int vfio_iommufd_bind(struct vfio_device *vdev, struct 
iommufd_ctx *ictx)
 
lockdep_assert_held(>dev_set->lock);
 
-   if (vfio_device_is_noiommu(vdev)) {
-   if (!capable(CAP_SYS_RAWIO))
-   return -EPERM;
-
-   /*
-* Require no compat ioas to be assigned to proceed. The basic
-* statement is that the user cannot have done something that
-* implies they expected translation to exist
-*/
-   if (!iommufd_vfio_compat_ioas_get_id(ictx, _id))
-   return -EPERM;
-   return 0;
-   }
-
ret = vdev->ops->bind_iommufd(vdev, ictx, _id);
if (ret)
return ret;
@@ -59,9 +63,6 @@ void vfio_iommufd_unbind(struct vfio_device *vdev)
 {
lockdep_assert_held(>dev_set->lock);
 
-   if (vfio_device_is_noiommu(vdev))
-   return;
-
if (vdev->ops->unbind_iommufd)
vdev->ops->unbind_iommufd(vdev);
 }
diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h
index 7d4108cbc185..136137b8618d 100644
--- a/drivers/vfio/vfio.h
+++ b/drivers/vfio/vfio.h
@@ -236,9 +236,18 @@ static inline void vfio_container_cleanup(void)
 #endif
 
 #if IS_ENABLED(CONFIG_IOMMUFD)
+int vfio_iommufd_enable_noiommu_compat(struct vfio_device *device,
+  struct iommufd_ctx *ictx);
 int vfio_iommufd_bind(struct vfio_device *device, struct iommufd_ctx *ictx);
 void vfio_iommufd_unbind(struct vfio_device *device);
 #else
+static inline int
+vfio_iommufd_enable_noiommu_compat(struct vfio_device *device,
+  struct iommufd_ctx *ictx)
+{
+   return -EOPNOTSUPP;
+}
+
 static inline int vfio_iommufd_bind(struct vfio_device *device,
struct iommufd_ctx *ictx)
 {
-- 
2.34.1



[Intel-gfx] [PATCH v7 09/22] vfio: Add cdev_device_open_cnt to vfio_group

2023-03-16 Thread Yi Liu
for counting the devices that are opened via the cdev path. This count
is increased and decreased by the cdev path. The group path checks it
to achieve exclusion with the cdev path. With this, only one path (group
path or cdev path) will claim DMA ownership. This avoids scenarios in
which devices within the same group may be opened via different paths.

Reviewed-by: Kevin Tian 
Reviewed-by: Jason Gunthorpe 
Tested-by: Terrence Xu 
Tested-by: Nicolin Chen 
Tested-by: Matthew Rosato 
Signed-off-by: Yi Liu 
---
 drivers/vfio/group.c | 33 +
 drivers/vfio/vfio.h  |  3 +++
 2 files changed, 36 insertions(+)

diff --git a/drivers/vfio/group.c b/drivers/vfio/group.c
index 4f267ae7bebc..4de7a8fc3be1 100644
--- a/drivers/vfio/group.c
+++ b/drivers/vfio/group.c
@@ -383,6 +383,33 @@ static long vfio_group_fops_unl_ioctl(struct file *filep,
}
 }
 
+int vfio_device_block_group(struct vfio_device *device)
+{
+   struct vfio_group *group = device->group;
+   int ret = 0;
+
+   mutex_lock(>group_lock);
+   if (group->opened_file) {
+   ret = -EBUSY;
+   goto out_unlock;
+   }
+
+   group->cdev_device_open_cnt++;
+
+out_unlock:
+   mutex_unlock(>group_lock);
+   return ret;
+}
+
+void vfio_device_unblock_group(struct vfio_device *device)
+{
+   struct vfio_group *group = device->group;
+
+   mutex_lock(>group_lock);
+   group->cdev_device_open_cnt--;
+   mutex_unlock(>group_lock);
+}
+
 static int vfio_group_fops_open(struct inode *inode, struct file *filep)
 {
struct vfio_group *group =
@@ -405,6 +432,11 @@ static int vfio_group_fops_open(struct inode *inode, 
struct file *filep)
goto out_unlock;
}
 
+   if (group->cdev_device_open_cnt) {
+   ret = -EBUSY;
+   goto out_unlock;
+   }
+
/*
 * Do we need multiple instances of the group open?  Seems not.
 */
@@ -479,6 +511,7 @@ static void vfio_group_release(struct device *dev)
mutex_destroy(>device_lock);
mutex_destroy(>group_lock);
WARN_ON(group->iommu_group);
+   WARN_ON(group->cdev_device_open_cnt);
ida_free(_ida, MINOR(group->dev.devt));
kfree(group);
 }
diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h
index 854f2c97cb9a..b2f20b78a707 100644
--- a/drivers/vfio/vfio.h
+++ b/drivers/vfio/vfio.h
@@ -83,8 +83,11 @@ struct vfio_group {
struct blocking_notifier_head   notifier;
struct iommufd_ctx  *iommufd;
spinlock_t  kvm_ref_lock;
+   unsigned intcdev_device_open_cnt;
 };
 
+int vfio_device_block_group(struct vfio_device *device);
+void vfio_device_unblock_group(struct vfio_device *device);
 int vfio_device_set_group(struct vfio_device *device,
  enum vfio_group_type type);
 void vfio_device_remove_group(struct vfio_device *device);
-- 
2.34.1



[Intel-gfx] [PATCH v7 14/22] vfio: Record devid in vfio_device_file

2023-03-16 Thread Yi Liu
.bind_iommufd() will generate an ID to represent this bond, which is
needed by userspace for further usage. Store devid in vfio_device_file
to avoid passing the pointer in multiple places.

Signed-off-by: Yi Liu 
---
 drivers/vfio/iommufd.c   | 12 +++-
 drivers/vfio/vfio.h  | 10 +-
 drivers/vfio/vfio_main.c |  6 +++---
 3 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/drivers/vfio/iommufd.c b/drivers/vfio/iommufd.c
index 2daef60fe439..32a3a57ebb34 100644
--- a/drivers/vfio/iommufd.c
+++ b/drivers/vfio/iommufd.c
@@ -28,14 +28,14 @@ int vfio_iommufd_enable_noiommu_compat(struct vfio_device 
*device,
return 0;
 }
 
-int vfio_iommufd_bind(struct vfio_device *vdev, struct iommufd_ctx *ictx)
+int vfio_iommufd_bind(struct vfio_device_file *df)
 {
-   u32 device_id;
+   struct vfio_device *vdev = df->device;
+   struct iommufd_ctx *ictx = df->iommufd;
 
lockdep_assert_held(>dev_set->lock);
 
-   /* The legacy path has no way to return the device id */
-   return vdev->ops->bind_iommufd(vdev, ictx, _id);
+   return vdev->ops->bind_iommufd(vdev, ictx, >devid);
 }
 
 int vfio_iommufd_attach_compat_ioas(struct vfio_device *vdev,
@@ -54,8 +54,10 @@ int vfio_iommufd_attach_compat_ioas(struct vfio_device *vdev,
return vdev->ops->attach_ioas(vdev, _id);
 }
 
-void vfio_iommufd_unbind(struct vfio_device *vdev)
+void vfio_iommufd_unbind(struct vfio_device_file *df)
 {
+   struct vfio_device *vdev = df->device;
+
lockdep_assert_held(>dev_set->lock);
 
if (vdev->ops->unbind_iommufd)
diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h
index abfaf85cc266..b47b186573ac 100644
--- a/drivers/vfio/vfio.h
+++ b/drivers/vfio/vfio.h
@@ -24,6 +24,7 @@ struct vfio_device_file {
spinlock_t kvm_ref_lock; /* protect kvm field */
struct kvm *kvm;
struct iommufd_ctx *iommufd; /* protected by struct 
vfio_device_set::lock */
+   u32 devid; /* only valid when iommufd is valid */
 };
 
 void vfio_device_put_registration(struct vfio_device *device);
@@ -240,8 +241,8 @@ int vfio_iommufd_enable_noiommu_compat(struct vfio_device 
*device,
   struct iommufd_ctx *ictx);
 int vfio_iommufd_attach_compat_ioas(struct vfio_device *device,
struct iommufd_ctx *ictx);
-int vfio_iommufd_bind(struct vfio_device *device, struct iommufd_ctx *ictx);
-void vfio_iommufd_unbind(struct vfio_device *device);
+int vfio_iommufd_bind(struct vfio_device_file *df);
+void vfio_iommufd_unbind(struct vfio_device_file *df);
 #else
 static inline int
 vfio_iommufd_enable_noiommu_compat(struct vfio_device *device,
@@ -257,13 +258,12 @@ vfio_iommufd_attach_compat_ioas(struct vfio_device 
*device,
return -EOPNOTSUPP;
 }
 
-static inline int vfio_iommufd_bind(struct vfio_device *device,
-   struct iommufd_ctx *ictx)
+static inline int vfio_iommufd_bind(struct vfio_device_file *df)
 {
return -EOPNOTSUPP;
 }
 
-static inline void vfio_iommufd_unbind(struct vfio_device *device)
+static inline void vfio_iommufd_unbind(struct vfio_device_file *df)
 {
 }
 #endif
diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c
index 6739203873a6..d54c03248794 100644
--- a/drivers/vfio/vfio_main.c
+++ b/drivers/vfio/vfio_main.c
@@ -435,7 +435,7 @@ static int vfio_device_first_open(struct vfio_device_file 
*df)
 * noiommu mode then just go ahead to open it.
 */
if (iommufd)
-   ret = vfio_iommufd_bind(device, iommufd);
+   ret = vfio_iommufd_bind(df);
else if (vfio_device_group_uses_container(df))
ret = vfio_device_group_use_iommu(device);
if (ret)
@@ -450,7 +450,7 @@ static int vfio_device_first_open(struct vfio_device_file 
*df)
 
 err_unuse_iommu:
if (iommufd)
-   vfio_iommufd_unbind(device);
+   vfio_iommufd_unbind(df);
else if (vfio_device_group_uses_container(df))
vfio_device_group_unuse_iommu(device);
 err_module_put:
@@ -468,7 +468,7 @@ static void vfio_device_last_close(struct vfio_device_file 
*df)
if (device->ops->close_device)
device->ops->close_device(device);
if (iommufd)
-   vfio_iommufd_unbind(device);
+   vfio_iommufd_unbind(df);
else if (vfio_device_group_uses_container(df))
vfio_device_group_unuse_iommu(device);
module_put(device->dev->driver->owner);
-- 
2.34.1



[Intel-gfx] [PATCH v7 07/22] vfio: Pass struct vfio_device_file * to vfio_device_open/close()

2023-03-16 Thread Yi Liu
This avoids passing too much parameters in multiple functions.

Reviewed-by: Kevin Tian 
Reviewed-by: Jason Gunthorpe 
Tested-by: Terrence Xu 
Tested-by: Nicolin Chen 
Tested-by: Matthew Rosato 
Signed-off-by: Yi Liu 
---
 drivers/vfio/group.c | 20 ++--
 drivers/vfio/vfio.h  |  8 
 drivers/vfio/vfio_main.c | 25 +++--
 3 files changed, 33 insertions(+), 20 deletions(-)

diff --git a/drivers/vfio/group.c b/drivers/vfio/group.c
index 4f937ebaf6f7..9a7b2765eef6 100644
--- a/drivers/vfio/group.c
+++ b/drivers/vfio/group.c
@@ -169,8 +169,9 @@ static void vfio_device_group_get_kvm_safe(struct 
vfio_device *device)
spin_unlock(>group->kvm_ref_lock);
 }
 
-static int vfio_device_group_open(struct vfio_device *device)
+static int vfio_device_group_open(struct vfio_device_file *df)
 {
+   struct vfio_device *device = df->device;
int ret;
 
mutex_lock(>group->group_lock);
@@ -190,7 +191,11 @@ static int vfio_device_group_open(struct vfio_device 
*device)
if (device->open_count == 0)
vfio_device_group_get_kvm_safe(device);
 
-   ret = vfio_device_open(device, device->group->iommufd);
+   df->iommufd = device->group->iommufd;
+
+   ret = vfio_device_open(df);
+   if (ret)
+   df->iommufd = NULL;
 
if (device->open_count == 0)
vfio_device_put_kvm(device);
@@ -202,12 +207,15 @@ static int vfio_device_group_open(struct vfio_device 
*device)
return ret;
 }
 
-void vfio_device_group_close(struct vfio_device *device)
+void vfio_device_group_close(struct vfio_device_file *df)
 {
+   struct vfio_device *device = df->device;
+
mutex_lock(>group->group_lock);
mutex_lock(>dev_set->lock);
 
-   vfio_device_close(device, device->group->iommufd);
+   vfio_device_close(df);
+   df->iommufd = NULL;
 
if (device->open_count == 0)
vfio_device_put_kvm(device);
@@ -228,7 +236,7 @@ static struct file *vfio_device_open_file(struct 
vfio_device *device)
goto err_out;
}
 
-   ret = vfio_device_group_open(device);
+   ret = vfio_device_group_open(df);
if (ret)
goto err_free;
 
@@ -260,7 +268,7 @@ static struct file *vfio_device_open_file(struct 
vfio_device *device)
return filep;
 
 err_close_device:
-   vfio_device_group_close(device);
+   vfio_device_group_close(df);
 err_free:
kfree(df);
 err_out:
diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h
index e4672d91a6f7..cffc08f5a6f1 100644
--- a/drivers/vfio/vfio.h
+++ b/drivers/vfio/vfio.h
@@ -20,13 +20,13 @@ struct vfio_device_file {
struct vfio_device *device;
spinlock_t kvm_ref_lock; /* protect kvm field */
struct kvm *kvm;
+   struct iommufd_ctx *iommufd; /* protected by struct 
vfio_device_set::lock */
 };
 
 void vfio_device_put_registration(struct vfio_device *device);
 bool vfio_device_try_get_registration(struct vfio_device *device);
-int vfio_device_open(struct vfio_device *device, struct iommufd_ctx *iommufd);
-void vfio_device_close(struct vfio_device *device,
-  struct iommufd_ctx *iommufd);
+int vfio_device_open(struct vfio_device_file *df);
+void vfio_device_close(struct vfio_device_file *df);
 struct vfio_device_file *
 vfio_allocate_device_file(struct vfio_device *device);
 
@@ -91,7 +91,7 @@ void vfio_device_group_register(struct vfio_device *device);
 void vfio_device_group_unregister(struct vfio_device *device);
 int vfio_device_group_use_iommu(struct vfio_device *device);
 void vfio_device_group_unuse_iommu(struct vfio_device *device);
-void vfio_device_group_close(struct vfio_device *device);
+void vfio_device_group_close(struct vfio_device_file *df);
 struct vfio_group *vfio_group_from_file(struct file *file);
 bool vfio_group_has_dev(struct vfio_group *group, struct vfio_device *device);
 bool vfio_group_enforced_coherent(struct vfio_group *group);
diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c
index cb543791b28b..2ea6cb6d03c7 100644
--- a/drivers/vfio/vfio_main.c
+++ b/drivers/vfio/vfio_main.c
@@ -419,9 +419,10 @@ vfio_allocate_device_file(struct vfio_device *device)
return df;
 }
 
-static int vfio_device_first_open(struct vfio_device *device,
- struct iommufd_ctx *iommufd)
+static int vfio_device_first_open(struct vfio_device_file *df)
 {
+   struct vfio_device *device = df->device;
+   struct iommufd_ctx *iommufd = df->iommufd;
int ret;
 
lockdep_assert_held(>dev_set->lock);
@@ -453,9 +454,11 @@ static int vfio_device_first_open(struct vfio_device 
*device,
return ret;
 }
 
-static void vfio_device_last_close(struct vfio_device *device,
-  struct iommufd_ctx *iommufd)
+static void vfio_device_last_close(struct vfio_device_file *df)
 {
+   struct vfio_device *device = df->device;
+   struct 

[Intel-gfx] [PATCH v7 08/22] vfio: Block device access via device fd until device is opened

2023-03-16 Thread Yi Liu
Allow the vfio_device file to be in a state where the device FD is
opened but the device cannot be used by userspace (i.e. its .open_device()
hasn't been called). This inbetween state is not used when the device
FD is spawned from the group FD, however when we create the device FD
directly by opening a cdev it will be opened in the blocked state.

The reason for the inbetween state is that userspace only gets a FD but
doesn't gain access permission until binding the FD to an iommufd. So in
the blocked state, only the bind operation is allowed. Completing bind
will allow user to further access the device.

This is implemented by adding a flag in struct vfio_device_file to mark
the blocked state and using a simple smp_load_acquire() to obtain the
flag value and serialize all the device setup with the thread accessing
this device.

Following this lockless scheme, it can safely handle the device FD
unbound->bound but it cannot handle bound->unbound. To allow this we'd
need to add a lock on all the vfio ioctls which seems costly. So once
device FD is bound, it remains bound until the FD is closed.

Suggested-by: Jason Gunthorpe 
Reviewed-by: Kevin Tian 
Reviewed-by: Jason Gunthorpe 
Tested-by: Terrence Xu 
Tested-by: Nicolin Chen 
Tested-by: Matthew Rosato 
Signed-off-by: Yi Liu 
---
 drivers/vfio/group.c | 11 ++-
 drivers/vfio/vfio.h  |  1 +
 drivers/vfio/vfio_main.c | 41 ++--
 3 files changed, 46 insertions(+), 7 deletions(-)

diff --git a/drivers/vfio/group.c b/drivers/vfio/group.c
index 9a7b2765eef6..4f267ae7bebc 100644
--- a/drivers/vfio/group.c
+++ b/drivers/vfio/group.c
@@ -194,9 +194,18 @@ static int vfio_device_group_open(struct vfio_device_file 
*df)
df->iommufd = device->group->iommufd;
 
ret = vfio_device_open(df);
-   if (ret)
+   if (ret) {
df->iommufd = NULL;
+   goto out_put_kvm;
+   }
+
+   /*
+* Paired with smp_load_acquire() in vfio_device_fops::ioctl/
+* read/write/mmap
+*/
+   smp_store_release(>access_granted, true);
 
+out_put_kvm:
if (device->open_count == 0)
vfio_device_put_kvm(device);
 
diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h
index cffc08f5a6f1..854f2c97cb9a 100644
--- a/drivers/vfio/vfio.h
+++ b/drivers/vfio/vfio.h
@@ -18,6 +18,7 @@ struct vfio_container;
 
 struct vfio_device_file {
struct vfio_device *device;
+   bool access_granted;
spinlock_t kvm_ref_lock; /* protect kvm field */
struct kvm *kvm;
struct iommufd_ctx *iommufd; /* protected by struct 
vfio_device_set::lock */
diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c
index 2ea6cb6d03c7..b515bbda4c74 100644
--- a/drivers/vfio/vfio_main.c
+++ b/drivers/vfio/vfio_main.c
@@ -1114,6 +1114,10 @@ static long vfio_device_fops_unl_ioctl(struct file 
*filep,
struct vfio_device *device = df->device;
int ret;
 
+   /* Paired with smp_store_release() following vfio_device_open() */
+   if (!smp_load_acquire(>access_granted))
+   return -EINVAL;
+
ret = vfio_device_pm_runtime_get(device);
if (ret)
return ret;
@@ -1141,6 +1145,10 @@ static ssize_t vfio_device_fops_read(struct file *filep, 
char __user *buf,
struct vfio_device_file *df = filep->private_data;
struct vfio_device *device = df->device;
 
+   /* Paired with smp_store_release() following vfio_device_open() */
+   if (!smp_load_acquire(>access_granted))
+   return -EINVAL;
+
if (unlikely(!device->ops->read))
return -EINVAL;
 
@@ -1154,6 +1162,10 @@ static ssize_t vfio_device_fops_write(struct file *filep,
struct vfio_device_file *df = filep->private_data;
struct vfio_device *device = df->device;
 
+   /* Paired with smp_store_release() following vfio_device_open() */
+   if (!smp_load_acquire(>access_granted))
+   return -EINVAL;
+
if (unlikely(!device->ops->write))
return -EINVAL;
 
@@ -1165,6 +1177,10 @@ static int vfio_device_fops_mmap(struct file *filep, 
struct vm_area_struct *vma)
struct vfio_device_file *df = filep->private_data;
struct vfio_device *device = df->device;
 
+   /* Paired with smp_store_release() following vfio_device_open() */
+   if (!smp_load_acquire(>access_granted))
+   return -EINVAL;
+
if (unlikely(!device->ops->mmap))
return -EINVAL;
 
@@ -1201,6 +1217,24 @@ bool vfio_file_is_valid(struct file *file)
 }
 EXPORT_SYMBOL_GPL(vfio_file_is_valid);
 
+/*
+ * Return true if the input file is a vfio device file and has opened
+ * the input device. Otherwise, return false.
+ */
+static bool vfio_file_has_device_access(struct file *file,
+   struct vfio_device *device)
+{
+   struct vfio_device *vdev = vfio_device_from_file(file);
+   struct 

[Intel-gfx] [PATCH v7 06/22] kvm/vfio: Accept vfio device file from userspace

2023-03-16 Thread Yi Liu
This defines KVM_DEV_VFIO_FILE* and make alias with KVM_DEV_VFIO_GROUP*.
Old userspace uses KVM_DEV_VFIO_GROUP* works as well.

Reviewed-by: Jason Gunthorpe 
Tested-by: Terrence Xu 
Tested-by: Nicolin Chen 
Tested-by: Matthew Rosato 
Signed-off-by: Yi Liu 
---
 Documentation/virt/kvm/devices/vfio.rst | 52 +
 include/uapi/linux/kvm.h| 16 ++--
 virt/kvm/vfio.c | 16 
 3 files changed, 55 insertions(+), 29 deletions(-)

diff --git a/Documentation/virt/kvm/devices/vfio.rst 
b/Documentation/virt/kvm/devices/vfio.rst
index 79b6811bb4f3..5b05b48abaab 100644
--- a/Documentation/virt/kvm/devices/vfio.rst
+++ b/Documentation/virt/kvm/devices/vfio.rst
@@ -9,24 +9,37 @@ Device types supported:
   - KVM_DEV_TYPE_VFIO
 
 Only one VFIO instance may be created per VM.  The created device
-tracks VFIO groups in use by the VM and features of those groups
-important to the correctness and acceleration of the VM.  As groups
-are enabled and disabled for use by the VM, KVM should be updated
-about their presence.  When registered with KVM, a reference to the
-VFIO-group is held by KVM.
+tracks VFIO files (group or device) in use by the VM and features
+of those groups/devices important to the correctness and acceleration
+of the VM.  As groups/devices are enabled and disabled for use by the
+VM, KVM should be updated about their presence.  When registered with
+KVM, a reference to the VFIO file is held by KVM.
 
 Groups:
-  KVM_DEV_VFIO_GROUP
-
-KVM_DEV_VFIO_GROUP attributes:
-  KVM_DEV_VFIO_GROUP_ADD: Add a VFIO group to VFIO-KVM device tracking
-   kvm_device_attr.addr points to an int32_t file descriptor
-   for the VFIO group.
-  KVM_DEV_VFIO_GROUP_DEL: Remove a VFIO group from VFIO-KVM device tracking
-   kvm_device_attr.addr points to an int32_t file descriptor
-   for the VFIO group.
-  KVM_DEV_VFIO_GROUP_SET_SPAPR_TCE: attaches a guest visible TCE table
+  KVM_DEV_VFIO_FILE
+   alias: KVM_DEV_VFIO_GROUP
+
+KVM_DEV_VFIO_FILE attributes:
+  KVM_DEV_VFIO_FILE_ADD: Add a VFIO file (group/device) to VFIO-KVM device
+   tracking
+
+   alias: KVM_DEV_VFIO_GROUP_ADD
+
+   kvm_device_attr.addr points to an int32_t file descriptor for the
+   VFIO file.
+  KVM_DEV_VFIO_FILE_DEL: Remove a VFIO file (group/device) from VFIO-KVM
+   device tracking
+
+   alias: KVM_DEV_VFIO_GROUP_DEL
+
+   kvm_device_attr.addr points to an int32_t file descriptor for the
+   VFIO file.
+
+  KVM_DEV_VFIO_FILE_SET_SPAPR_TCE: attaches a guest visible TCE table
allocated by sPAPR KVM.
+
+   alias: KVM_DEV_VFIO_GROUP_SET_SPAPR_TCE
+
kvm_device_attr.addr points to a struct::
 
struct kvm_vfio_spapr_tce {
@@ -40,9 +53,14 @@ KVM_DEV_VFIO_GROUP attributes:
- @tablefd is a file descriptor for a TCE table allocated via
  KVM_CREATE_SPAPR_TCE.
 
+   only accepts vfio group file as SPAPR has no iommufd support
+
 ::
 
-The GROUP_ADD operation above should be invoked prior to accessing the
+The FILE/GROUP_ADD operation above should be invoked prior to accessing the
 device file descriptor via VFIO_GROUP_GET_DEVICE_FD in order to support
 drivers which require a kvm pointer to be set in their .open_device()
-callback.
+callback.  It is the same for device file descriptor via character device
+open which gets device access via VFIO_DEVICE_BIND_IOMMUFD.  For such file
+descriptors, FILE_ADD should be invoked before VFIO_DEVICE_BIND_IOMMUFD
+to support the drivers mentioned in piror sentence as well.
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index d77aef872a0a..a8eeca70a498 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -1410,10 +1410,18 @@ struct kvm_device_attr {
__u64   addr;   /* userspace address of attr data */
 };
 
-#define  KVM_DEV_VFIO_GROUP1
-#define   KVM_DEV_VFIO_GROUP_ADD   1
-#define   KVM_DEV_VFIO_GROUP_DEL   2
-#define   KVM_DEV_VFIO_GROUP_SET_SPAPR_TCE 3
+#define  KVM_DEV_VFIO_FILE 1
+
+#define   KVM_DEV_VFIO_FILE_ADD1
+#define   KVM_DEV_VFIO_FILE_DEL2
+#define   KVM_DEV_VFIO_FILE_SET_SPAPR_TCE  3
+
+/* KVM_DEV_VFIO_GROUP aliases are for compile time uapi compatibility */
+#define  KVM_DEV_VFIO_GROUPKVM_DEV_VFIO_FILE
+
+#define   KVM_DEV_VFIO_GROUP_ADD   KVM_DEV_VFIO_FILE_ADD
+#define   KVM_DEV_VFIO_GROUP_DEL   KVM_DEV_VFIO_FILE_DEL
+#define   KVM_DEV_VFIO_GROUP_SET_SPAPR_TCE KVM_DEV_VFIO_FILE_SET_SPAPR_TCE
 
 enum kvm_device_type {
KVM_DEV_TYPE_FSL_MPIC_20= 1,
diff --git a/virt/kvm/vfio.c b/virt/kvm/vfio.c
index 857d6ba349e1..d869913baafd 100644
--- a/virt/kvm/vfio.c
+++ b/virt/kvm/vfio.c
@@ -286,18 +286,18 @@ static int kvm_vfio_set_file(struct kvm_device *dev, long 
attr,
int32_t fd;
 
switch (attr) {
-   case 

[Intel-gfx] [PATCH v7 05/22] kvm/vfio: Rename kvm_vfio_group to prepare for accepting vfio device fd

2023-03-16 Thread Yi Liu
Meanwhile, rename related helpers. No functional change is intended.

Reviewed-by: Kevin Tian 
Reviewed-by: Eric Auger 
Reviewed-by: Jason Gunthorpe 
Tested-by: Terrence Xu 
Tested-by: Nicolin Chen 
Tested-by: Matthew Rosato 
Signed-off-by: Yi Liu 
---
 virt/kvm/vfio.c | 115 
 1 file changed, 58 insertions(+), 57 deletions(-)

diff --git a/virt/kvm/vfio.c b/virt/kvm/vfio.c
index 8bac308ba630..857d6ba349e1 100644
--- a/virt/kvm/vfio.c
+++ b/virt/kvm/vfio.c
@@ -21,7 +21,7 @@
 #include 
 #endif
 
-struct kvm_vfio_group {
+struct kvm_vfio_file {
struct list_head node;
struct file *file;
 #ifdef CONFIG_SPAPR_TCE_IOMMU
@@ -30,7 +30,7 @@ struct kvm_vfio_group {
 };
 
 struct kvm_vfio {
-   struct list_head group_list;
+   struct list_head file_list;
struct mutex lock;
bool noncoherent;
 };
@@ -98,34 +98,35 @@ static struct iommu_group *kvm_vfio_file_iommu_group(struct 
file *file)
 }
 
 static void kvm_spapr_tce_release_vfio_group(struct kvm *kvm,
-struct kvm_vfio_group *kvg)
+struct kvm_vfio_file *kvf)
 {
-   if (WARN_ON_ONCE(!kvg->iommu_group))
+   if (WARN_ON_ONCE(!kvf->iommu_group))
return;
 
-   kvm_spapr_tce_release_iommu_group(kvm, kvg->iommu_group);
-   iommu_group_put(kvg->iommu_group);
-   kvg->iommu_group = NULL;
+   kvm_spapr_tce_release_iommu_group(kvm, kvf->iommu_group);
+   iommu_group_put(kvf->iommu_group);
+   kvf->iommu_group = NULL;
 }
 #endif
 
 /*
- * Groups can use the same or different IOMMU domains.  If the same then
- * adding a new group may change the coherency of groups we've previously
- * been told about.  We don't want to care about any of that so we retest
- * each group and bail as soon as we find one that's noncoherent.  This
- * means we only ever [un]register_noncoherent_dma once for the whole device.
+ * Groups/devices can use the same or different IOMMU domains. If the same
+ * then adding a new group/device may change the coherency of groups/devices
+ * we've previously been told about. We don't want to care about any of
+ * that so we retest each group/device and bail as soon as we find one that's
+ * noncoherent.  This means we only ever [un]register_noncoherent_dma once
+ * for the whole device.
  */
 static void kvm_vfio_update_coherency(struct kvm_device *dev)
 {
struct kvm_vfio *kv = dev->private;
bool noncoherent = false;
-   struct kvm_vfio_group *kvg;
+   struct kvm_vfio_file *kvf;
 
mutex_lock(>lock);
 
-   list_for_each_entry(kvg, >group_list, node) {
-   if (!kvm_vfio_file_enforced_coherent(kvg->file)) {
+   list_for_each_entry(kvf, >file_list, node) {
+   if (!kvm_vfio_file_enforced_coherent(kvf->file)) {
noncoherent = true;
break;
}
@@ -143,10 +144,10 @@ static void kvm_vfio_update_coherency(struct kvm_device 
*dev)
mutex_unlock(>lock);
 }
 
-static int kvm_vfio_group_add(struct kvm_device *dev, unsigned int fd)
+static int kvm_vfio_file_add(struct kvm_device *dev, unsigned int fd)
 {
struct kvm_vfio *kv = dev->private;
-   struct kvm_vfio_group *kvg;
+   struct kvm_vfio_file *kvf;
struct file *filp;
int ret;
 
@@ -162,27 +163,27 @@ static int kvm_vfio_group_add(struct kvm_device *dev, 
unsigned int fd)
 
mutex_lock(>lock);
 
-   list_for_each_entry(kvg, >group_list, node) {
-   if (kvg->file == filp) {
+   list_for_each_entry(kvf, >file_list, node) {
+   if (kvf->file == filp) {
ret = -EEXIST;
goto err_unlock;
}
}
 
-   kvg = kzalloc(sizeof(*kvg), GFP_KERNEL_ACCOUNT);
-   if (!kvg) {
+   kvf = kzalloc(sizeof(*kvf), GFP_KERNEL_ACCOUNT);
+   if (!kvf) {
ret = -ENOMEM;
goto err_unlock;
}
 
-   kvg->file = filp;
-   list_add_tail(>node, >group_list);
+   kvf->file = filp;
+   list_add_tail(>node, >file_list);
 
kvm_arch_start_assignment(dev->kvm);
 
mutex_unlock(>lock);
 
-   kvm_vfio_file_set_kvm(kvg->file, dev->kvm);
+   kvm_vfio_file_set_kvm(kvf->file, dev->kvm);
kvm_vfio_update_coherency(dev);
 
return 0;
@@ -193,10 +194,10 @@ static int kvm_vfio_group_add(struct kvm_device *dev, 
unsigned int fd)
return ret;
 }
 
-static int kvm_vfio_group_del(struct kvm_device *dev, unsigned int fd)
+static int kvm_vfio_file_del(struct kvm_device *dev, unsigned int fd)
 {
struct kvm_vfio *kv = dev->private;
-   struct kvm_vfio_group *kvg;
+   struct kvm_vfio_file *kvf;
struct fd f;
int ret;
 
@@ -208,18 +209,18 @@ static int kvm_vfio_group_del(struct kvm_device *dev, 
unsigned int fd)
 
mutex_lock(>lock);
 
-   

[Intel-gfx] [PATCH v7 04/22] vfio: Accept vfio device file in the KVM facing kAPI

2023-03-16 Thread Yi Liu
This makes the vfio file kAPIs to accept vfio device files, also a
preparation for vfio device cdev support.

For the kvm set with vfio device file, kvm pointer is stored in struct
vfio_device_file, and use kvm_ref_lock to protect kvm set and kvm
pointer usage within VFIO. This kvm pointer will be set to vfio_device
after device file is bound to iommufd in the cdev path.

Reviewed-by: Kevin Tian 
Reviewed-by: Jason Gunthorpe 
Tested-by: Terrence Xu 
Tested-by: Nicolin Chen 
Tested-by: Matthew Rosato 
Signed-off-by: Yi Liu 
---
 drivers/vfio/vfio.h  |  2 ++
 drivers/vfio/vfio_main.c | 18 ++
 2 files changed, 20 insertions(+)

diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h
index 56ad127ac618..e4672d91a6f7 100644
--- a/drivers/vfio/vfio.h
+++ b/drivers/vfio/vfio.h
@@ -18,6 +18,8 @@ struct vfio_container;
 
 struct vfio_device_file {
struct vfio_device *device;
+   spinlock_t kvm_ref_lock; /* protect kvm field */
+   struct kvm *kvm;
 };
 
 void vfio_device_put_registration(struct vfio_device *device);
diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c
index 748bde4d74d9..cb543791b28b 100644
--- a/drivers/vfio/vfio_main.c
+++ b/drivers/vfio/vfio_main.c
@@ -414,6 +414,7 @@ vfio_allocate_device_file(struct vfio_device *device)
return ERR_PTR(-ENOMEM);
 
df->device = device;
+   spin_lock_init(>kvm_ref_lock);
 
return df;
 }
@@ -1246,6 +1247,20 @@ bool vfio_file_enforced_coherent(struct file *file)
 }
 EXPORT_SYMBOL_GPL(vfio_file_enforced_coherent);
 
+static void vfio_device_file_set_kvm(struct file *file, struct kvm *kvm)
+{
+   struct vfio_device_file *df = file->private_data;
+
+   /*
+* The kvm is first recorded in the vfio_device_file, and will
+* be propagated to vfio_device::kvm when the file is bound to
+* iommufd successfully in the vfio device cdev path.
+*/
+   spin_lock(>kvm_ref_lock);
+   df->kvm = kvm;
+   spin_unlock(>kvm_ref_lock);
+}
+
 /**
  * vfio_file_set_kvm - Link a kvm with VFIO drivers
  * @file: VFIO group file or VFIO device file
@@ -1259,6 +1274,9 @@ void vfio_file_set_kvm(struct file *file, struct kvm *kvm)
group = vfio_group_from_file(file);
if (group)
vfio_group_set_kvm(group, kvm);
+
+   if (vfio_device_from_file(file))
+   vfio_device_file_set_kvm(file, kvm);
 }
 EXPORT_SYMBOL_GPL(vfio_file_set_kvm);
 
-- 
2.34.1



[Intel-gfx] [PATCH v7 01/22] vfio: Allocate per device file structure

2023-03-16 Thread Yi Liu
This is preparation for adding vfio device cdev support. vfio device
cdev requires:
1) A per device file memory to store the kvm pointer set by KVM. It will
   be propagated to vfio_device:kvm after the device cdev file is bound
   to an iommufd.
2) A mechanism to block device access through device cdev fd before it
   is bound to an iommufd.

To address above requirements, this adds a per device file structure
named vfio_device_file. For now, it's only a wrapper of struct vfio_device
pointer. Other fields will be added to this per file structure in future
commits.

Reviewed-by: Kevin Tian 
Reviewed-by: Eric Auger 
Reviewed-by: Jason Gunthorpe 
Tested-by: Terrence Xu 
Tested-by: Nicolin Chen 
Tested-by: Matthew Rosato 
Signed-off-by: Yi Liu 
---
 drivers/vfio/group.c | 13 +++--
 drivers/vfio/vfio.h  |  6 ++
 drivers/vfio/vfio_main.c | 35 ---
 3 files changed, 45 insertions(+), 9 deletions(-)

diff --git a/drivers/vfio/group.c b/drivers/vfio/group.c
index d0c95d033605..8a13cea43f49 100644
--- a/drivers/vfio/group.c
+++ b/drivers/vfio/group.c
@@ -218,19 +218,26 @@ void vfio_device_group_close(struct vfio_device *device)
 
 static struct file *vfio_device_open_file(struct vfio_device *device)
 {
+   struct vfio_device_file *df;
struct file *filep;
int ret;
 
+   df = vfio_allocate_device_file(device);
+   if (IS_ERR(df)) {
+   ret = PTR_ERR(df);
+   goto err_out;
+   }
+
ret = vfio_device_group_open(device);
if (ret)
-   goto err_out;
+   goto err_free;
 
/*
 * We can't use anon_inode_getfd() because we need to modify
 * the f_mode flags directly to allow more than just ioctls
 */
filep = anon_inode_getfile("[vfio-device]", _device_fops,
-  device, O_RDWR);
+  df, O_RDWR);
if (IS_ERR(filep)) {
ret = PTR_ERR(filep);
goto err_close_device;
@@ -254,6 +261,8 @@ static struct file *vfio_device_open_file(struct 
vfio_device *device)
 
 err_close_device:
vfio_device_group_close(device);
+err_free:
+   kfree(df);
 err_out:
return ERR_PTR(ret);
 }
diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h
index c0aeea24fbd6..250fbd3786c5 100644
--- a/drivers/vfio/vfio.h
+++ b/drivers/vfio/vfio.h
@@ -16,11 +16,17 @@ struct iommufd_ctx;
 struct iommu_group;
 struct vfio_container;
 
+struct vfio_device_file {
+   struct vfio_device *device;
+};
+
 void vfio_device_put_registration(struct vfio_device *device);
 bool vfio_device_try_get_registration(struct vfio_device *device);
 int vfio_device_open(struct vfio_device *device, struct iommufd_ctx *iommufd);
 void vfio_device_close(struct vfio_device *device,
   struct iommufd_ctx *iommufd);
+struct vfio_device_file *
+vfio_allocate_device_file(struct vfio_device *device);
 
 extern const struct file_operations vfio_device_fops;
 
diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c
index ebbb6b91a498..89722bf87edc 100644
--- a/drivers/vfio/vfio_main.c
+++ b/drivers/vfio/vfio_main.c
@@ -404,6 +404,20 @@ static bool vfio_assert_device_open(struct vfio_device 
*device)
return !WARN_ON_ONCE(!READ_ONCE(device->open_count));
 }
 
+struct vfio_device_file *
+vfio_allocate_device_file(struct vfio_device *device)
+{
+   struct vfio_device_file *df;
+
+   df = kzalloc(sizeof(*df), GFP_KERNEL_ACCOUNT);
+   if (!df)
+   return ERR_PTR(-ENOMEM);
+
+   df->device = device;
+
+   return df;
+}
+
 static int vfio_device_first_open(struct vfio_device *device,
  struct iommufd_ctx *iommufd)
 {
@@ -517,12 +531,15 @@ static inline void vfio_device_pm_runtime_put(struct 
vfio_device *device)
  */
 static int vfio_device_fops_release(struct inode *inode, struct file *filep)
 {
-   struct vfio_device *device = filep->private_data;
+   struct vfio_device_file *df = filep->private_data;
+   struct vfio_device *device = df->device;
 
vfio_device_group_close(device);
 
vfio_device_put_registration(device);
 
+   kfree(df);
+
return 0;
 }
 
@@ -1087,7 +1104,8 @@ static int vfio_ioctl_device_feature(struct vfio_device 
*device,
 static long vfio_device_fops_unl_ioctl(struct file *filep,
   unsigned int cmd, unsigned long arg)
 {
-   struct vfio_device *device = filep->private_data;
+   struct vfio_device_file *df = filep->private_data;
+   struct vfio_device *device = df->device;
int ret;
 
ret = vfio_device_pm_runtime_get(device);
@@ -1114,7 +1132,8 @@ static long vfio_device_fops_unl_ioctl(struct file *filep,
 static ssize_t vfio_device_fops_read(struct file *filep, char __user *buf,
 size_t count, loff_t *ppos)
 {
-   struct vfio_device *device = 

[Intel-gfx] [PATCH v7 03/22] vfio: Remove vfio_file_is_group()

2023-03-16 Thread Yi Liu
since no user of vfio_file_is_group() now.

Signed-off-by: Yi Liu 
---
 drivers/vfio/group.c | 10 --
 include/linux/vfio.h |  1 -
 2 files changed, 11 deletions(-)

diff --git a/drivers/vfio/group.c b/drivers/vfio/group.c
index ede4723c5f72..4f937ebaf6f7 100644
--- a/drivers/vfio/group.c
+++ b/drivers/vfio/group.c
@@ -792,16 +792,6 @@ struct iommu_group *vfio_file_iommu_group(struct file 
*file)
 }
 EXPORT_SYMBOL_GPL(vfio_file_iommu_group);
 
-/**
- * vfio_file_is_group - True if the file is a vfio group file
- * @file: VFIO group file
- */
-bool vfio_file_is_group(struct file *file)
-{
-   return vfio_group_from_file(file);
-}
-EXPORT_SYMBOL_GPL(vfio_file_is_group);
-
 bool vfio_group_enforced_coherent(struct vfio_group *group)
 {
struct vfio_device *device;
diff --git a/include/linux/vfio.h b/include/linux/vfio.h
index 5a2e8a9d538d..a689c64432b7 100644
--- a/include/linux/vfio.h
+++ b/include/linux/vfio.h
@@ -247,7 +247,6 @@ int vfio_mig_get_next_state(struct vfio_device *device,
  * External user API
  */
 struct iommu_group *vfio_file_iommu_group(struct file *file);
-bool vfio_file_is_group(struct file *file);
 bool vfio_file_is_valid(struct file *file);
 bool vfio_file_enforced_coherent(struct file *file);
 void vfio_file_set_kvm(struct file *file, struct kvm *kvm);
-- 
2.34.1



[Intel-gfx] [PATCH v7 02/22] vfio: Refine vfio file kAPIs for KVM

2023-03-16 Thread Yi Liu
This prepares for making the below kAPIs to accept both group file
and device file instead of only vfio group file.

  bool vfio_file_enforced_coherent(struct file *file);
  void vfio_file_set_kvm(struct file *file, struct kvm *kvm);

Reviewed-by: Kevin Tian 
Reviewed-by: Eric Auger 
Reviewed-by: Jason Gunthorpe 
Tested-by: Terrence Xu 
Tested-by: Nicolin Chen 
Tested-by: Matthew Rosato 
Signed-off-by: Yi Liu 
---
 drivers/vfio/group.c | 36 ++---
 drivers/vfio/vfio.h  |  2 ++
 drivers/vfio/vfio_main.c | 43 
 virt/kvm/vfio.c  | 10 +-
 4 files changed, 56 insertions(+), 35 deletions(-)

diff --git a/drivers/vfio/group.c b/drivers/vfio/group.c
index 8a13cea43f49..ede4723c5f72 100644
--- a/drivers/vfio/group.c
+++ b/drivers/vfio/group.c
@@ -802,24 +802,11 @@ bool vfio_file_is_group(struct file *file)
 }
 EXPORT_SYMBOL_GPL(vfio_file_is_group);
 
-/**
- * vfio_file_enforced_coherent - True if the DMA associated with the VFIO file
- *is always CPU cache coherent
- * @file: VFIO group file
- *
- * Enforced coherency means that the IOMMU ignores things like the PCIe 
no-snoop
- * bit in DMA transactions. A return of false indicates that the user has
- * rights to access additional instructions such as wbinvd on x86.
- */
-bool vfio_file_enforced_coherent(struct file *file)
+bool vfio_group_enforced_coherent(struct vfio_group *group)
 {
-   struct vfio_group *group = file->private_data;
struct vfio_device *device;
bool ret = true;
 
-   if (!vfio_file_is_group(file))
-   return true;
-
/*
 * If the device does not have IOMMU_CAP_ENFORCE_CACHE_COHERENCY then
 * any domain later attached to it will also not support it. If the cap
@@ -837,28 +824,17 @@ bool vfio_file_enforced_coherent(struct file *file)
mutex_unlock(>device_lock);
return ret;
 }
-EXPORT_SYMBOL_GPL(vfio_file_enforced_coherent);
 
-/**
- * vfio_file_set_kvm - Link a kvm with VFIO drivers
- * @file: VFIO group file
- * @kvm: KVM to link
- *
- * When a VFIO device is first opened the KVM will be available in
- * device->kvm if one was associated with the group.
- */
-void vfio_file_set_kvm(struct file *file, struct kvm *kvm)
+void vfio_group_set_kvm(struct vfio_group *group, struct kvm *kvm)
 {
-   struct vfio_group *group = file->private_data;
-
-   if (!vfio_file_is_group(file))
-   return;
-
+   /*
+* When a VFIO device is first opened the KVM will be available in
+* device->kvm if one was associated with the group.
+*/
spin_lock(>kvm_ref_lock);
group->kvm = kvm;
spin_unlock(>kvm_ref_lock);
 }
-EXPORT_SYMBOL_GPL(vfio_file_set_kvm);
 
 bool vfio_group_has_dev(struct vfio_group *group, struct vfio_device *device)
 {
diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h
index 250fbd3786c5..56ad127ac618 100644
--- a/drivers/vfio/vfio.h
+++ b/drivers/vfio/vfio.h
@@ -92,6 +92,8 @@ void vfio_device_group_unuse_iommu(struct vfio_device 
*device);
 void vfio_device_group_close(struct vfio_device *device);
 struct vfio_group *vfio_group_from_file(struct file *file);
 bool vfio_group_has_dev(struct vfio_group *group, struct vfio_device *device);
+bool vfio_group_enforced_coherent(struct vfio_group *group);
+void vfio_group_set_kvm(struct vfio_group *group, struct kvm *kvm);
 bool vfio_device_has_container(struct vfio_device *device);
 int __init vfio_group_init(void);
 void vfio_group_cleanup(void);
diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c
index 89722bf87edc..748bde4d74d9 100644
--- a/drivers/vfio/vfio_main.c
+++ b/drivers/vfio/vfio_main.c
@@ -1219,6 +1219,49 @@ bool vfio_file_has_dev(struct file *file, struct 
vfio_device *device)
 }
 EXPORT_SYMBOL_GPL(vfio_file_has_dev);
 
+/**
+ * vfio_file_enforced_coherent - True if the DMA associated with the VFIO file
+ *is always CPU cache coherent
+ * @file: VFIO group file or VFIO device file
+ *
+ * Enforced coherency means that the IOMMU ignores things like the PCIe 
no-snoop
+ * bit in DMA transactions. A return of false indicates that the user has
+ * rights to access additional instructions such as wbinvd on x86.
+ */
+bool vfio_file_enforced_coherent(struct file *file)
+{
+   struct vfio_group *group;
+   struct vfio_device *device;
+
+   group = vfio_group_from_file(file);
+   if (group)
+   return vfio_group_enforced_coherent(group);
+
+   device = vfio_device_from_file(file);
+   if (device)
+   return device_iommu_capable(device->dev,
+   IOMMU_CAP_ENFORCE_CACHE_COHERENCY);
+
+   return true;
+}
+EXPORT_SYMBOL_GPL(vfio_file_enforced_coherent);
+
+/**
+ * vfio_file_set_kvm - Link a kvm with VFIO drivers
+ * @file: VFIO group file or VFIO device file
+ * @kvm: KVM to link
+ *
+ */
+void vfio_file_set_kvm(struct file *file, struct kvm *kvm)
+{
+   

[Intel-gfx] [PATCH v7 00/22] Add vfio_device cdev for iommufd support

2023-03-16 Thread Yi Liu
Existing VFIO provides group-centric user APIs for userspace. Userspace
opens the /dev/vfio/$group_id first before getting device fd and hence
getting access to device. This is not the desired model for iommufd. Per
the conclusion of community discussion[1], iommufd provides device-centric
kAPIs and requires its consumer (like VFIO) to be device-centric user
APIs. Such user APIs are used to associate device with iommufd and also
the I/O address spaces managed by the iommufd.

This series first introduces a per device file structure to be prepared
for further enhancement and refactors the kvm-vfio code to be prepared
for accepting device file from userspace. Afte this, adds a mechanism for
blocking device access before iommufd bind. Then refactors the vfio to be
able to handle cdev path (e.g. iommufd binding, no-iommufd, [de]attach ioas).
This refactor includes making the device_open exclusive between group and
cdev path, only allow single device open in cdev path; vfio-iommufd code is
also refactored to support cdev. e.g. split the vfio_iommufd_bind() into
two steps. Eventually, adds the cdev support for vfio device and the new
ioctls, then makes group infrastructure optional as it is not needed when
vfio device cdev is compiled.

This series is based on some preparation works done to vfio emulated devices[2]
and vfio pci hot reset enhancements[3].

This series is a prerequisite for iommu nesting for vfio device[4] [5].

The complete code can be found in below branch, simple tests done to the
legacy group path and the cdev path. Draft QEMU branch can be found at[6]

https://github.com/yiliu1765/iommufd/tree/vfio_device_cdev_v7
(config CONFIG_IOMMUFD=y CONFIG_VFIO_DEVICE_CDEV=y)

base-commit: d28283a0c30d2f3c82d78fbe27f258671b6dc535

[1] 
https://lore.kernel.org/kvm/bn9pr11mb5433b1e4ae5b0480369f97178c...@bn9pr11mb5433.namprd11.prod.outlook.com/
[2] https://lore.kernel.org/kvm/20230316121526.5644-1-yi.l@intel.com/
[3] https://lore.kernel.org/kvm/20230316124156.12064-1-yi.l@intel.com/
[4] 
https://lore.kernel.org/linux-iommu/20230309080910.607396-1-yi.l@intel.com/
[5] 
https://lore.kernel.org/linux-iommu/20230309082207.612346-1-yi.l@intel.com/
[6] https://github.com/yiliu1765/qemu/tree/iommufd_rfcv3 (it is based on Eric's
QEMU iommufd rfcv3 
(https://lore.kernel.org/kvm/20230131205305.2726330-1-eric.au...@redhat.com/)
plus commits to align with vfio_device_cdev v7)

Change log:

v7:
 - Split the vfio-pci hot reset changes to be separate patch series (Jason, 
Kevin)
 - More polish on no-iommufd support (patch 11 - 13) in cdev path (Kevin)
 - iommufd_access_detach() in patch 16 is added by Nic for emulated devices 
(Kevin, Jason)

v6: https://lore.kernel.org/kvm/20230308132903.465159-1-yi.l@intel.com/#t
 - Add r-b from Jason on patch 01 - 08 and 13 in v5
 - Based on the prerequisite mini-series which makes vfio emulated devices
   be prepared to cdev (Jason)
 - Add the approach to pass a set of device fds to do hot reset ownership
   check, while the zero-length array approach is also kept. (Jason, Kevin, 
Alex)
 - Drop patch 10 of v5, it is reworked by patch 13 and 17 in v6 (Jason)
 - Store vfio_group pointer in vfio_device_file to check if user is using
   legacy vfio container (Jason)
 - Drop the is_cdev_device flag (introduced in patch 14 of v5) as the group
   pointer stored in vfio_device_file can cover it.
 - Add iommu_group check in the cdev no-iommu path patch 24 (Kevin)
 - Add t-b from Terrence, Nicolin and Matthew (thanks for the help, some patches
   are new in this version, so I just added t-b to the patches that are also
   in v5 and no big change, for others would add in this version).

v5: https://lore.kernel.org/kvm/2023022735.61728-1-yi.l@intel.com/
 - Add r-b from Kevin on patch 08, 13, 14, 15 and 17.
 - Rename patch 02 to limit the change for KVM facing kAPIs. The vfio pci
   hot reset path only accepts group file until patch 09. (Kevin)
 - Update comment around smp_load_acquire(>access_granted) (Yan)
 - Adopt Jason's suggestion on the vfio pci hot reset path, passing zero-length
   fd array to indicate using bound iommufd_ctx as ownership check. (Jason, 
Kevin)
 - Direct read df->access_granted value in vfio_device_cdev_close() (Kevin, 
Yan, Jason)
 - Wrap the iommufd get/put into a helper to refine the error path of
   vfio_device_ioctl_bind_iommufd(). (Yan)

v4: https://lore.kernel.org/kvm/20230221034812.138051-1-yi.l@intel.com/
 - Add r-b from Kevin on patch 09/10
 - Add a line in devices/vfio.rst to emphasize user should add group/device to
   KVM prior to invoke open_device op which may be called in the 
VFIO_GROUP_GET_DEVICE_FD
   or VFIO_DEVICE_BIND_IOMMUFD ioctl.
 - Modify VFIO_GROUP/VFIO_DEVICE_CDEV Kconfig dependency (Alex)
 - Select VFIO_GROUP for SPAPR (Jason)
 - Check device fully-opened in PCI hotreset path for device fd (Jason)
 - Set df->access_granted in the caller of vfio_device_open() since
   the caller may fail in other 

[Intel-gfx] [PATCH 6/7] vfio: Accpet device file from vfio PCI hot reset path

2023-03-16 Thread Yi Liu
This extends both vfio_file_is_valid() and vfio_file_has_dev() to accept
device file from the vfio PCI hot reset.

Signed-off-by: Yi Liu 
---
 drivers/vfio/vfio_main.c | 23 +++
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c
index fe7446805afd..ebbb6b91a498 100644
--- a/drivers/vfio/vfio_main.c
+++ b/drivers/vfio/vfio_main.c
@@ -1154,13 +1154,23 @@ const struct file_operations vfio_device_fops = {
.mmap   = vfio_device_fops_mmap,
 };
 
+static struct vfio_device *vfio_device_from_file(struct file *file)
+{
+   struct vfio_device *device = file->private_data;
+
+   if (file->f_op != _device_fops)
+   return NULL;
+   return device;
+}
+
 /**
  * vfio_file_is_valid - True if the file is valid vfio file
  * @file: VFIO group file or VFIO device file
  */
 bool vfio_file_is_valid(struct file *file)
 {
-   return vfio_group_from_file(file);
+   return vfio_group_from_file(file) ||
+  vfio_device_from_file(file);
 }
 EXPORT_SYMBOL_GPL(vfio_file_is_valid);
 
@@ -1174,12 +1184,17 @@ EXPORT_SYMBOL_GPL(vfio_file_is_valid);
 bool vfio_file_has_dev(struct file *file, struct vfio_device *device)
 {
struct vfio_group *group;
+   struct vfio_device *vdev;
 
group = vfio_group_from_file(file);
-   if (!group)
-   return false;
+   if (group)
+   return vfio_group_has_dev(group, device);
+
+   vdev = vfio_device_from_file(file);
+   if (vdev)
+   return vdev == device;
 
-   return vfio_group_has_dev(group, device);
+   return false;
 }
 EXPORT_SYMBOL_GPL(vfio_file_has_dev);
 
-- 
2.34.1



[Intel-gfx] [PATCH 4/7] vfio/pci: Renaming for accepting device fd in hot reset path

2023-03-16 Thread Yi Liu
No functional change is intended.

Signed-off-by: Yi Liu 
---
 drivers/vfio/pci/vfio_pci_core.c | 55 
 1 file changed, 28 insertions(+), 27 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
index b68fcba67a4b..b6b5624c8b15 100644
--- a/drivers/vfio/pci/vfio_pci_core.c
+++ b/drivers/vfio/pci/vfio_pci_core.c
@@ -177,10 +177,10 @@ static void vfio_pci_probe_mmaps(struct 
vfio_pci_core_device *vdev)
}
 }
 
-struct vfio_pci_group_info;
+struct vfio_pci_file_info;
 static void vfio_pci_dev_set_try_reset(struct vfio_device_set *dev_set);
 static int vfio_pci_dev_set_hot_reset(struct vfio_device_set *dev_set,
- struct vfio_pci_group_info *groups,
+ struct vfio_pci_file_info *info,
  struct iommufd_ctx *iommufd_ctx);
 
 /*
@@ -800,7 +800,7 @@ static int vfio_pci_fill_devs(struct pci_dev *pdev, void 
*data)
return 0;
 }
 
-struct vfio_pci_group_info {
+struct vfio_pci_file_info {
int count;
struct file **files;
 };
@@ -1257,14 +1257,14 @@ static int vfio_pci_ioctl_get_pci_hot_reset_info(
 }
 
 static int
-vfio_pci_ioctl_pci_hot_reset_groups(struct vfio_pci_core_device *vdev,
-   struct vfio_pci_hot_reset *hdr,
-   bool slot,
-   struct vfio_pci_hot_reset __user *arg)
+vfio_pci_ioctl_pci_hot_reset_files(struct vfio_pci_core_device *vdev,
+  struct vfio_pci_hot_reset *hdr,
+  bool slot,
+  struct vfio_pci_hot_reset __user *arg)
 {
-   int32_t *group_fds;
+   int32_t *fds;
struct file **files;
-   struct vfio_pci_group_info info;
+   struct vfio_pci_file_info info;
int file_idx, count = 0, ret = 0;
 
/*
@@ -1281,17 +1281,17 @@ vfio_pci_ioctl_pci_hot_reset_groups(struct 
vfio_pci_core_device *vdev,
if (hdr->count > count)
return -EINVAL;
 
-   group_fds = kcalloc(hdr->count, sizeof(*group_fds), GFP_KERNEL);
+   fds = kcalloc(hdr->count, sizeof(*fds), GFP_KERNEL);
files = kcalloc(hdr->count, sizeof(*files), GFP_KERNEL);
-   if (!group_fds || !files) {
-   kfree(group_fds);
+   if (!fds || !files) {
+   kfree(fds);
kfree(files);
return -ENOMEM;
}
 
-   if (copy_from_user(group_fds, arg->group_fds,
-  hdr->count * sizeof(*group_fds))) {
-   kfree(group_fds);
+   if (copy_from_user(fds, arg->group_fds,
+  hdr->count * sizeof(*fds))) {
+   kfree(fds);
kfree(files);
return -EFAULT;
}
@@ -1301,7 +1301,7 @@ vfio_pci_ioctl_pci_hot_reset_groups(struct 
vfio_pci_core_device *vdev,
 * the reset
 */
for (file_idx = 0; file_idx < hdr->count; file_idx++) {
-   struct file *file = fget(group_fds[file_idx]);
+   struct file *file = fget(fds[file_idx]);
 
if (!file) {
ret = -EBADF;
@@ -1318,9 +1318,9 @@ vfio_pci_ioctl_pci_hot_reset_groups(struct 
vfio_pci_core_device *vdev,
files[file_idx] = file;
}
 
-   kfree(group_fds);
+   kfree(fds);
 
-   /* release reference to groups on error */
+   /* release reference to fds on error */
if (ret)
goto hot_reset_release;
 
@@ -1358,7 +1358,7 @@ static int vfio_pci_ioctl_pci_hot_reset(struct 
vfio_pci_core_device *vdev,
return -ENODEV;
 
if (hdr.count)
-   return vfio_pci_ioctl_pci_hot_reset_groups(vdev, , slot, 
arg);
+   return vfio_pci_ioctl_pci_hot_reset_files(vdev, , slot, 
arg);
 
iommufd = vfio_iommufd_physical_ictx(>vdev);
 
@@ -2329,16 +2329,16 @@ const struct pci_error_handlers 
vfio_pci_core_err_handlers = {
 };
 EXPORT_SYMBOL_GPL(vfio_pci_core_err_handlers);
 
-static bool vfio_dev_in_groups(struct vfio_pci_core_device *vdev,
-  struct vfio_pci_group_info *groups)
+static bool vfio_dev_in_files(struct vfio_pci_core_device *vdev,
+ struct vfio_pci_file_info *info)
 {
unsigned int i;
 
-   if (!groups)
+   if (!info)
return false;
 
-   for (i = 0; i < groups->count; i++)
-   if (vfio_file_has_dev(groups->files[i], >vdev))
+   for (i = 0; i < info->count; i++)
+   if (vfio_file_has_dev(info->files[i], >vdev))
return true;
return false;
 }
@@ -2429,7 +2429,7 @@ static bool vfio_dev_in_iommufd_ctx(struct 
vfio_pci_core_device *vdev,
  * get each memory_lock.
  */
 static int vfio_pci_dev_set_hot_reset(struct vfio_device_set *dev_set,
-  

[Intel-gfx] [PATCH 7/7] vfio/pci: Accept device fd in VFIO_DEVICE_PCI_HOT_RESET ioctl

2023-03-16 Thread Yi Liu
Now user can also provide an array of device fds as a 3rd method to verify
the reset ownership. It's not useful at this point when the device fds are
acquired via group fds. But it's necessary when moving to device cdev which
allows the user to directly acquire device fds by skipping group. In that
case this method can be used as a last resort when the preferred iommufd
verification doesn't work, e.g. in noiommu usages.

Clarify it in uAPI.

Signed-off-by: Yi Liu 
---
 drivers/vfio/pci/vfio_pci_core.c | 6 +++---
 include/uapi/linux/vfio.h| 3 ++-
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
index b7de1816b97b..19f5b075d70a 100644
--- a/drivers/vfio/pci/vfio_pci_core.c
+++ b/drivers/vfio/pci/vfio_pci_core.c
@@ -1289,7 +1289,7 @@ vfio_pci_ioctl_pci_hot_reset_files(struct 
vfio_pci_core_device *vdev,
return -ENOMEM;
}
 
-   if (copy_from_user(fds, arg->group_fds,
+   if (copy_from_user(fds, arg->fds,
   hdr->count * sizeof(*fds))) {
kfree(fds);
kfree(files);
@@ -1297,8 +1297,8 @@ vfio_pci_ioctl_pci_hot_reset_files(struct 
vfio_pci_core_device *vdev,
}
 
/*
-* Get the group file for each fd to ensure the group held across
-* the reset
+* Get the file for each fd to ensure the group/device file
+* is held across the reset
 */
for (file_idx = 0; file_idx < hdr->count; file_idx++) {
struct file *file = fget(fds[file_idx]);
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 17aa5d09db41..25432ef213ee 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -681,6 +681,7 @@ struct vfio_pci_hot_reset_info {
  *
  * The ownership can be proved by:
  *   - An array of group fds
+ *   - An array of device fds
  *   - A zero-length array
  *
  * In the last case all affected devices which are opened by this user
@@ -694,7 +695,7 @@ struct vfio_pci_hot_reset {
__u32   argsz;
__u32   flags;
__u32   count;
-   __s32   group_fds[];
+   __s32   fds[];
 };
 
 #define VFIO_DEVICE_PCI_HOT_RESET  _IO(VFIO_TYPE, VFIO_BASE + 13)
-- 
2.34.1



[Intel-gfx] [PATCH 5/7] vfio: Refine vfio file kAPIs for vfio PCI hot reset

2023-03-16 Thread Yi Liu
This prepares vfio core to accept vfio device file from the vfio PCI
hot reset path. vfio_file_is_group() is still kept for KVM usage.

Signed-off-by: Yi Liu 
---
 drivers/vfio/group.c | 32 ++--
 drivers/vfio/pci/vfio_pci_core.c |  4 ++--
 drivers/vfio/vfio.h  |  2 ++
 drivers/vfio/vfio_main.c | 29 +
 include/linux/vfio.h |  1 +
 5 files changed, 48 insertions(+), 20 deletions(-)

diff --git a/drivers/vfio/group.c b/drivers/vfio/group.c
index 27d5ba7cf9dc..d0c95d033605 100644
--- a/drivers/vfio/group.c
+++ b/drivers/vfio/group.c
@@ -745,6 +745,15 @@ bool vfio_device_has_container(struct vfio_device *device)
return device->group->container;
 }
 
+struct vfio_group *vfio_group_from_file(struct file *file)
+{
+   struct vfio_group *group = file->private_data;
+
+   if (file->f_op != _group_fops)
+   return NULL;
+   return group;
+}
+
 /**
  * vfio_file_iommu_group - Return the struct iommu_group for the vfio group 
file
  * @file: VFIO group file
@@ -755,13 +764,13 @@ bool vfio_device_has_container(struct vfio_device *device)
  */
 struct iommu_group *vfio_file_iommu_group(struct file *file)
 {
-   struct vfio_group *group = file->private_data;
+   struct vfio_group *group = vfio_group_from_file(file);
struct iommu_group *iommu_group = NULL;
 
if (!IS_ENABLED(CONFIG_SPAPR_TCE_IOMMU))
return NULL;
 
-   if (!vfio_file_is_group(file))
+   if (!group)
return NULL;
 
mutex_lock(>group_lock);
@@ -775,12 +784,12 @@ struct iommu_group *vfio_file_iommu_group(struct file 
*file)
 EXPORT_SYMBOL_GPL(vfio_file_iommu_group);
 
 /**
- * vfio_file_is_group - True if the file is usable with VFIO aPIS
+ * vfio_file_is_group - True if the file is a vfio group file
  * @file: VFIO group file
  */
 bool vfio_file_is_group(struct file *file)
 {
-   return file->f_op == _group_fops;
+   return vfio_group_from_file(file);
 }
 EXPORT_SYMBOL_GPL(vfio_file_is_group);
 
@@ -842,23 +851,10 @@ void vfio_file_set_kvm(struct file *file, struct kvm *kvm)
 }
 EXPORT_SYMBOL_GPL(vfio_file_set_kvm);
 
-/**
- * vfio_file_has_dev - True if the VFIO file is a handle for device
- * @file: VFIO file to check
- * @device: Device that must be part of the file
- *
- * Returns true if given file has permission to manipulate the given device.
- */
-bool vfio_file_has_dev(struct file *file, struct vfio_device *device)
+bool vfio_group_has_dev(struct vfio_group *group, struct vfio_device *device)
 {
-   struct vfio_group *group = file->private_data;
-
-   if (!vfio_file_is_group(file))
-   return false;
-
return group == device->group;
 }
-EXPORT_SYMBOL_GPL(vfio_file_has_dev);
 
 static char *vfio_devnode(const struct device *dev, umode_t *mode)
 {
diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
index b6b5624c8b15..b7de1816b97b 100644
--- a/drivers/vfio/pci/vfio_pci_core.c
+++ b/drivers/vfio/pci/vfio_pci_core.c
@@ -1308,8 +1308,8 @@ vfio_pci_ioctl_pci_hot_reset_files(struct 
vfio_pci_core_device *vdev,
break;
}
 
-   /* Ensure the FD is a vfio group FD.*/
-   if (!vfio_file_is_group(file)) {
+   /* Ensure the FD is a vfio FD. vfio group or vfio device */
+   if (!vfio_file_is_valid(file)) {
fput(file);
ret = -EINVAL;
break;
diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h
index 7b19c621e0e6..c0aeea24fbd6 100644
--- a/drivers/vfio/vfio.h
+++ b/drivers/vfio/vfio.h
@@ -84,6 +84,8 @@ void vfio_device_group_unregister(struct vfio_device *device);
 int vfio_device_group_use_iommu(struct vfio_device *device);
 void vfio_device_group_unuse_iommu(struct vfio_device *device);
 void vfio_device_group_close(struct vfio_device *device);
+struct vfio_group *vfio_group_from_file(struct file *file);
+bool vfio_group_has_dev(struct vfio_group *group, struct vfio_device *device);
 bool vfio_device_has_container(struct vfio_device *device);
 int __init vfio_group_init(void);
 void vfio_group_cleanup(void);
diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c
index 89497c933490..fe7446805afd 100644
--- a/drivers/vfio/vfio_main.c
+++ b/drivers/vfio/vfio_main.c
@@ -1154,6 +1154,35 @@ const struct file_operations vfio_device_fops = {
.mmap   = vfio_device_fops_mmap,
 };
 
+/**
+ * vfio_file_is_valid - True if the file is valid vfio file
+ * @file: VFIO group file or VFIO device file
+ */
+bool vfio_file_is_valid(struct file *file)
+{
+   return vfio_group_from_file(file);
+}
+EXPORT_SYMBOL_GPL(vfio_file_is_valid);
+
+/**
+ * vfio_file_has_dev - True if the VFIO file is a handle for device
+ * @file: VFIO file to check
+ * @device: Device that must be part of the file
+ *
+ * Returns true if given file has 

[Intel-gfx] [PATCH 2/7] vfio/pci: Only check ownership of opened devices in hot reset

2023-03-16 Thread Yi Liu
If the affected device is not opened by any user, it's safe to reset it
given it's not in use.

Reviewed-by: Kevin Tian 
Signed-off-by: Yi Liu 
---
 drivers/vfio/pci/vfio_pci_core.c | 14 +++---
 include/uapi/linux/vfio.h|  8 
 2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
index 65bbef562268..5d745c9abf05 100644
--- a/drivers/vfio/pci/vfio_pci_core.c
+++ b/drivers/vfio/pci/vfio_pci_core.c
@@ -2429,10 +2429,18 @@ static int vfio_pci_dev_set_hot_reset(struct 
vfio_device_set *dev_set,
 
list_for_each_entry(cur_vma, _set->device_list, vdev.dev_set_list) {
/*
-* Test whether all the affected devices are contained by the
-* set of groups provided by the user.
+* Test whether all the affected devices can be reset by the
+* user.
+*
+* Resetting an unused device (not opened) is safe, because
+* dev_set->lock is held in hot reset path so this device
+* cannot race being opened by another user simultaneously.
+*
+* Otherwise all opened devices in the dev_set must be
+* contained by the set of groups provided by the user.
 */
-   if (!vfio_dev_in_groups(cur_vma, groups)) {
+   if (cur_vma->vdev.open_count &&
+   !vfio_dev_in_groups(cur_vma, groups)) {
ret = -EINVAL;
goto err_undo;
}
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 0552e8dcf0cb..f96e5689cffc 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -673,6 +673,14 @@ struct vfio_pci_hot_reset_info {
  * VFIO_DEVICE_PCI_HOT_RESET - _IOW(VFIO_TYPE, VFIO_BASE + 13,
  * struct vfio_pci_hot_reset)
  *
+ * Userspace requests hot reset for the devices it uses.  Due to the
+ * underlying topology, multiple devices can be affected in the reset
+ * while some might be opened by another user.  To avoid interference
+ * the calling user must ensure all affected devices, if opened, are
+ * owned by itself.
+ *
+ * The ownership is proved by an array of group fds.
+ *
  * Return: 0 on success, -errno on failure.
  */
 struct vfio_pci_hot_reset {
-- 
2.34.1



[Intel-gfx] [PATCH 3/7] vfio/pci: Allow passing zero-length fd array in VFIO_DEVICE_PCI_HOT_RESET

2023-03-16 Thread Yi Liu
as an alternative method for ownership check when iommufd is used. In
this case all opened devices in the affected dev_set are verified to
be bound to a same valid iommufd value to allow reset. It's simpler
and faster as user does not need to pass a set of fds and kernel no
need to search the device within the given fds.

a device in noiommu mode doesn't have a valid iommufd, so this method
should not be used in a dev_set which contains multiple devices and one
of them is in noiommu. The only allowed noiommu scenario is that the
calling device is noiommu and it's in a singleton dev_set.

Suggested-by: Jason Gunthorpe 
Signed-off-by: Jason Gunthorpe 
Signed-off-by: Yi Liu 
---
 drivers/iommu/iommufd/device.c   |  6 ++
 drivers/vfio/iommufd.c   |  8 +++
 drivers/vfio/pci/vfio_pci_core.c | 94 +++-
 include/linux/iommufd.h  |  1 +
 include/linux/vfio.h |  3 +
 include/uapi/linux/vfio.h|  9 ++-
 6 files changed, 93 insertions(+), 28 deletions(-)

diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c
index 0295140dd384..2ca12716db98 100644
--- a/drivers/iommu/iommufd/device.c
+++ b/drivers/iommu/iommufd/device.c
@@ -131,6 +131,12 @@ void iommufd_device_unbind(struct iommufd_device *idev)
 }
 EXPORT_SYMBOL_NS_GPL(iommufd_device_unbind, IOMMUFD);
 
+struct iommufd_ctx *iommufd_device_to_ictx(struct iommufd_device *idev)
+{
+   return idev->ictx;
+}
+EXPORT_SYMBOL_NS_GPL(iommufd_device_to_ictx, IOMMUFD);
+
 static int iommufd_device_setup_msi(struct iommufd_device *idev,
struct iommufd_hw_pagetable *hwpt,
phys_addr_t sw_msi_start)
diff --git a/drivers/vfio/iommufd.c b/drivers/vfio/iommufd.c
index 9aabd8b31c15..ca0c16bb747e 100644
--- a/drivers/vfio/iommufd.c
+++ b/drivers/vfio/iommufd.c
@@ -66,6 +66,14 @@ void vfio_iommufd_unbind(struct vfio_device *vdev)
vdev->ops->unbind_iommufd(vdev);
 }
 
+struct iommufd_ctx *vfio_iommufd_physical_ictx(struct vfio_device *vdev)
+{
+   if (!vdev->iommufd_device)
+   return NULL;
+   return iommufd_device_to_ictx(vdev->iommufd_device);
+}
+EXPORT_SYMBOL_GPL(vfio_iommufd_physical_ictx);
+
 /*
  * The physical standard ops mean that the iommufd_device is bound to the
  * physical device vdev->dev that was provided to vfio_init_group_dev(). 
Drivers
diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
index 5d745c9abf05..b68fcba67a4b 100644
--- a/drivers/vfio/pci/vfio_pci_core.c
+++ b/drivers/vfio/pci/vfio_pci_core.c
@@ -180,7 +180,8 @@ static void vfio_pci_probe_mmaps(struct 
vfio_pci_core_device *vdev)
 struct vfio_pci_group_info;
 static void vfio_pci_dev_set_try_reset(struct vfio_device_set *dev_set);
 static int vfio_pci_dev_set_hot_reset(struct vfio_device_set *dev_set,
- struct vfio_pci_group_info *groups);
+ struct vfio_pci_group_info *groups,
+ struct iommufd_ctx *iommufd_ctx);
 
 /*
  * INTx masking requires the ability to disable INTx signaling via PCI_COMMAND
@@ -1255,29 +1256,17 @@ static int vfio_pci_ioctl_get_pci_hot_reset_info(
return ret;
 }
 
-static int vfio_pci_ioctl_pci_hot_reset(struct vfio_pci_core_device *vdev,
-   struct vfio_pci_hot_reset __user *arg)
+static int
+vfio_pci_ioctl_pci_hot_reset_groups(struct vfio_pci_core_device *vdev,
+   struct vfio_pci_hot_reset *hdr,
+   bool slot,
+   struct vfio_pci_hot_reset __user *arg)
 {
-   unsigned long minsz = offsetofend(struct vfio_pci_hot_reset, count);
-   struct vfio_pci_hot_reset hdr;
int32_t *group_fds;
struct file **files;
struct vfio_pci_group_info info;
-   bool slot = false;
int file_idx, count = 0, ret = 0;
 
-   if (copy_from_user(, arg, minsz))
-   return -EFAULT;
-
-   if (hdr.argsz < minsz || hdr.flags)
-   return -EINVAL;
-
-   /* Can we do a slot or bus reset or neither? */
-   if (!pci_probe_reset_slot(vdev->pdev->slot))
-   slot = true;
-   else if (pci_probe_reset_bus(vdev->pdev->bus))
-   return -ENODEV;
-
/*
 * We can't let userspace give us an arbitrarily large buffer to copy,
 * so verify how many we think there could be.  Note groups can have
@@ -1289,11 +1278,11 @@ static int vfio_pci_ioctl_pci_hot_reset(struct 
vfio_pci_core_device *vdev,
return ret;
 
/* Somewhere between 1 and count is OK */
-   if (!hdr.count || hdr.count > count)
+   if (hdr->count > count)
return -EINVAL;
 
-   group_fds = kcalloc(hdr.count, sizeof(*group_fds), GFP_KERNEL);
-   files = kcalloc(hdr.count, sizeof(*files), GFP_KERNEL);
+   group_fds = 

[Intel-gfx] [PATCH 0/7] Introduce new methods for verifying ownership in vfio PCI hot reset

2023-03-16 Thread Yi Liu
VFIO_DEVICE_PCI_HOT_RESET requires user to pass an array of group fds
to prove that it owns all devices affected by resetting the calling
device. This series introduces several extensions to allow the ownership
check better aligned with iommufd and coming vfio device cdev support.

First, resetting an unopened device is always safe given nobody is using
it. So relax the check to allow such devices not covered by group fd
array. [1]

When iommufd is used we can simply verify that all affected devices are
bound to a same iommufd then no need for the user to provide extra fd
information. This is enabled by the user passing a zero-length fd array
and moving forward this should be the preferred way for hot reset. [2]

However the iommufd method has difficulty working with noiommu devices
since those devices don't have a valid iommufd, unless the noiommu device
is in a singleton dev_set hence no ownership check is required. [3]

For noiommu backward compatibility a 3rd method is introduced by allowing
the user to pass an array of device fds to prove ownership. [4]

As suggested by Jason [5], we have this series to introduce the above
stuffs to the vfio PCI hot reset.

[1] https://lore.kernel.org/kvm/y%2fdobs6gdskxn...@nvidia.com/
[2] https://lore.kernel.org/kvm/y%2fzooclu8nxy2...@nvidia.com/#t
[3] https://lore.kernel.org/kvm/zacx+np%2fiy7yg...@nvidia.com/
[4] 
https://lore.kernel.org/kvm/ds0pr11mb7529be88460582bd599dc1f7c3...@ds0pr11mb7529.namprd11.prod.outlook.com/#t
[5] https://lore.kernel.org/kvm/zacvzvhkt9qhc...@nvidia.com/

Regards,
Yi Liu

Yi Liu (7):
  vfio/pci: Update comment around group_fd get in
vfio_pci_ioctl_pci_hot_reset()
  vfio/pci: Only check ownership of opened devices in hot reset
  vfio/pci: Allow passing zero-length fd array in
VFIO_DEVICE_PCI_HOT_RESET
  vfio/pci: Renaming for accepting device fd in hot reset path
  vfio: Refine vfio file kAPIs for vfio PCI hot reset
  vfio: Accpet device file from vfio PCI hot reset path
  vfio/pci: Accept device fd in VFIO_DEVICE_PCI_HOT_RESET ioctl

 drivers/iommu/iommufd/device.c   |   6 ++
 drivers/vfio/group.c |  32 +++
 drivers/vfio/iommufd.c   |   8 ++
 drivers/vfio/pci/vfio_pci_core.c | 146 ---
 drivers/vfio/vfio.h  |   2 +
 drivers/vfio/vfio_main.c |  44 ++
 include/linux/iommufd.h  |   1 +
 include/linux/vfio.h |   4 +
 include/uapi/linux/vfio.h|  18 +++-
 9 files changed, 193 insertions(+), 68 deletions(-)

-- 
2.34.1



[Intel-gfx] [PATCH 1/7] vfio/pci: Update comment around group_fd get in vfio_pci_ioctl_pci_hot_reset()

2023-03-16 Thread Yi Liu
this suits more on what the code does.

Reviewed-by: Kevin Tian 
Reviewed-by: Jason Gunthorpe 
Signed-off-by: Yi Liu 
---
 drivers/vfio/pci/vfio_pci_core.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
index a5ab416cf476..65bbef562268 100644
--- a/drivers/vfio/pci/vfio_pci_core.c
+++ b/drivers/vfio/pci/vfio_pci_core.c
@@ -1308,9 +1308,8 @@ static int vfio_pci_ioctl_pci_hot_reset(struct 
vfio_pci_core_device *vdev,
}
 
/*
-* For each group_fd, get the group through the vfio external user
-* interface and store the group and iommu ID.  This ensures the group
-* is held across the reset.
+* Get the group file for each fd to ensure the group held across
+* the reset
 */
for (file_idx = 0; file_idx < hdr.count; file_idx++) {
struct file *file = fget(group_fds[file_idx]);
-- 
2.34.1



[Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915/gvt: KVM: KVMGT fixes and page-track cleanups (rev5)

2023-03-16 Thread Patchwork
== Series Details ==

Series: drm/i915/gvt: KVM: KVMGT fixes and page-track cleanups (rev5)
URL   : https://patchwork.freedesktop.org/series/112196/
State : warning

== Summary ==

Error: dim checkpatch failed
25a3d4a31296 drm/i915/gvt: Verify pfn is "valid" before dereferencing "struct 
page"
7616ee93a101 KVM: x86/mmu: Factor out helper to get max mapping size of a 
memslot
fcb516cf24af drm/i915/gvt: remove interface intel_gvt_is_valid_gfn
4e9589b9266b drm/i915/gvt: Incorporate KVM memslot info into check for 2MiB GTT 
entry
7e1387732ec3 drm/i915/gvt: Verify VFIO-pinned page is THP when shadowing 2M gtt 
entry
8b245ebb321a drm/i915/gvt: Put the page reference obtained by KVM's gfn_to_pfn()
fd92a12e9d0c drm/i915/gvt: Don't rely on KVM's gfn_to_pfn() to query possible 
2M GTT
-:37: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#37: FILE: drivers/gpu/drm/i915/gvt/gtt.c:1157:
+static int try_map_2MB_gtt_entry(struct intel_vgpu *vgpu,
+   struct intel_gvt_gtt_entry *entry, dma_addr_t *dma_addr)

total: 0 errors, 0 warnings, 1 checks, 78 lines checked
d33f165a76b9 drm/i915/gvt: Use an "unsigned long" to iterate over memslot gfns
2f00c4873260 drm/i915/gvt: Drop unused helper intel_vgpu_reset_gtt()
524b8ca6b867 drm/i915/gvt: Protect gfn hash table with vgpu_lock
da08c5987ad9 KVM: x86/mmu: Don't rely on page-track mechanism to flush on 
memslot change
7395b953521e KVM: x86/mmu: Don't bounce through page-track mechanism for guest 
PTEs
e0945379e27a KVM: drm/i915/gvt: Drop @vcpu from KVM's ->track_write() hook
ac3d05c84e2f KVM: x86: Reject memslot MOVE operations if KVMGT is attached
b7d633d0df47 drm/i915/gvt: Don't bother removing write-protection on 
to-be-deleted slot
641942aa6bc1 KVM: x86: Add a new page-track hook to handle memslot deletion
-:84: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#84: FILE: arch/x86/kvm/mmu/page_track.c:324:
+   hlist_for_each_entry_srcu(n, >track_notifier_list, node,
+   srcu_read_lock_held(>track_srcu))

total: 0 errors, 0 warnings, 1 checks, 62 lines checked
813496703fa8 drm/i915/gvt: switch from ->track_flush_slot() to 
->track_remove_region()
9747b5c46647 KVM: x86: Remove the unused page-track hook track_flush_slot()
22cac1f2fb48 KVM: x86/mmu: Move KVM-only page-track declarations to internal 
header
Traceback (most recent call last):
  File "scripts/spdxcheck.py", line 6, in 
from ply import lex, yacc
ModuleNotFoundError: No module named 'ply'
-:119: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does 
MAINTAINERS need updating?
#119: 
new file mode 100644

total: 0 errors, 1 warnings, 0 checks, 118 lines checked
900cdc374edb KVM: x86/mmu: Use page-track notifiers iff there are external users
edc7b922b08c KVM: x86/mmu: Drop infrastructure for multiple page-track modes
8e372f22d215 KVM: x86/mmu: Rename page-track APIs to reflect the new reality
722952f3cee5 KVM: x86/mmu: Assert that correct locks are held for page 
write-tracking
0ccb4868c921 KVM: x86/mmu: Bug the VM if write-tracking is used but not enabled
e4fbe25725a8 KVM: x86/mmu: Drop @slot param from exported/external page-track 
APIs
a000d410d307 KVM: x86/mmu: Handle KVM bookkeeping in page-track APIs, not 
callers
d5ce069cc421 drm/i915/gvt: Drop final dependencies on KVM internal details




[Intel-gfx] [PATCH v2 2/5] vfio-iommufd: No need to record iommufd_ctx in vfio_device

2023-03-16 Thread Yi Liu
iommufd_ctx is stored in vfio_device for emulated devices per bind_iommufd.
However, as iommufd_access is created in bind, no more need to stored it
since iommufd_access implicitly stores it.

Reviewed-by: Jason Gunthorpe 
Signed-off-by: Yi Liu 
---
 drivers/vfio/iommufd.c | 10 +-
 include/linux/vfio.h   |  1 -
 2 files changed, 1 insertion(+), 10 deletions(-)

diff --git a/drivers/vfio/iommufd.c b/drivers/vfio/iommufd.c
index 6b4b495b24c4..b576d4c7b79b 100644
--- a/drivers/vfio/iommufd.c
+++ b/drivers/vfio/iommufd.c
@@ -142,14 +142,10 @@ int vfio_iommufd_emulated_bind(struct vfio_device *vdev,
 
lockdep_assert_held(>dev_set->lock);
 
-   iommufd_ctx_get(ictx);
user = iommufd_access_create(ictx, _user_ops, vdev);
-   if (IS_ERR(user)) {
-   iommufd_ctx_put(ictx);
+   if (IS_ERR(user))
return PTR_ERR(user);
-   }
vdev->iommufd_access = user;
-   vdev->iommufd_ictx = ictx;
return 0;
 }
 EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_bind);
@@ -163,8 +159,6 @@ void vfio_iommufd_emulated_unbind(struct vfio_device *vdev)
vdev->iommufd_attached = false;
vdev->iommufd_access = NULL;
}
-   iommufd_ctx_put(vdev->iommufd_ictx);
-   vdev->iommufd_ictx = NULL;
 }
 EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_unbind);
 
@@ -174,8 +168,6 @@ int vfio_iommufd_emulated_attach_ioas(struct vfio_device 
*vdev, u32 *pt_id)
 
lockdep_assert_held(>dev_set->lock);
 
-   if (WARN_ON(!vdev->iommufd_ictx))
-   return -EINVAL;
if (WARN_ON(!vdev->iommufd_access))
return -ENOENT;
if (vdev->iommufd_attached)
diff --git a/include/linux/vfio.h b/include/linux/vfio.h
index 93134b023968..3188d8a374bd 100644
--- a/include/linux/vfio.h
+++ b/include/linux/vfio.h
@@ -60,7 +60,6 @@ struct vfio_device {
void (*put_kvm)(struct kvm *kvm);
 #if IS_ENABLED(CONFIG_IOMMUFD)
struct iommufd_device *iommufd_device;
-   struct iommufd_ctx *iommufd_ictx;
bool iommufd_attached;
 #endif
 };
-- 
2.34.1



[Intel-gfx] [PATCH v2 3/5] vfio-iommufd: Make vfio_iommufd_emulated_bind() return iommufd_access ID

2023-03-16 Thread Yi Liu
vfio device cdev needs to return iommufd_access ID to userspace if
bind_iommufd succeeds.

Reviewed-by: Kevin Tian 
Reviewed-by: Jason Gunthorpe 
Signed-off-by: Yi Liu 
---
 drivers/iommu/iommufd/device.c   | 4 +++-
 drivers/iommu/iommufd/selftest.c | 3 ++-
 drivers/vfio/iommufd.c   | 2 +-
 include/linux/iommufd.h  | 2 +-
 4 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c
index 99d34c81d786..0295140dd384 100644
--- a/drivers/iommu/iommufd/device.c
+++ b/drivers/iommu/iommufd/device.c
@@ -426,6 +426,7 @@ void iommufd_access_destroy_object(struct iommufd_object 
*obj)
  * @ioas_id: ID for a IOMMUFD_OBJ_IOAS
  * @ops: Driver's ops to associate with the access
  * @data: Opaque data to pass into ops functions
+ * @id: Output ID number to return to userspace for this access
  *
  * An iommufd_access allows a driver to read/write to the IOAS without using
  * DMA. The underlying CPU memory can be accessed using the
@@ -435,7 +436,7 @@ void iommufd_access_destroy_object(struct iommufd_object 
*obj)
  */
 struct iommufd_access *
 iommufd_access_create(struct iommufd_ctx *ictx,
- const struct iommufd_access_ops *ops, void *data)
+ const struct iommufd_access_ops *ops, void *data, u32 *id)
 {
struct iommufd_access *access;
 
@@ -460,6 +461,7 @@ iommufd_access_create(struct iommufd_ctx *ictx,
access->ictx = ictx;
iommufd_ctx_get(ictx);
iommufd_object_finalize(ictx, >obj);
+   *id = access->obj.id;
return access;
 }
 EXPORT_SYMBOL_NS_GPL(iommufd_access_create, IOMMUFD);
diff --git a/drivers/iommu/iommufd/selftest.c b/drivers/iommu/iommufd/selftest.c
index 0eabda430c9f..65e3bdaadd67 100644
--- a/drivers/iommu/iommufd/selftest.c
+++ b/drivers/iommu/iommufd/selftest.c
@@ -554,6 +554,7 @@ static int iommufd_test_create_access(struct iommufd_ucmd 
*ucmd,
struct iommu_test_cmd *cmd = ucmd->cmd;
struct selftest_access *staccess;
struct iommufd_access *access;
+   u32 id;
int fdno;
int rc;
 
@@ -575,7 +576,7 @@ static int iommufd_test_create_access(struct iommufd_ucmd 
*ucmd,
(flags & MOCK_FLAGS_ACCESS_CREATE_NEEDS_PIN_PAGES) ?
_access_ops_pin :
_access_ops,
-   staccess);
+   staccess, );
if (IS_ERR(access)) {
rc = PTR_ERR(access);
goto out_put_fdno;
diff --git a/drivers/vfio/iommufd.c b/drivers/vfio/iommufd.c
index b576d4c7b79b..e40c0e9fea30 100644
--- a/drivers/vfio/iommufd.c
+++ b/drivers/vfio/iommufd.c
@@ -142,7 +142,7 @@ int vfio_iommufd_emulated_bind(struct vfio_device *vdev,
 
lockdep_assert_held(>dev_set->lock);
 
-   user = iommufd_access_create(ictx, _user_ops, vdev);
+   user = iommufd_access_create(ictx, _user_ops, vdev, out_device_id);
if (IS_ERR(user))
return PTR_ERR(user);
vdev->iommufd_access = user;
diff --git a/include/linux/iommufd.h b/include/linux/iommufd.h
index 155d3630aedc..1129a36a74c4 100644
--- a/include/linux/iommufd.h
+++ b/include/linux/iommufd.h
@@ -41,7 +41,7 @@ enum {
 
 struct iommufd_access *
 iommufd_access_create(struct iommufd_ctx *ictx,
- const struct iommufd_access_ops *ops, void *data);
+ const struct iommufd_access_ops *ops, void *data, u32 
*id);
 void iommufd_access_destroy(struct iommufd_access *access);
 int iommufd_access_attach(struct iommufd_access *access, u32 ioas_id);
 
-- 
2.34.1



[Intel-gfx] [PATCH v2 4/5] vfio/mdev: Uses the vfio emulated iommufd ops set in the mdev sample drivers

2023-03-16 Thread Yi Liu
This harmonizes the no-DMA devices (the vfio-mdev sample drivers) with
the emulated devices (gvt-g, vfio-ap etc.). It makes it easier to add
BIND_IOMMUFD user interface which requires to return an iommufd ID to
represent the device/iommufd bond.

Reviewed-by: Jason Gunthorpe 
Signed-off-by: Yi Liu 
---
 drivers/vfio/iommufd.c | 14 ++
 samples/vfio-mdev/mbochs.c |  3 +++
 samples/vfio-mdev/mdpy.c   |  3 +++
 samples/vfio-mdev/mtty.c   |  3 +++
 4 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/drivers/vfio/iommufd.c b/drivers/vfio/iommufd.c
index e40c0e9fea30..345ff8cf29e7 100644
--- a/drivers/vfio/iommufd.c
+++ b/drivers/vfio/iommufd.c
@@ -32,12 +32,8 @@ int vfio_iommufd_bind(struct vfio_device *vdev, struct 
iommufd_ctx *ictx)
return 0;
}
 
-   /*
-* If the driver doesn't provide this op then it means the device does
-* not do DMA at all. So nothing to do.
-*/
-   if (!vdev->ops->bind_iommufd)
-   return 0;
+   if (WARN_ON(!vdev->ops->bind_iommufd))
+   return -ENODEV;
 
ret = vdev->ops->bind_iommufd(vdev, ictx, _id);
if (ret)
@@ -119,7 +115,8 @@ EXPORT_SYMBOL_GPL(vfio_iommufd_physical_attach_ioas);
 /*
  * The emulated standard ops mean that vfio_device is going to use the
  * "mdev path" and will call vfio_pin_pages()/vfio_dma_rw(). Drivers using this
- * ops set should call vfio_register_emulated_iommu_dev().
+ * ops set should call vfio_register_emulated_iommu_dev(). Drivers that do
+ * not call vfio_pin_pages()/vfio_dma_rw() have no need to provide dma_unmap.
  */
 
 static void vfio_emulated_unmap(void *data, unsigned long iova,
@@ -127,7 +124,8 @@ static void vfio_emulated_unmap(void *data, unsigned long 
iova,
 {
struct vfio_device *vdev = data;
 
-   vdev->ops->dma_unmap(vdev, iova, length);
+   if (vdev->ops->dma_unmap)
+   vdev->ops->dma_unmap(vdev, iova, length);
 }
 
 static const struct iommufd_access_ops vfio_user_ops = {
diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c
index e54eb752e1ba..19391dda5fba 100644
--- a/samples/vfio-mdev/mbochs.c
+++ b/samples/vfio-mdev/mbochs.c
@@ -1374,6 +1374,9 @@ static const struct vfio_device_ops mbochs_dev_ops = {
.write = mbochs_write,
.ioctl = mbochs_ioctl,
.mmap = mbochs_mmap,
+   .bind_iommufd   = vfio_iommufd_emulated_bind,
+   .unbind_iommufd = vfio_iommufd_emulated_unbind,
+   .attach_ioas= vfio_iommufd_emulated_attach_ioas,
 };
 
 static struct mdev_driver mbochs_driver = {
diff --git a/samples/vfio-mdev/mdpy.c b/samples/vfio-mdev/mdpy.c
index e8400fdab71d..5f48aef36995 100644
--- a/samples/vfio-mdev/mdpy.c
+++ b/samples/vfio-mdev/mdpy.c
@@ -663,6 +663,9 @@ static const struct vfio_device_ops mdpy_dev_ops = {
.write = mdpy_write,
.ioctl = mdpy_ioctl,
.mmap = mdpy_mmap,
+   .bind_iommufd   = vfio_iommufd_emulated_bind,
+   .unbind_iommufd = vfio_iommufd_emulated_unbind,
+   .attach_ioas= vfio_iommufd_emulated_attach_ioas,
 };
 
 static struct mdev_driver mdpy_driver = {
diff --git a/samples/vfio-mdev/mtty.c b/samples/vfio-mdev/mtty.c
index e887de672c52..35460901b9f7 100644
--- a/samples/vfio-mdev/mtty.c
+++ b/samples/vfio-mdev/mtty.c
@@ -1269,6 +1269,9 @@ static const struct vfio_device_ops mtty_dev_ops = {
.read = mtty_read,
.write = mtty_write,
.ioctl = mtty_ioctl,
+   .bind_iommufd   = vfio_iommufd_emulated_bind,
+   .unbind_iommufd = vfio_iommufd_emulated_unbind,
+   .attach_ioas= vfio_iommufd_emulated_attach_ioas,
 };
 
 static struct mdev_driver mtty_driver = {
-- 
2.34.1



[Intel-gfx] [PATCH v2 5/5] vfio: Check the presence for iommufd callbacks in __vfio_register_dev()

2023-03-16 Thread Yi Liu
After making the no-DMA drivers (samples/vfio-mdev) providing iommufd
callbacks, __vfio_register_dev() should check the presence of the iommufd
callbacks if CONFIG_IOMMUFD is enabled.

Reviewed-by: Jason Gunthorpe 
Signed-off-by: Yi Liu 
---
 drivers/vfio/iommufd.c   | 3 ---
 drivers/vfio/vfio_main.c | 5 +++--
 2 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/vfio/iommufd.c b/drivers/vfio/iommufd.c
index 345ff8cf29e7..9aabd8b31c15 100644
--- a/drivers/vfio/iommufd.c
+++ b/drivers/vfio/iommufd.c
@@ -32,9 +32,6 @@ int vfio_iommufd_bind(struct vfio_device *vdev, struct 
iommufd_ctx *ictx)
return 0;
}
 
-   if (WARN_ON(!vdev->ops->bind_iommufd))
-   return -ENODEV;
-
ret = vdev->ops->bind_iommufd(vdev, ictx, _id);
if (ret)
return ret;
diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c
index 43bd6b76e2b6..89497c933490 100644
--- a/drivers/vfio/vfio_main.c
+++ b/drivers/vfio/vfio_main.c
@@ -255,8 +255,9 @@ static int __vfio_register_dev(struct vfio_device *device,
 {
int ret;
 
-   if (WARN_ON(device->ops->bind_iommufd &&
-   (!device->ops->unbind_iommufd ||
+   if (WARN_ON(IS_ENABLED(CONFIG_IOMMUFD) &&
+   (!device->ops->bind_iommufd ||
+!device->ops->unbind_iommufd ||
 !device->ops->attach_ioas)))
return -EINVAL;
 
-- 
2.34.1



[Intel-gfx] [PATCH v2 0/5] vfio: Make emulated devices prepared for vfio device cdev

2023-03-16 Thread Yi Liu
The .bind_iommufd op of vfio emulated devices are either empty or does
nothing. This is different with the vfio physical devices, to add vfio
device cdev, need to make them act the same.

This series first makes the .bind_iommufd op of vfio emulated devices
to create iommufd_access, this introduces a new iommufd API. Then let
the driver that does not provide .bind_iommufd op to use the vfio emulated
iommufd op set. This makes all vfio device drivers have consistent iommufd
operations, which is good for adding new device uAPIs in the device cdev
series.

Change log:

v2:
 - Add r-b from Kevin and Jason
 - Refine patch 01 per comments from Jason and Kevin

v1: https://lore.kernel.org/kvm/20230308131340.459224-1-yi.l@intel.com/

Thanks,
Yi Liu

Nicolin Chen (1):
  iommufd: Create access in vfio_iommufd_emulated_bind()

Yi Liu (4):
  vfio-iommufd: No need to record iommufd_ctx in vfio_device
  vfio-iommufd: Make vfio_iommufd_emulated_bind() return iommufd_access
ID
  vfio/mdev: Uses the vfio emulated iommufd ops set in the mdev sample
drivers
  vfio: Check the presence for iommufd callbacks in
__vfio_register_dev()

 drivers/iommu/iommufd/device.c   | 57 
 drivers/iommu/iommufd/selftest.c |  8 +++--
 drivers/vfio/iommufd.c   | 39 +++---
 drivers/vfio/vfio_main.c |  5 +--
 include/linux/iommufd.h  |  5 +--
 include/linux/vfio.h |  1 -
 samples/vfio-mdev/mbochs.c   |  3 ++
 samples/vfio-mdev/mdpy.c |  3 ++
 samples/vfio-mdev/mtty.c |  3 ++
 9 files changed, 76 insertions(+), 48 deletions(-)

-- 
2.34.1



[Intel-gfx] [PATCH v2 1/5] iommufd: Create access in vfio_iommufd_emulated_bind()

2023-03-16 Thread Yi Liu
From: Nicolin Chen 

There are needs to created iommufd_access prior to have an IOAS and set
IOAS later. Like the vfio device cdev needs to have an iommufd object
to represent the bond (iommufd_access) and IOAS replacement.

Moves the iommufd_access_create() call into vfio_iommufd_emulated_bind(),
making it symmetric with the __vfio_iommufd_access_destroy() call in the
vfio_iommufd_emulated_unbind(). This means an access is created/destroyed
by the bind()/unbind(), and the vfio_iommufd_emulated_attach_ioas() only
updates the access->ioas pointer.

Since vfio_iommufd_emulated_bind() does not provide ioas_id, drop it from
the argument list of iommufd_access_create(). Instead, add a new access
API iommufd_access_attach() to set the access->ioas pointer. Also, set
vdev->iommufd_attached accordingly, similar to the physical pathway.

Reviewed-by: Kevin Tian 
Signed-off-by: Nicolin Chen 
Signed-off-by: Yi Liu 
---
 drivers/iommu/iommufd/device.c   | 53 +++-
 drivers/iommu/iommufd/selftest.c |  5 ++-
 drivers/vfio/iommufd.c   | 28 -
 include/linux/iommufd.h  |  3 +-
 4 files changed, 59 insertions(+), 30 deletions(-)

diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c
index a0c66f47a65a..99d34c81d786 100644
--- a/drivers/iommu/iommufd/device.c
+++ b/drivers/iommu/iommufd/device.c
@@ -412,9 +412,12 @@ void iommufd_access_destroy_object(struct iommufd_object 
*obj)
struct iommufd_access *access =
container_of(obj, struct iommufd_access, obj);
 
-   iopt_remove_access(>ioas->iopt, access);
+   if (access->ioas) {
+   iopt_remove_access(>ioas->iopt, access);
+   refcount_dec(>ioas->obj.users);
+   access->ioas = NULL;
+   }
iommufd_ctx_put(access->ictx);
-   refcount_dec(>ioas->obj.users);
 }
 
 /**
@@ -431,12 +434,10 @@ void iommufd_access_destroy_object(struct iommufd_object 
*obj)
  * The provided ops are required to use iommufd_access_pin_pages().
  */
 struct iommufd_access *
-iommufd_access_create(struct iommufd_ctx *ictx, u32 ioas_id,
+iommufd_access_create(struct iommufd_ctx *ictx,
  const struct iommufd_access_ops *ops, void *data)
 {
struct iommufd_access *access;
-   struct iommufd_object *obj;
-   int rc;
 
/*
 * There is no uAPI for the access object, but to keep things symmetric
@@ -449,21 +450,10 @@ iommufd_access_create(struct iommufd_ctx *ictx, u32 
ioas_id,
access->data = data;
access->ops = ops;
 
-   obj = iommufd_get_object(ictx, ioas_id, IOMMUFD_OBJ_IOAS);
-   if (IS_ERR(obj)) {
-   rc = PTR_ERR(obj);
-   goto out_abort;
-   }
-   access->ioas = container_of(obj, struct iommufd_ioas, obj);
-   iommufd_ref_to_users(obj);
-
if (ops->needs_pin_pages)
access->iova_alignment = PAGE_SIZE;
else
access->iova_alignment = 1;
-   rc = iopt_add_access(>ioas->iopt, access);
-   if (rc)
-   goto out_put_ioas;
 
/* The calling driver is a user until iommufd_access_destroy() */
refcount_inc(>obj.users);
@@ -471,11 +461,6 @@ iommufd_access_create(struct iommufd_ctx *ictx, u32 
ioas_id,
iommufd_ctx_get(ictx);
iommufd_object_finalize(ictx, >obj);
return access;
-out_put_ioas:
-   refcount_dec(>ioas->obj.users);
-out_abort:
-   iommufd_object_abort(ictx, >obj);
-   return ERR_PTR(rc);
 }
 EXPORT_SYMBOL_NS_GPL(iommufd_access_create, IOMMUFD);
 
@@ -494,6 +479,32 @@ void iommufd_access_destroy(struct iommufd_access *access)
 }
 EXPORT_SYMBOL_NS_GPL(iommufd_access_destroy, IOMMUFD);
 
+int iommufd_access_attach(struct iommufd_access *access, u32 ioas_id)
+{
+   struct iommufd_ioas *new_ioas;
+   struct iommufd_object *obj;
+   int rc = 0;
+
+   if (access->ioas != NULL && access->ioas->obj.id != ioas_id)
+   return -EINVAL;
+
+   obj = iommufd_get_object(access->ictx, ioas_id, IOMMUFD_OBJ_IOAS);
+   if (IS_ERR(obj))
+   return PTR_ERR(obj);
+   new_ioas = container_of(obj, struct iommufd_ioas, obj);
+
+   rc = iopt_add_access(_ioas->iopt, access);
+   if (rc) {
+   iommufd_put_object(obj);
+   return rc;
+   }
+   iommufd_ref_to_users(obj);
+
+   access->ioas = new_ioas;
+   return 0;
+}
+EXPORT_SYMBOL_NS_GPL(iommufd_access_attach, IOMMUFD);
+
 /**
  * iommufd_access_notify_unmap - Notify users of an iopt to stop using it
  * @iopt: iopt to work on
diff --git a/drivers/iommu/iommufd/selftest.c b/drivers/iommu/iommufd/selftest.c
index cfb5fe9a5e0e..0eabda430c9f 100644
--- a/drivers/iommu/iommufd/selftest.c
+++ b/drivers/iommu/iommufd/selftest.c
@@ -571,7 +571,7 @@ static int iommufd_test_create_access(struct iommufd_ucmd 
*ucmd,
}
 
access = iommufd_access_create(
-   ucmd->ictx, ioas_id,
+ 

Re: [Intel-gfx] [PATCH] drm/i915/hdcp: Remove drm_modeset_lock in intel_conn_to_vcpi

2023-03-16 Thread Kandpal, Suraj
> 
> On Thu, Mar 16, 2023 at 01:52:32PM +0530, Suraj Kandpal wrote:
> > Remove drm_modeset_lock in intel_conn_to_vcpi as we don't need it
> > anymore since all the required locks are taken in atomic check and
> > prepare phases.
> >
> > Signed-off-by: Suraj Kandpal 
> > ---
> >  drivers/gpu/drm/i915/display/intel_hdcp.c | 2 --
> >  1 file changed, 2 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c
> > b/drivers/gpu/drm/i915/display/intel_hdcp.c
> > index 2984d2810e42..f957b4bd9c26 100644
> > --- a/drivers/gpu/drm/i915/display/intel_hdcp.c
> > +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c
> > @@ -41,7 +41,6 @@ static int intel_conn_to_vcpi(struct intel_connector
> *connector)
> > return 0;
> > mgr = connector->port->mgr;
> >
> > -   drm_modeset_lock(>base.lock, NULL);
> > mst_state = to_drm_dp_mst_topology_state(mgr->base.state);
> > payload = drm_atomic_get_mst_payload_state(mst_state,
> connector->port);
> > if (drm_WARN_ON(mgr->dev, !payload)) @@ -53,7 +52,6 @@ static
> int
> > intel_conn_to_vcpi(struct intel_connector *connector)
> > goto out;
> > }
> >  out:
> > -   drm_modeset_unlock(>base.lock);
> > return vcpi;
> >  }
> 
> That whole function looks like it something that should be part of the
> drm_dp_mst_helper.c.
> 
> Also, it's directly accessing mgr->base.state which is just wrong.
> 
> And it looks like it can get called from outside the normal atomic commit
> flows (like so many other things in the hdcp code, sigh), so what you're doing
> here is also wrong in that case.
> 

Okay but as of now we are seeing a lock error which does not allow us to enable
HDCP (VLK-45132) when DPMST is connected so how do I move forward in a way that 
solves the
Issue and we access mgr->base.state in an acceptable manner

Regards,
Suraj Kandpal
> So the whole thing looks just very broken to me. Not to mention the HDCP vs.
> MST<->SST switch is also still fundementally broken. I'm really tempted to
> just send a patch to nuke the entire HDCP MST code.
> 
> --
> Ville Syrjälä
> Intel


Re: [Intel-gfx] [PATCH 7/7] drm/debugfs: remove debugfs_root pointer from minor

2023-03-16 Thread kernel test robot
Hi Christian,

I love your patch! Yet something to improve:

[auto build test ERROR on drm-misc/drm-misc-next]
[also build test ERROR on drm-intel/for-linux-next-fixes linus/master v6.3-rc2]
[cannot apply to drm-tip/drm-tip drm-intel/for-linux-next tegra/for-next 
next-20230316]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:
https://github.com/intel-lab-lkp/linux/commits/Christian-K-nig/drm-tegra-allow-compile-test-on-ARM/20230316-172205
base:   git://anongit.freedesktop.org/drm/drm-misc drm-misc-next
patch link:
https://lore.kernel.org/r/20230316082035.567520-8-christian.koenig%40amd.com
patch subject: [PATCH 7/7] drm/debugfs: remove debugfs_root pointer from minor
config: s390-allyesconfig 
(https://download.01.org/0day-ci/archive/20230316/202303161920.xbwfrr94-...@intel.com/config)
compiler: s390-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# 
https://github.com/intel-lab-lkp/linux/commit/70b21b15c200ec426c806bf2aa03083e3b19dd41
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review 
Christian-K-nig/drm-tegra-allow-compile-test-on-ARM/20230316-172205
git checkout 70b21b15c200ec426c806bf2aa03083e3b19dd41
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 
O=build_dir ARCH=s390 olddefconfig
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 
O=build_dir ARCH=s390 SHELL=/bin/bash drivers/gpu/

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot 
| Link: 
https://lore.kernel.org/oe-kbuild-all/202303161920.xbwfrr94-...@intel.com/

All errors (new ones prefixed by >>):

   drivers/gpu/drm/msm/msm_debugfs.c: In function 'msm_debugfs_init':
>> drivers/gpu/drm/msm/msm_debugfs.c:329:58: error: 'struct drm_minor' has no 
>> member named 'debugfs_root'
 329 | gpu_devfreq = debugfs_create_dir("devfreq", 
minor->debugfs_root);
 |  ^~


vim +329 drivers/gpu/drm/msm/msm_debugfs.c

edcd60ce243d16 Rob Clark 2016-03-16  303  
7ce84471e3c72e Wambui Karuga 2020-03-10  304  void 
msm_debugfs_init(struct drm_minor *minor)
edcd60ce243d16 Rob Clark 2016-03-16  305  {
edcd60ce243d16 Rob Clark 2016-03-16  306struct 
drm_device *dev = minor->dev;
bc5289eed48176 Rob Clark 2016-10-26  307struct 
msm_drm_private *priv = dev->dev_private;
6563f60f14cbb3 Rob Clark 2023-01-10  308struct dentry 
*gpu_devfreq;
edcd60ce243d16 Rob Clark 2016-03-16  309  
9e2fd463ec346d Wambui Karuga 2020-03-10  310
drm_debugfs_create_files(msm_debugfs_list,
edcd60ce243d16 Rob Clark 2016-03-16  311
 ARRAY_SIZE(msm_debugfs_list),
70b21b15c200ec Christian König   2023-03-16  312
 minor->dev->debugfs_root, minor);
edcd60ce243d16 Rob Clark 2016-03-16  313  
70b21b15c200ec Christian König   2023-03-16  314
debugfs_create_file("gpu", S_IRUSR, minor->dev->debugfs_root,
4f776f4511c7f7 Jordan Crouse 2018-07-24  315dev, 
_gpu_fops);
4f776f4511c7f7 Jordan Crouse 2018-07-24  316  
70b21b15c200ec Christian König   2023-03-16  317
debugfs_create_file("kms", S_IRUSR, minor->dev->debugfs_root,
c1760555884b7f Rob Clark 2021-12-15  318dev, 
_kms_fops);
c1760555884b7f Rob Clark 2021-12-15  319  
70b21b15c200ec Christian König   2023-03-16  320
debugfs_create_u32("hangcheck_period_ms", 0600, minor->dev->debugfs_root,
1d2fa58e0dda33 Samuel Iglesias Gonsalvez 2021-06-07  321
>hangcheck_period);
1d2fa58e0dda33 Samuel Iglesias Gonsalvez 2021-06-07  322  
70b21b15c200ec Christian König   2023-03-16  323
debugfs_create_bool("disable_err_irq", 0600, minor->dev->debugfs_root,
5edf2750d998b7 Rob Clark 2021-11-09  324
>disable_err_irq);
5edf2750d998b7 Rob Clark 2021-11-09  325  
70b21b15c200ec Christian König   2023-03-16  326
debugfs_create_file("shrink", S_IRWXU, minor->dev->debugfs_root,
5434941fd45d30 Rob Clark 2021-06-14  327dev, 
_fops);
5434941fd45d30 Rob Clark

Re: [Intel-gfx] [PATCH v11 08/11] drm/i915/dp: Avoid DSC with output_format YCBCR420

2023-03-16 Thread Nautiyal, Ankit K

Hi Manasi,

I just realized that there is a newer version of the patch in another 
series for DSC 420 support [1].


I added this patch when I was debugging an issue with PCON + 8k YCbCr420 
only mode, and noticed that we set the output_format first and then 
check for DSC.


Later this patch was pulled in DSC420 series and then got some comments 
and modifications.


So, to avoid having similar change in 2 places, perhaps will drop this 
patch from this series, and collect reviews in [1] for the change.


Currently on [1], the check is outside of intel_dp_supports_dsc(), as a 
separate function explicitly checking for the given output_format, but 
we can discuss and have this inside the mentioned function.


Apologies for the inconvenience.

[1] https://patchwork.freedesktop.org/patch/525903/?series=114246=3 



Thanks & Regards,

Ankit


On 3/14/2023 11:03 PM, Manasi Navare wrote:
Since we cannot do DSC with this output format currently, can this 
check be added as part of the intel_dp_supports_dsc() ?


Regards
Manasi


On Tue, Mar 14, 2023 at 4:07 AM Ankit Nautiyal 
 wrote:


Currently, DSC with YCBCR420 is not supported.
Return -EINVAL when trying with DSC with output_format as YCBCR420.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c
b/drivers/gpu/drm/i915/display/intel_dp.c
index b1431ed175bc..99a5cd370c1f 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1602,6 +1602,10 @@ int intel_dp_dsc_compute_config(struct
intel_dp *intel_dp,
        if (!(intel_dp, pipe_config))
                return -EINVAL;

+       /* Currently DSC with YCBCR420 format is not supported */
+       if (pipe_config->output_format ==
INTEL_OUTPUT_FORMAT_YCBCR420)
+               return -EINVAL;
+
        if (compute_pipe_bpp)
                pipe_bpp = intel_dp_dsc_compute_bpp(intel_dp,
pipe_config->output_format,
conn_state->max_requested_bpc);
-- 
2.25.1




[Intel-gfx] [PATCH v5 20/22] drm/i915/mtl: Power up TCSS

2023-03-16 Thread Mika Kahola
Add register writes to enable powering up Type-C subsystem i.e. TCSS.
For MeteorLake we need to request TCSS to power up and check the TCSS
power state after 500 us.

In addition, for PICA we need to set/clear the Type-C PHY ownnership
bit when Type-C device is connected/disconnected.

v2: Call tcss power request with correct parameter.
v3: Use de variant for register wait (Jani)

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_display.c |   2 +-
 drivers/gpu/drm/i915/display/intel_tc.c  | 117 ++-
 2 files changed, 114 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 89279814e789..71fa60cf4953 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -1978,7 +1978,7 @@ bool intel_phy_is_tc(struct drm_i915_private *dev_priv, 
enum phy phy)
if (IS_DG2(dev_priv))
/* DG2's "TC1" output uses a SNPS PHY */
return false;
-   else if (IS_ALDERLAKE_P(dev_priv))
+   else if (IS_ALDERLAKE_P(dev_priv) || IS_METEORLAKE(dev_priv))
return phy >= PHY_F && phy <= PHY_I;
else if (IS_TIGERLAKE(dev_priv))
return phy >= PHY_D && phy <= PHY_I;
diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
b/drivers/gpu/drm/i915/display/intel_tc.c
index f45328712bff..89dfc19de1b8 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -5,6 +5,7 @@
 
 #include "i915_drv.h"
 #include "i915_reg.h"
+#include "intel_cx0_phy_regs.h"
 #include "intel_de.h"
 #include "intel_display.h"
 #include "intel_display_power_map.h"
@@ -300,7 +301,7 @@ static u32 tc_port_live_status_mask(struct 
intel_digital_port *dig_port)
 {
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
 
-   if (IS_ALDERLAKE_P(i915))
+   if (DISPLAY_VER(i915) >= 13)
return adl_tc_port_live_status_mask(dig_port);
 
return icl_tc_port_live_status_mask(dig_port);
@@ -354,11 +355,69 @@ static bool adl_tc_phy_status_complete(struct 
intel_digital_port *dig_port)
return val & TCSS_DDI_STATUS_READY;
 }
 
+static bool xelpdp_wait_phy_status_complete(struct intel_digital_port 
*dig_port)
+{
+   struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+   enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port);
+
+   if (intel_de_wait_for_register(i915,
+  TCSS_DDI_STATUS(tc_port),
+  TCSS_DDI_STATUS_READY,
+  TCSS_DDI_STATUS_READY,
+  1)) {
+   drm_dbg_kms(>drm,
+   "Port %s: PHY in TCCOLD, assuming not complete\n",
+   dig_port->tc_port_name);
+   return false;
+   }
+
+   return true;
+}
+
+static bool xelpdp_wait_for_tcss_power(struct intel_digital_port *dig_port,
+  bool enabled)
+{
+   struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+
+   if (intel_de_wait_for_register(i915,
+  
XELPDP_PORT_BUF_CTL1(dig_port->base.port),
+  XELPDP_TCSS_POWER_STATE,
+  enabled ? XELPDP_TCSS_POWER_STATE : 0,
+  5)) {
+   drm_dbg_kms(>drm,
+   "Port %s: TCSS power state not as expected\n",
+   dig_port->tc_port_name);
+   return false;
+   }
+
+   return true;
+}
+
+static bool xelpdp_tc_power_request(struct intel_digital_port *dig_port, bool 
request)
+{
+   struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+   struct intel_uncore *uncore = >uncore;
+   enum port port = dig_port->base.port;
+   u32 val;
+
+   val = intel_uncore_read(uncore, XELPDP_PORT_BUF_CTL1(port));
+   if (request)
+   val |= XELPDP_TCSS_POWER_REQUEST;
+   else
+   val &= ~XELPDP_TCSS_POWER_REQUEST;
+   intel_uncore_write(uncore, XELPDP_PORT_BUF_CTL1(port), val);
+
+   return xelpdp_wait_phy_status_complete(dig_port) &&
+  xelpdp_wait_for_tcss_power(dig_port, request);
+}
+
 static bool tc_phy_status_complete(struct intel_digital_port *dig_port)
 {
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
 
-   if (IS_ALDERLAKE_P(i915))
+   if (DISPLAY_VER(i915) >= 14)
+   return xelpdp_wait_phy_status_complete(dig_port);
+   else if (IS_ALDERLAKE_P(i915))
return adl_tc_phy_status_complete(dig_port);
 
return icl_tc_phy_status_complete(dig_port);
@@ -400,11 +459,31 @@ static bool adl_tc_phy_take_ownership(struct 
intel_digital_port *dig_port,
return true;
 }
 

[Intel-gfx] [PATCH v5 22/22] drm/i915/mtl: Pin assignment for TypeC

2023-03-16 Thread Mika Kahola
From: Anusha Srivatsa 

Unlike previous platforms that used PORT_TX_DFLEXDPSP
for max_lane calculation, MTL uses only PORT_TX_DFLEXPA1
from which the max_lanes has to be calculated.

Bspec: 50235, 65380

Cc: Mika Kahola 
Cc: Imre Deak 
Cc: Matt Roper 
Signed-off-by: Anusha Srivatsa 
Signed-off-by: Jose Roberto de Souza 
---
 drivers/gpu/drm/i915/display/intel_tc.c | 30 +
 1 file changed, 30 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
b/drivers/gpu/drm/i915/display/intel_tc.c
index 5756daac91d9..694d74088980 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -15,6 +15,10 @@
 #include "intel_mg_phy_regs.h"
 #include "intel_tc.h"
 
+#define DP_PIN_ASSIGNMENT_C0x3
+#define DP_PIN_ASSIGNMENT_D0x4
+#define DP_PIN_ASSIGNMENT_E0x5
+
 static const char *tc_port_mode_name(enum tc_port_mode mode)
 {
static const char * const names[] = {
@@ -147,6 +151,29 @@ u32 intel_tc_port_get_pin_assignment_mask(struct 
intel_digital_port *dig_port)
   DP_PIN_ASSIGNMENT_SHIFT(dig_port->tc_phy_fia_idx);
 }
 
+static int mtl_tc_port_get_pin_assignment_mask(struct intel_digital_port 
*dig_port)
+{
+   struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+   intel_wakeref_t wakeref;
+   u32 pin_mask;
+
+   assert_tc_cold_blocked(dig_port);
+
+   with_intel_display_power(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref)
+   pin_mask = intel_tc_port_get_pin_assignment_mask(dig_port);
+
+   switch(pin_mask) {
+   default:
+   MISSING_CASE(pin_mask);
+   fallthrough;
+   case DP_PIN_ASSIGNMENT_D:
+   return 2;
+   case DP_PIN_ASSIGNMENT_C:
+   case DP_PIN_ASSIGNMENT_E:
+   return 4;
+   }
+}
+
 int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
 {
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
@@ -156,6 +183,9 @@ int intel_tc_port_fia_max_lane_count(struct 
intel_digital_port *dig_port)
if (dig_port->tc_mode != TC_PORT_DP_ALT)
return 4;
 
+   if (DISPLAY_VER(i915) >= 14)
+   return mtl_tc_port_get_pin_assignment_mask(dig_port);
+
assert_tc_cold_blocked(dig_port);
 
lane_mask = 0;
-- 
2.34.1



[Intel-gfx] [PATCH v5 21/22] drm/i915/mtl: TypeC HPD live status query

2023-03-16 Thread Mika Kahola
From: Imre Deak 

The HPD live status for MTL has to be read from different set of
registers. MTL deserves a new function for this purpose
and cannot reuse the existing  HPD live status detection

Signed-off-by: Anusha Srivatsa 
Signed-off-by: Imre Deak 
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_tc.c | 30 +
 1 file changed, 30 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
b/drivers/gpu/drm/i915/display/intel_tc.c
index 89dfc19de1b8..5756daac91d9 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -297,10 +297,40 @@ static u32 adl_tc_port_live_status_mask(struct 
intel_digital_port *dig_port)
return mask;
 }
 
+static u32 xelpdp_tc_port_live_status_mask(struct intel_digital_port *dig_port)
+{
+   struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+   enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port);
+   u32 isr_bit = i915->display.hotplug.pch_hpd[dig_port->base.hpd_pin];
+   struct intel_uncore *uncore = >uncore;
+   u32 val, mask = 0;
+   enum hpd_pin pin;
+
+   val = intel_uncore_read(uncore, PICAINTERRUPT_ISR);
+   pin = HPD_PORT_TC1 + tc_port - TC_PORT_1;
+   if (val & XELPDP_DP_ALT_HOTPLUG(pin))
+   mask |= BIT(TC_PORT_DP_ALT);
+   if (val & XELPDP_TBT_HOTPLUG(pin))
+   mask |= BIT(TC_PORT_TBT_ALT);
+
+   if (dig_port->tc_legacy_port &&
+   intel_uncore_read(uncore, SDEISR) & isr_bit)
+   mask |= BIT(TC_PORT_LEGACY);
+
+   /* The sink can be connected only in a single mode. */
+   if (!drm_WARN_ON(>drm, hweight32(mask) > 1))
+   tc_port_fixup_legacy_flag(dig_port, mask);
+
+   return mask;
+}
+
 static u32 tc_port_live_status_mask(struct intel_digital_port *dig_port)
 {
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
 
+   if (DISPLAY_VER(i915) >= 14)
+   return xelpdp_tc_port_live_status_mask(dig_port);
+
if (DISPLAY_VER(i915) >= 13)
return adl_tc_port_live_status_mask(dig_port);
 
-- 
2.34.1



[Intel-gfx] [PATCH v5 17/22] drm/i915/mtl: Enable TC ports

2023-03-16 Thread Mika Kahola
Finally, we can enable TC ports for Meteorlake.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_display.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 505e99ef17f8..89279814e789 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -7842,9 +7842,12 @@ static void intel_setup_outputs(struct drm_i915_private 
*dev_priv)
return;
 
if (IS_METEORLAKE(dev_priv)) {
-   /* TODO: initialize TC ports as well */
intel_ddi_init(dev_priv, PORT_A);
intel_ddi_init(dev_priv, PORT_B);
+   intel_ddi_init(dev_priv, PORT_TC1);
+   intel_ddi_init(dev_priv, PORT_TC2);
+   intel_ddi_init(dev_priv, PORT_TC3);
+   intel_ddi_init(dev_priv, PORT_TC4);
} else if (IS_DG2(dev_priv)) {
intel_ddi_init(dev_priv, PORT_A);
intel_ddi_init(dev_priv, PORT_B);
-- 
2.34.1



[Intel-gfx] [PATCH v5 15/22] drm/i915/mtl: Enabling/disabling sequence Thunderbolt pll

2023-03-16 Thread Mika Kahola
Enabling and disabling sequence for Thunderbolt PLL.

v2: Use __intel_de_wait_for_register() instead of
__intel_wait_for_register() (Jani)
Use '0' instead of ~XELPDP_TBT_CLOCK_ACK (Gustavo)

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 136 ++-
 drivers/gpu/drm/i915/display/intel_cx0_phy.h |   7 +-
 drivers/gpu/drm/i915/display/intel_ddi.c |   4 +-
 3 files changed, 138 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index e1a919803241..ee281e9de301 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -15,7 +15,6 @@
 #include "intel_panel.h"
 #include "intel_tc.h"
 #include "intel_psr.h"
-#include "intel_uncore.h"
 #include "intel_tc.h"
 
 bool intel_is_c10phy(struct drm_i915_private *dev_priv, enum phy phy)
@@ -2466,8 +2465,8 @@ static u32 intel_cx0_get_pclk_pll_ack(u8 lane)
   XELPDP_LANE1_PCLK_PLL_ACK;
 }
 
-void intel_cx0pll_enable(struct intel_encoder *encoder,
-const struct intel_crtc_state *crtc_state)
+static void intel_cx0pll_enable(struct intel_encoder *encoder,
+   const struct intel_crtc_state *crtc_state)
 {
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
enum phy phy = intel_port_to_phy(i915, encoder->port);
@@ -2540,7 +2539,86 @@ void intel_cx0pll_enable(struct intel_encoder *encoder,
intel_cx0_phy_transaction_end(encoder, wakeref);
 }
 
-void intel_cx0pll_disable(struct intel_encoder *encoder)
+static int intel_mtl_tbt_clock_select(struct drm_i915_private *i915, int clock)
+{
+   switch (clock) {
+   case 162000:
+   return XELPDP_DDI_CLOCK_SELECT_TBT_162;
+   case 27:
+   return XELPDP_DDI_CLOCK_SELECT_TBT_270;
+   case 54:
+   return XELPDP_DDI_CLOCK_SELECT_TBT_540;
+   case 81:
+   return XELPDP_DDI_CLOCK_SELECT_TBT_810;
+   default:
+   MISSING_CASE(clock);
+   return XELPDP_DDI_CLOCK_SELECT_TBT_162;
+   }
+}
+
+static void intel_mtl_tbt_pll_enable(struct intel_encoder *encoder,
+const struct intel_crtc_state *crtc_state)
+{
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+   enum phy phy = intel_port_to_phy(i915, encoder->port);
+   u32 val = 0;
+
+   /*
+* 1. Program PORT_CLOCK_CTL REGISTER to configure
+* clock muxes, gating and SSC
+*/
+   val |= XELPDP_DDI_CLOCK_SELECT(intel_mtl_tbt_clock_select(i915, 
crtc_state->port_clock));
+   val |= XELPDP_FORWARD_CLOCK_UNGATE;
+   intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
+XELPDP_DDI_CLOCK_SELECT_MASK | 
XELPDP_FORWARD_CLOCK_UNGATE, val);
+
+   /* 2. Read back PORT_CLOCK_CTL REGISTER */
+   val = intel_de_read(i915, XELPDP_PORT_CLOCK_CTL(encoder->port));
+
+   /*
+* 3. Follow the Display Voltage Frequency Switching - Sequence
+* Before Frequency Change. We handle this step in bxt_set_cdclk().
+*/
+
+   /*
+* 4. Set PORT_CLOCK_CTL register TBT CLOCK Request to "1" to enable 
PLL.
+*/
+   val |= XELPDP_TBT_CLOCK_REQUEST;
+   intel_de_write(i915, XELPDP_PORT_CLOCK_CTL(encoder->port), val);
+
+   /* 5. Poll on PORT_CLOCK_CTL TBT CLOCK Ack == "1". */
+   if (__intel_de_wait_for_register(i915, 
XELPDP_PORT_CLOCK_CTL(encoder->port),
+XELPDP_TBT_CLOCK_ACK,
+XELPDP_TBT_CLOCK_ACK,
+100, 0, NULL))
+   drm_warn(>drm, "[ENCODER:%d:%s][%c] PHY PLL not locked 
after 100us.\n",
+encoder->base.base.id, encoder->base.name, 
phy_name(phy));
+
+   /*
+* 6. Follow the Display Voltage Frequency Switching Sequence After
+* Frequency Change. We handle this step in bxt_set_cdclk().
+*/
+
+   /*
+* 7. Program DDI_CLK_VALFREQ to match intended DDI
+* clock frequency.
+*/
+   intel_de_write(i915, DDI_CLK_VALFREQ(encoder->port),
+  crtc_state->port_clock);
+}
+
+void intel_mtl_pll_enable(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state)
+{
+   struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+
+   if (intel_tc_port_in_tbt_alt_mode(dig_port))
+   intel_mtl_tbt_pll_enable(encoder, crtc_state);
+   else
+   intel_cx0pll_enable(encoder, crtc_state);
+}
+
+static void intel_cx0pll_disable(struct intel_encoder *encoder)
 {
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
enum phy phy = intel_port_to_phy(i915, encoder->port);
@@ -2592,6 +2670,56 @@ void intel_cx0pll_disable(struct 

[Intel-gfx] [PATCH v5 14/22] drm/i915/mtl: For DP2.0 10G and 20G rates use MPLLA

2023-03-16 Thread Mika Kahola
Use MPLLA for DP2.0 rates 20G and 20G, when ssc is enabled.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 55ec256c0379..e1a919803241 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -2220,8 +2220,12 @@ static void intel_program_port_clock_ctl(struct 
intel_encoder *encoder,
if (!intel_panel_use_ssc(i915))
ssc_enabled = false;
 
-   /* TODO: DP2.0 10G and 20G rates enable MPLLA*/
-   val |= ssc_enabled ? XELPDP_SSC_ENABLE_PLLB : 0;
+   /* DP2.0 10G and 20G rates enable MPLLA*/
+   if (crtc_state->port_clock == 100 || crtc_state->port_clock 
== 200) {
+   val |= ssc_enabled ? XELPDP_SSC_ENABLE_PLLA : 0;
+   } else {
+   val |= ssc_enabled ? XELPDP_SSC_ENABLE_PLLB : 0;
+   }
}
 
intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
-- 
2.34.1



[Intel-gfx] [PATCH v5 12/22] drm/i915/mtl: C20 HDMI state calculations

2023-03-16 Thread Mika Kahola
Add C20 HDMI state calculations and put HDMI table definitions
in use.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 23ebea25aaa9..55ec256c0379 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -1632,6 +1632,8 @@ intel_c20_pll_tables_get(struct intel_crtc_state 
*crtc_state,
 {
if (intel_crtc_has_dp_encoder(crtc_state)) {
return mtl_c20_dp_tables;
+   } else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
+   return mtl_c20_hdmi_tables;
}
 
MISSING_CASE(encoder->type);
@@ -1672,9 +1674,19 @@ static int intel_c10mpllb_calc_state(struct 
intel_crtc_state *crtc_state,
 static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state,
   struct intel_encoder *encoder)
 {
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+   enum phy phy = intel_port_to_phy(i915, encoder->port);
const struct intel_c20pll_state * const *tables;
int i;
 
+   if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
+   if (intel_c20_phy_check_hdmi_link_rate(crtc_state->port_clock) 
!= MODE_OK) {
+   drm_dbg_kms(>drm, "Can't support HDMI link rate 
%d on phy %c.\n",
+   crtc_state->port_clock, phy_name(phy));
+   return -EINVAL;
+   }
+   }
+
tables = intel_c20_pll_tables_get(crtc_state, encoder);
if (!tables)
return -EINVAL;
-- 
2.34.1



[Intel-gfx] [PATCH v5 16/22] drm/i915/mtl: Readout Thunderbolt HW state

2023-03-16 Thread Mika Kahola
Readout hw state for Thunderbolt.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 27 
 drivers/gpu/drm/i915/display/intel_cx0_phy.h |  2 +-
 drivers/gpu/drm/i915/display/intel_ddi.c |  5 +++-
 3 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index ee281e9de301..083595cbc33b 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -2539,6 +2539,33 @@ static void intel_cx0pll_enable(struct intel_encoder 
*encoder,
intel_cx0_phy_transaction_end(encoder, wakeref);
 }
 
+int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder)
+{
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+   u32 clock;
+   u32 val = intel_de_read(i915, XELPDP_PORT_CLOCK_CTL(encoder->port));
+
+   clock = REG_FIELD_GET(XELPDP_DDI_CLOCK_SELECT_MASK, val);
+
+   drm_WARN_ON(>drm, !(val & XELPDP_FORWARD_CLOCK_UNGATE));
+   drm_WARN_ON(>drm, !(val & XELPDP_TBT_CLOCK_REQUEST));
+   drm_WARN_ON(>drm, !(val & XELPDP_TBT_CLOCK_ACK));
+
+   switch (clock) {
+   case XELPDP_DDI_CLOCK_SELECT_TBT_162:
+   return 162000;
+   case XELPDP_DDI_CLOCK_SELECT_TBT_270:
+   return 27;
+   case XELPDP_DDI_CLOCK_SELECT_TBT_540:
+   return 54;
+   case XELPDP_DDI_CLOCK_SELECT_TBT_810:
+   return 81;
+   default:
+   MISSING_CASE(clock);
+   return 162000;
+   }
+}
+
 static int intel_mtl_tbt_clock_select(struct drm_i915_private *i915, int clock)
 {
switch (clock) {
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
index f8a86da4a3f7..9e115ec619ea 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
@@ -53,5 +53,5 @@ int intel_c20_phy_check_hdmi_link_rate(int clock);
 void intel_cx0_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
   const struct intel_crtc_state 
*crtc_state,
   u32 level);
-int intel_mtl_tbt_readout_hw_state(struct intel_encoder *encoder);
+int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder);
 #endif /* __INTEL_CX0_PHY_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index 298cc3ef6c4f..45df36b89162 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -3515,8 +3515,11 @@ static void mtl_ddi_get_config(struct intel_encoder 
*encoder,
 {
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
enum phy phy = intel_port_to_phy(i915, encoder->port);
+   struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
 
-   if (intel_is_c10phy(i915, phy)) {
+   if (intel_tc_port_in_tbt_alt_mode(dig_port)) {
+   crtc_state->port_clock = intel_mtl_tbt_calc_port_clock(encoder);
+   } else if (intel_is_c10phy(i915, phy)) {
intel_c10mpllb_readout_hw_state(encoder, 
_state->cx0pll_state.c10mpllb_state);
intel_c10mpllb_dump_hw_state(i915, 
_state->cx0pll_state.c10mpllb_state);
crtc_state->port_clock = 
intel_c10mpllb_calc_port_clock(encoder, 
_state->cx0pll_state.c10mpllb_state);
-- 
2.34.1



[Intel-gfx] [PATCH v5 19/22] drm/i915/mtl: Define mask for DDI AUX interrupts

2023-03-16 Thread Mika Kahola
From: Gustavo Sousa 

Xe_LPD+ defines interrupt bits for only DDI ports in the DE Port
Interrupt registers. The bits for Type-C ports are defined in the PICA
interrupt registers.

BSpec: 50064
Signed-off-by: Gustavo Sousa 
---
 drivers/gpu/drm/i915/i915_irq.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index e301f4755417..7eef4a5bab46 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1923,7 +1923,10 @@ static u32 gen8_de_port_aux_mask(struct drm_i915_private 
*dev_priv)
 {
u32 mask;
 
-   if (DISPLAY_VER(dev_priv) >= 13)
+   if (DISPLAY_VER(dev_priv) >= 14)
+   return TGL_DE_PORT_AUX_DDIA |
+   TGL_DE_PORT_AUX_DDIB;
+   else if (DISPLAY_VER(dev_priv) >= 13)
return TGL_DE_PORT_AUX_DDIA |
TGL_DE_PORT_AUX_DDIB |
TGL_DE_PORT_AUX_DDIC |
-- 
2.34.1



[Intel-gfx] [PATCH v5 18/22] drm/i915/mtl: MTL PICA hotplug detection

2023-03-16 Thread Mika Kahola
PICA is used for DP alt mode and TBT modes. Hotplug interruption is routed
from PICA chip to south display engine and from there to north display
engine. This patch adds functionality to enable hotplug detection for
all Type-C ports (4 ports available).

Differently from HPD in south display, PICA provides a dedicated HPD
control register for each supported port, so we loop over ports
ourselves instead of using intel_hpd_hotplug_enables() or
intel_get_hpd_pins().

BSpec: 49305, 55726, 65107, 65300

Signed-off-by: Mika Kahola 
Signed-off-by: Madhumitha Tolakanahalli Pradeep 

Signed-off-by: Gustavo Sousa 
Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/i915_irq.c | 249 +++-
 drivers/gpu/drm/i915/i915_reg.h |  31 +++-
 2 files changed, 273 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 4de7edc6c751..e301f4755417 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -160,6 +160,13 @@ static const u32 hpd_gen11[HPD_NUM_PINS] = {
[HPD_PORT_TC6] = GEN11_TC_HOTPLUG(HPD_PORT_TC6) | 
GEN11_TBT_HOTPLUG(HPD_PORT_TC6),
 };
 
+static const u32 hpd_xelpdp[HPD_NUM_PINS] = {
+   [HPD_PORT_TC1] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC1) | 
XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC1),
+   [HPD_PORT_TC2] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC2) | 
XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC2),
+   [HPD_PORT_TC3] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC3) | 
XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC3),
+   [HPD_PORT_TC4] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC4) | 
XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC4),
+};
+
 static const u32 hpd_icp[HPD_NUM_PINS] = {
[HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A),
[HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B),
@@ -180,6 +187,16 @@ static const u32 hpd_sde_dg1[HPD_NUM_PINS] = {
[HPD_PORT_TC1] = SDE_TC_HOTPLUG_DG2(HPD_PORT_TC1),
 };
 
+static const u32 hpd_mtp[HPD_NUM_PINS] = {
+   [HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A),
+   [HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B),
+   [HPD_PORT_TC1] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC1),
+   [HPD_PORT_TC2] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC2),
+   [HPD_PORT_TC3] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC3),
+   [HPD_PORT_TC4] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC4),
+};
+
+
 static void intel_hpd_init_pins(struct drm_i915_private *dev_priv)
 {
struct intel_hotplug *hpd = _priv->display.hotplug;
@@ -193,7 +210,9 @@ static void intel_hpd_init_pins(struct drm_i915_private 
*dev_priv)
return;
}
 
-   if (DISPLAY_VER(dev_priv) >= 11)
+   if (DISPLAY_VER(dev_priv) >= 14)
+   hpd->hpd = hpd_xelpdp;
+   else if (DISPLAY_VER(dev_priv) >= 11)
hpd->hpd = hpd_gen11;
else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
hpd->hpd = hpd_bxt;
@@ -212,6 +231,8 @@ static void intel_hpd_init_pins(struct drm_i915_private 
*dev_priv)
 
if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1)
hpd->pch_hpd = hpd_sde_dg1;
+   else if (INTEL_PCH_TYPE(dev_priv) >= PCH_MTP)
+   hpd->pch_hpd = hpd_mtp;
else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
hpd->pch_hpd = hpd_icp;
else if (HAS_PCH_CNP(dev_priv) || HAS_PCH_SPT(dev_priv))
@@ -1557,6 +1578,44 @@ static void cpt_irq_handler(struct drm_i915_private 
*dev_priv, u32 pch_iir)
cpt_serr_int_handler(dev_priv);
 }
 
+static void xelpdp_pica_irq_handler(struct drm_i915_private *dev_priv, u32 iir)
+{
+   enum hpd_pin pin;
+   u32 hotplug_trigger = iir & (XELPDP_DP_ALT_HOTPLUG_MASK | 
XELPDP_TBT_HOTPLUG_MASK);
+   u32 trigger_aux = iir & XELPDP_AUX_TC_MASK;
+   u32 pin_mask = 0, long_mask = 0;
+
+   for (pin = HPD_PORT_TC1; pin <= HPD_PORT_TC4; pin++) {
+   u32 val;
+
+   if (!(dev_priv->display.hotplug.hpd[pin] & hotplug_trigger))
+   continue;
+
+   pin_mask |= BIT(pin);
+
+   val = intel_uncore_read(_priv->uncore, 
XELPDP_PORT_HOTPLUG_CTL(pin));
+   intel_uncore_write(_priv->uncore, 
XELPDP_PORT_HOTPLUG_CTL(pin), val);
+
+   if (val & (XELPDP_DP_ALT_HPD_LONG_DETECT | 
XELPDP_TBT_HPD_LONG_DETECT))
+   long_mask |= BIT(pin);
+   }
+
+   if (pin_mask) {
+   drm_dbg(_priv->drm,
+   "pica hotplug event received, stat 0x%08x, pins 0x%08x, 
long 0x%08x\n",
+   hotplug_trigger, pin_mask, long_mask);
+
+   intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
+   }
+
+   if (trigger_aux)
+   dp_aux_irq_handler(dev_priv);
+
+   if (!pin_mask && !trigger_aux)
+   drm_err(_priv->drm,
+   "Unexpected DE HPD/AUX interrupt 0x%08x\n", iir);
+}
+
 static void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
 {
u32 ddi_hotplug_trigger = pch_iir & 

[Intel-gfx] [PATCH v5 13/22] drm/i915/mtl: Add voltage swing sequence for C20

2023-03-16 Thread Mika Kahola
DP1.4 and DP20 voltage swing sequence for C20 phy.

Bspec: 65449, 67636, 67610

v2: DP2.0 Tx Eq tables has been updated in BSpec.
Update also the driver code as per BSpec 65449

Signed-off-by: Mika Kahola 
Signed-off-by: Radhakrishna Sripada 
Signed-off-by: Clint Taylor 
---
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h |  4 ++
 .../drm/i915/display/intel_ddi_buf_trans.c| 51 ++-
 2 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h 
b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
index 929a8aa243c3..f8917f20a151 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
@@ -216,6 +216,10 @@
 #define C20_MPLLA_TX_CLK_DIV_MASK   REG_GENMASK(10, 8)
 #define C20_FB_CLK_DIV4_EN  REG_BIT(13)
 
+/* C20 Phy VSwing Masks */
+#define C20_PHY_VSWING_PREEMPH_MASKREG_GENMASK8(5, 0)
+#define C20_PHY_VSWING_PREEMPH(val)
REG_FIELD_PREP8(C20_PHY_VSWING_PREEMPH_MASK, val)
+
 #define RAWLANEAONX_DIG_TX_MPLLB_CAL_DONE_BANK(idx)(0x303D + (idx))
 
 #endif /* __INTEL_CX0_PHY_REGS_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c 
b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c
index d5a9aa2de2fa..883084422f1f 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c
@@ -9,6 +9,7 @@
 #include "intel_de.h"
 #include "intel_display_types.h"
 #include "intel_dp.h"
+#include "intel_cx0_phy.h"
 
 /* HDMI/DVI modes ignore everything but the last 2 items. So we share
  * them for both DP and FDI transports, allowing those ports to
@@ -1059,6 +1060,46 @@ static const struct intel_ddi_buf_trans mtl_cx0_trans = {
.hdmi_default_entry = ARRAY_SIZE(_mtl_c10_trans_dp14) - 1,
 };
 
+/* HDMI2.0 */
+static const union intel_ddi_buf_trans_entry _mtl_c20_trans_hdmi[] = {
+   { .snps = { 48, 0, 0 } },   /* preset 0 */
+   { .snps = { 38, 4, 6 } },   /* preset 1 */
+   { .snps = { 36, 4, 8 } },   /* preset 2 */
+   { .snps = { 34, 4, 10 } },  /* preset 3 */
+   { .snps = { 32, 4, 12 } },  /* preset 4 */
+};
+
+static const struct intel_ddi_buf_trans mtl_c20_trans_hdmi = {
+   .entries = _mtl_c20_trans_hdmi,
+   .num_entries = ARRAY_SIZE(_mtl_c20_trans_hdmi),
+   .hdmi_default_entry = 0,
+};
+
+/* DP2.0 */
+static const union intel_ddi_buf_trans_entry _mtl_c20_trans_uhbr[] = {
+   { .snps = { 48, 0, 0 } },   /* preset 0 */
+   { .snps = { 43, 0, 5 } },   /* preset 1 */
+   { .snps = { 40, 0, 8 } },   /* preset 2 */
+   { .snps = { 37, 0, 11 } },  /* preset 3 */
+   { .snps = { 33, 0, 15 } },  /* preset 4 */
+   { .snps = { 46, 2, 0 } },   /* preset 5 */
+   { .snps = { 42, 2, 4 } },   /* preset 6 */
+   { .snps = { 38, 2, 8 } },   /* preset 7 */
+   { .snps = { 35, 2, 11 } },  /* preset 8 */
+   { .snps = { 33, 2, 13 } },  /* preset 9 */
+   { .snps = { 44, 4, 0 } },   /* preset 10 */
+   { .snps = { 40, 4, 4 } },   /* preset 11 */
+   { .snps = { 37, 4, 7 } },   /* preset 12 */
+   { .snps = { 33, 4, 11 } },  /* preset 13 */
+   { .snps = { 40, 8, 0 } },   /* preset 14 */
+   { .snps = { 28, 2, 2 } },   /* preset 15 */
+};
+
+static const struct intel_ddi_buf_trans mtl_c20_trans_uhbr = {
+   .entries = _mtl_c20_trans_uhbr,
+   .num_entries = ARRAY_SIZE(_mtl_c20_trans_uhbr),
+};
+
 bool is_hobl_buf_trans(const struct intel_ddi_buf_trans *table)
 {
return table == _combo_phy_trans_edp_hbr2_hobl;
@@ -1635,7 +1676,15 @@ mtl_get_cx0_buf_trans(struct intel_encoder *encoder,
  const struct intel_crtc_state *crtc_state,
  int *n_entries)
 {
-   return intel_get_buf_trans(_cx0_trans, n_entries);
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+   enum phy phy = intel_port_to_phy(i915, encoder->port);
+
+   if (intel_crtc_has_dp_encoder(crtc_state) && crtc_state->port_clock > 
100)
+   return intel_get_buf_trans(_c20_trans_uhbr, n_entries);
+   else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) && 
!(intel_is_c10phy(i915, phy)))
+   return intel_get_buf_trans(_c20_trans_hdmi, n_entries);
+   else
+   return intel_get_buf_trans(_cx0_trans, n_entries);
 }
 
 void intel_ddi_buf_trans_init(struct intel_encoder *encoder)
-- 
2.34.1



[Intel-gfx] [PATCH v5 11/22] drm/i915/mtl: C20 port clock calculation

2023-03-16 Thread Mika Kahola
Calculate port clock with C20 phy.

v2: Initialize parameters
v3: Revised formula for port clock check

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 70 ++-
 drivers/gpu/drm/i915/display/intel_cx0_phy.h  |  2 +
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h | 12 ++--
 drivers/gpu/drm/i915/display/intel_ddi.c  |  4 +-
 4 files changed, 78 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index bc6913a7444a..23ebea25aaa9 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -1626,6 +1626,18 @@ intel_c10_mpllb_tables_get(struct intel_crtc_state 
*crtc_state,
return NULL;
 }
 
+static const struct intel_c20pll_state * const *
+intel_c20_pll_tables_get(struct intel_crtc_state *crtc_state,
+struct intel_encoder *encoder)
+{
+   if (intel_crtc_has_dp_encoder(crtc_state)) {
+   return mtl_c20_dp_tables;
+   }
+
+   MISSING_CASE(encoder->type);
+   return NULL;
+}
+
 static int intel_c10mpllb_calc_state(struct intel_crtc_state *crtc_state,
 struct intel_encoder *encoder)
 {
@@ -1657,15 +1669,36 @@ static int intel_c10mpllb_calc_state(struct 
intel_crtc_state *crtc_state,
return -EINVAL;
 }
 
+static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state,
+  struct intel_encoder *encoder)
+{
+   const struct intel_c20pll_state * const *tables;
+   int i;
+
+   tables = intel_c20_pll_tables_get(crtc_state, encoder);
+   if (!tables)
+   return -EINVAL;
+
+   for (i = 0; tables[i]; i++) {
+   if (crtc_state->port_clock <= tables[i]->clock) {
+   crtc_state->cx0pll_state.c20pll_state = *tables[i];
+   return 0;
+   }
+   }
+
+   return -EINVAL;
+}
+
 int intel_cx0mpllb_calc_state(struct intel_crtc_state *crtc_state,
  struct intel_encoder *encoder)
 {
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
enum phy phy = intel_port_to_phy(i915, encoder->port);
 
-   drm_WARN_ON(>drm, !intel_is_c10phy(i915, phy));
-
-   return intel_c10mpllb_calc_state(crtc_state, encoder);
+   if (intel_is_c10phy(i915, phy))
+   return intel_c10mpllb_calc_state(crtc_state, encoder);
+   else
+   return intel_c20pll_calc_state(crtc_state, encoder);
 }
 
 void intel_c10mpllb_readout_hw_state(struct intel_encoder *encoder,
@@ -2111,6 +2144,37 @@ int intel_c10mpllb_calc_port_clock(struct intel_encoder 
*encoder,
return tmpclk;
 }
 
+int intel_c20pll_calc_port_clock(struct intel_encoder *encoder,
+const struct intel_c20pll_state *pll_state)
+{
+   unsigned int frac_quot = 0, frac_rem = 0, frac_den = 1;
+   unsigned int multiplier, refclk = 38400;
+   unsigned ref_clk_mpllb_div = 0;
+   unsigned fb_clk_div4_en = 0;
+   unsigned long tmp1, tmp2;
+
+   if (pll_state->mpllb[6] & C20_MPLLB_FRACEN) {
+   multiplier = REG_FIELD_GET(C20_MULTIPLIER_MASK, 
pll_state->mpllb[0]);
+   ref_clk_mpllb_div = REG_FIELD_GET(C20_REF_CLK_MPLLB_DIV_MASK, 
pll_state->mpllb[6]);
+   fb_clk_div4_en = REG_FIELD_GET(C20_FB_CLK_DIV4_EN, 
pll_state->mpllb[6]);
+   frac_den = pll_state->mpllb[7];
+   frac_quot = pll_state->mpllb[8];
+   frac_rem = pll_state->mpllb[9];
+   } else if (pll_state->mplla[6] & C20_MPLLA_FRACEN) {
+   multiplier = REG_FIELD_GET(C20_MULTIPLIER_MASK, 
pll_state->mplla[0]);
+   ref_clk_mpllb_div = REG_FIELD_GET(C20_REF_CLK_MPLLB_DIV_MASK, 
pll_state->mpllb[6]);
+   fb_clk_div4_en = REG_FIELD_GET(C20_FB_CLK_DIV4_EN, 
pll_state->mpllb[6]);
+   frac_den = pll_state->mpllb[7];
+   frac_quot = pll_state->mplla[8];
+   frac_rem = pll_state->mplla[9];
+   }
+
+   tmp1 = DIV_ROUND_CLOSEST(refclk * (1 << (1 + fb_clk_div4_en)), 1 << 
ref_clk_mpllb_div);
+   tmp2 = (multiplier << 15) + frac_quot + 
DIV_ROUND_CLOSEST(frac_rem,frac_den);
+
+   return DIV_ROUND_CLOSEST((tmp1 * tmp2) >> 17, 10);
+}
+
 static void intel_program_port_clock_ctl(struct intel_encoder *encoder,
 const struct intel_crtc_state 
*crtc_state,
 bool lane_reversal)
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
index 0b46b2ad48a9..0a8e76fd101e 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
@@ -43,6 +43,8 @@ int intel_c10mpllb_calc_port_clock(struct intel_encoder 
*encoder,
   const struct intel_c10mpllb_state 

[Intel-gfx] [PATCH v5 10/22] drm/i915/mtl: Dump C20 pll hw state

2023-03-16 Thread Mika Kahola
As we already do with C10 chip, let's dump the pll
hw state for C20 as well.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 20 
 drivers/gpu/drm/i915/display/intel_cx0_phy.h |  2 ++
 drivers/gpu/drm/i915/display/intel_ddi.c |  1 +
 3 files changed, 23 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index bfb264ea154a..bc6913a7444a 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -1874,6 +1874,26 @@ void intel_c20pll_readout_hw_state(struct intel_encoder 
*encoder,
}
 }
 
+void intel_c20pll_dump_hw_state(struct drm_i915_private *i915,
+   const struct intel_c20pll_state *hw_state)
+{
+   int i;
+
+   drm_dbg_kms(>drm, "c20pll_hw_state:\n");
+   drm_dbg_kms(>drm, "tx[0] = 0x%.4x, tx[1] = 0x%.4x, tx[2] = 
0x%.4x\n",
+   hw_state->tx[0], hw_state->tx[1], hw_state->tx[2]);
+   drm_dbg_kms(>drm, "cmn[0] = 0x%.4x, cmn[1] = 0x%.4x, cmn[2] = 
0x%.4x, cmn[3] = 0x%.4x\n",
+   hw_state->cmn[0], hw_state->cmn[1], hw_state->cmn[2], 
hw_state->cmn[3]);
+
+   if (intel_c20_use_mplla(hw_state->clock)) {
+   for (i = 0; i < ARRAY_SIZE(hw_state->mplla); i++)
+   drm_dbg_kms(>drm, "mplla[%d] = 0x%.4x\n", i, 
hw_state->mplla[i]);
+   } else {
+   for (i = 0; i < ARRAY_SIZE(hw_state->mpllb); i++)
+   drm_dbg_kms(>drm, "mpllb[%d] = 0x%.4x\n", i, 
hw_state->mpllb[i]);
+   }
+}
+
 static u8 intel_c20_get_dp_rate(u32 clock)
 {
switch (clock) {
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
index cf603080ce3d..0b46b2ad48a9 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
@@ -37,6 +37,8 @@ void intel_c20pll_readout_hw_state(struct intel_encoder 
*encoder,
struct intel_c20pll_state *pll_state);
 void intel_c10mpllb_dump_hw_state(struct drm_i915_private *dev_priv,
  const struct intel_c10mpllb_state *hw_state);
+void intel_c20pll_dump_hw_state(struct drm_i915_private *i915,
+   const struct intel_c20pll_state *hw_state);
 int intel_c10mpllb_calc_port_clock(struct intel_encoder *encoder,
   const struct intel_c10mpllb_state 
*pll_state);
 void intel_c10mpllb_state_verify(struct intel_atomic_state *state,
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index 14b8dcee1c0c..d94add6e322d 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -3521,6 +3521,7 @@ static void mtl_ddi_get_config(struct intel_encoder 
*encoder,
intel_c10mpllb_dump_hw_state(i915, 
_state->cx0pll_state.c10mpllb_state);
} else {
intel_c20pll_readout_hw_state(encoder, 
_state->cx0pll_state.c20pll_state);
+   intel_c20pll_dump_hw_state(i915, 
_state->cx0pll_state.c20pll_state);
}
 
crtc_state->port_clock = intel_c10mpllb_calc_port_clock(encoder, 
_state->cx0pll_state.c10mpllb_state);
-- 
2.34.1



[Intel-gfx] [PATCH v5 08/22] drm/i915/mtl: C20 PLL programming

2023-03-16 Thread Mika Kahola
C20 phy PLL programming sequence for DP, DP2.0, HDMI2.x non-FRL and
HDMI2.x FRL. This enables C20 MPLLA and MPLLB programming sequence. add
4 lane support for c20.

v2: Rename intel_c20_write() to intel_c20_sram_write() (Gustavo)
Remove unnecessary bit masks (Gustavo)
Fix comments on C20 pll programming (Gustavo)
Clear calibration banks for both lanes (Gustavo)

Signed-off-by: José Roberto de Souza 
Signed-off-by: Mika Kahola 
Signed-off-by: Bhanuprakash Modem 
Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 266 +++---
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h |  30 ++
 drivers/gpu/drm/i915/display/intel_ddi.c  |  11 +-
 .../drm/i915/display/intel_display_types.h|  19 +-
 drivers/gpu/drm/i915/display/intel_dp.c   |  12 +-
 5 files changed, 298 insertions(+), 40 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 3d61afbe7bdb..730c70f82822 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -15,6 +15,7 @@
 #include "intel_tc.h"
 #include "intel_psr.h"
 #include "intel_uncore.h"
+#include "intel_tc.h"
 
 bool intel_is_c10phy(struct drm_i915_private *dev_priv, enum phy phy)
 {
@@ -235,6 +236,18 @@ static void intel_cx0_write(struct drm_i915_private *i915, 
enum port port,
}
 }
 
+static void intel_c20_sram_write(struct drm_i915_private *i915, enum port port,
+int lane, u16 addr, u16 data)
+{
+   assert_dc_off(i915);
+
+   intel_cx0_write(i915, port, lane, PHY_C20_WR_ADDRESS_H, (addr >> 8), 0);
+   intel_cx0_write(i915, port, lane, PHY_C20_WR_ADDRESS_L, addr & 0xff, 0);
+
+   intel_cx0_write(i915, port, lane, PHY_C20_WR_DATA_H, (data >> 8), 0);
+   intel_cx0_write(i915, port, lane, PHY_C20_WR_DATA_L, data & 0xff, 1);
+}
+
 static void __intel_cx0_rmw(struct drm_i915_private *i915, enum port port,
int lane, u16 addr, u8 clear, u8 set, bool 
committed)
 {
@@ -1157,7 +1170,7 @@ static int intel_c10mpllb_calc_state(struct 
intel_crtc_state *crtc_state,
 
for (i = 0; tables[i]; i++) {
if (crtc_state->port_clock <= tables[i]->clock) {
-   crtc_state->c10mpllb_state = *tables[i];
+   crtc_state->cx0pll_state.c10mpllb_state = *tables[i];
return 0;
}
}
@@ -1217,7 +1230,7 @@ static void intel_c10_pll_program(struct drm_i915_private 
*i915,
  const struct intel_crtc_state *crtc_state,
  struct intel_encoder *encoder)
 {
-   const struct intel_c10mpllb_state *pll_state = 
_state->c10mpllb_state;
+   const struct intel_c10mpllb_state *pll_state = 
_state->cx0pll_state.c10mpllb_state;
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
bool lane_reversal = dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL;
u8 master_lane = lane_reversal ? INTEL_CX0_LANE1 :
@@ -1301,6 +1314,205 @@ void intel_c10mpllb_dump_hw_state(struct 
drm_i915_private *dev_priv,
i + 2, hw_state->pll[i + 2], i + 3, hw_state->pll[i 
+ 3]);
 }
 
+static bool intel_c20_use_mplla(u32 clock)
+{
+   /* 10G and 20G rates use MPLLA */
+   if (clock == 312500 || clock == 625000)
+   return true;
+
+   return false;
+}
+
+static u8 intel_c20_get_dp_rate(u32 clock)
+{
+   switch (clock) {
+   case 162000: /* 1.62 Gbps DP1.4 */
+   return 0;
+   case 27: /* 2.7 Gbps DP1.4 */
+   return 1;
+   case 54: /* 5.4 Gbps DP 1.4 */
+   return 2;
+   case 81: /* 8.1 Gbps DP1.4 */
+   return 3;
+   case 216000: /* 2.16 Gbps eDP */
+   return 4;
+   case 243000: /* 2.43 Gbps eDP */
+   return 5;
+   case 324000: /* 3.24 Gbps eDP */
+   return 6;
+   case 432000: /* 4.32 Gbps eDP */
+   return 7;
+   case 312500: /* 10 Gbps DP2.0 */
+   return 8;
+   case 421875: /* 13.5 Gbps DP2.0 */
+   return 9;
+   case 625000: /* 20 Gbps DP2.0*/
+   return 10;
+   default:
+   MISSING_CASE(clock);
+   return 0;
+   }
+}
+
+static u8 intel_c20_get_hdmi_rate(u32 clock)
+{
+   switch (clock) {
+   case 25175:
+   case 27000:
+   case 74250:
+   case 148500:
+   case 594000:
+   return 0;
+   case 166670: /* 3 Gbps */
+   case 30: /* 6 Gbps */
+   case 70: /* 12 Gbps */
+   return 1;
+   case 40: /* 8 Gbps */
+   return 2;
+   case 60: /* 10 Gbps */
+   return 3;
+   default:
+   MISSING_CASE(clock);
+   return 0;
+   }
+}
+
+static bool is_dp2(u32 clock)
+{
+   /* DP2.0 clock 

[Intel-gfx] [PATCH v5 09/22] drm/i915/mtl: C20 HW readout

2023-03-16 Thread Mika Kahola
Create a table for C20 DP1.4, DP2.0 and HDMI2.1 rates.
The PLL settings are based on table, not for algorithmic alternative.
For DP 1.4 only MPLLB is in use.

Once register settings are done, we read back C20 HW state.

BSpec: 64568

v2: Update rbr, hbr1, hbr2, and hbr3 pll configurations 4 and 5
based on changes in BSpec consolidated table
v3: Rename intel_c20_read() to intel_c20_sram_read() (Gustavo)
Use context and correct MPLLA reg bit to select if MPLLA is in
use or not (Gustavo)

Signed-off-by: Mika Kahola 
Signed-off-by: Clint Taylor 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 553 ++-
 drivers/gpu/drm/i915/display/intel_cx0_phy.h |   8 +-
 drivers/gpu/drm/i915/display/intel_ddi.c |   9 +-
 drivers/gpu/drm/i915/display/intel_hdmi.c|   6 +-
 drivers/gpu/drm/i915/display/intel_hdmi.h|   1 +
 5 files changed, 569 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 730c70f82822..bfb264ea154a 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -11,6 +11,7 @@
 #include "intel_de.h"
 #include "intel_display_types.h"
 #include "intel_dp.h"
+#include "intel_hdmi.h"
 #include "intel_panel.h"
 #include "intel_tc.h"
 #include "intel_psr.h"
@@ -248,6 +249,23 @@ static void intel_c20_sram_write(struct drm_i915_private 
*i915, enum port port,
intel_cx0_write(i915, port, lane, PHY_C20_WR_DATA_L, data & 0xff, 1);
 }
 
+static u16 intel_c20_sram_read(struct drm_i915_private *i915, enum port port,
+   int lane, u16 addr)
+{
+   u16 val;
+
+   assert_dc_off(i915);
+
+   intel_cx0_write(i915, port, lane, PHY_C20_RD_ADDRESS_H, (addr >> 8), 1);
+   intel_cx0_write(i915, port, lane, PHY_C20_RD_ADDRESS_L, addr & 0xff, 0);
+
+   val = intel_cx0_read(i915, port, lane, PHY_C20_RD_DATA_H);
+   val <<= 8;
+   val |= intel_cx0_read(i915, port, lane, PHY_C20_RD_DATA_L);
+
+   return val;
+}
+
 static void __intel_cx0_rmw(struct drm_i915_private *i915, enum port port,
int lane, u16 addr, u8 clear, u8 set, bool 
committed)
 {
@@ -598,6 +616,192 @@ static const struct intel_c10mpllb_state * const 
mtl_c10_edp_tables[] = {
NULL,
 };
 
+/* C20 basic DP 1.4 tables */
+static const struct intel_c20pll_state mtl_c20_dp_rbr = {
+   .clock = 162000,
+   .tx = { 0xbe88, /* tx cfg0 */
+   0x5800, /* tx cfg1 */
+   0x, /* tx cfg2 */
+   },
+   .cmn = {0x0500, /* cmn cfg0*/
+   0x0005, /* cmn cfg1 */
+   0x, /* cmn cfg2 */
+   0x, /* cmn cfg3 */
+   },
+   .mpllb = { 0x50a8,  /* mpllb cfg0 */
+   0x2120, /* mpllb cfg1 */
+   0xcd9a, /* mpllb cfg2 */
+   0xbfc1, /* mpllb cfg3 */
+   0x5ab8, /* mpllb cfg4 */
+   0x4c34, /* mpllb cfg5 */
+   0x2000, /* mpllb cfg6 */
+   0x0001, /* mpllb cfg7 */
+   0x6000, /* mpllb cfg8 */
+   0x, /* mpllb cfg9 */
+   0x, /* mpllb cfg10 */
+   },
+};
+
+static const struct intel_c20pll_state mtl_c20_dp_hbr1 = {
+   .clock = 27,
+   .tx = { 0xbe88, /* tx cfg0 */
+   0x4800, /* tx cfg1 */
+   0x, /* tx cfg2 */
+   },
+   .cmn = {0x0500, /* cmn cfg0*/
+   0x0005, /* cmn cfg1 */
+   0x, /* cmn cfg2 */
+   0x, /* cmn cfg3 */
+   },
+   .mpllb = { 0x308c,  /* mpllb cfg0 */
+   0x2110, /* mpllb cfg1 */
+   0xcc9c, /* mpllb cfg2 */
+   0xbfc1, /* mpllb cfg3 */
+   0x489a, /* mpllb cfg4 */
+   0x3f81, /* mpllb cfg5 */
+   0x2000, /* mpllb cfg6 */
+   0x0001, /* mpllb cfg7 */
+   0x5000, /* mpllb cfg8 */
+   0x, /* mpllb cfg9 */
+   0x, /* mpllb cfg10 */
+   },
+};
+
+static const struct intel_c20pll_state mtl_c20_dp_hbr2 = {
+   .clock = 54,
+   .tx = { 0xbe88, /* tx cfg0 */
+   0x4800, /* tx cfg1 */
+   0x, /* tx cfg2 */
+   },
+   .cmn = {0x0500, /* cmn cfg0*/
+   0x0005, /* cmn cfg1 */
+   0x, /* cmn cfg2 */
+   0x, /* cmn cfg3 */
+   },
+   .mpllb = { 0x108c,  /* mpllb cfg0 */
+   0x2108, /* mpllb cfg1 */
+   0xcc9c, /* mpllb cfg2 */
+   0xbfc1, /* mpllb cfg3 */
+   0x489a, /* mpllb cfg4 */
+   0x3f81, /* mpllb cfg5 */
+   0x2000, 

[Intel-gfx] [PATCH v5 05/22] drm/i915/mtl: Add C10 phy programming for HDMI

2023-03-16 Thread Mika Kahola
From: Radhakrishna Sripada 

Like DG2, we still don't have a proper algorithm that can be used
for calculating PHY settings, but we do have tables of register
values for a handful of the more common link rates. Some support is
better than none, so let's go ahead and add/use these tables when we
can, and also add some logic to hdmi_port_clock_valid() to filter the
modelist to just the modes we can actually support with these link
rates.

Hopefully we'll have a proper / non-encumbered algorithm to calculate
these registers by the time we upstream and we'll be able to replace
this patch with something more general purpose.

Bspec: 64568

v2: Rebasing with Clint's HDMI C10 PLL tables (Mika)

v3: Add missing use_hdmi checks from Clint's HDMI implementation changes (Ankit)
Remove unused table

Cc: Imre Deak 
Cc: Uma Shankar 
Signed-off-by: Radhakrishna Sripada 
Signed-off-by: Clint Taylor 
Signed-off-by: Mika Kahola 
Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 576 +-
 drivers/gpu/drm/i915/display/intel_cx0_phy.h  |   1 +
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h |   2 +
 drivers/gpu/drm/i915/display/intel_hdmi.c |   5 +-
 4 files changed, 573 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index dce55f0ed5e1..c73d2bc3e1a8 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -485,6 +485,538 @@ static const struct intel_c10mpllb_state * const 
mtl_c10_edp_tables[] = {
NULL,
 };
 
+/*
+ * HDMI link rates with 38.4 MHz reference clock.
+ */
+
+static const struct intel_c10mpllb_state mtl_c10_hdmi_25_2 = {
+   .clock = 25200,
+   .pll[0] = 0x4,
+   .pll[1] = 0,
+   .pll[2] = 0xB2,
+   .pll[3] = 0,
+   .pll[4] = 0,
+   .pll[5] = 0,
+   .pll[6] = 0,
+   .pll[7] = 0,
+   .pll[8] = 0x20,
+   .pll[9] = 0x1,
+   .pll[10] = 0,
+   .pll[11] = 0,
+   .pll[12] = 0,
+   .pll[13] = 0,
+   .pll[14] = 0,
+   .pll[15] = 0xD,
+   .pll[16] = 0x6,
+   .pll[17] = 0x8F,
+   .pll[18] = 0x84,
+   .pll[19] = 0x23,
+};
+
+static const struct intel_c10mpllb_state mtl_c10_hdmi_27_0 = {
+   .clock = 27000,
+   .pll[0] = 0x34,
+   .pll[1] = 0,
+   .pll[2] = 0xC0,
+   .pll[3] = 0,
+   .pll[4] = 0,
+   .pll[5] = 0,
+   .pll[6] = 0,
+   .pll[7] = 0,
+   .pll[8] = 0x20,
+   .pll[9] = 0x1,
+   .pll[10] = 0,
+   .pll[11] = 0,
+   .pll[12] = 0x80,
+   .pll[13] = 0,
+   .pll[14] = 0,
+   .pll[15] = 0xD,
+   .pll[16] = 0x6,
+   .pll[17] = 0xCF,
+   .pll[18] = 0x84,
+   .pll[19] = 0x23,
+};
+
+static const struct intel_c10mpllb_state mtl_c10_hdmi_74_25 = {
+   .clock = 74250,
+   .pll[0] = 0xF4,
+   .pll[1] = 0,
+   .pll[2] = 0x7A,
+   .pll[3] = 0,
+   .pll[4] = 0,
+   .pll[5] = 0,
+   .pll[6] = 0,
+   .pll[7] = 0,
+   .pll[8] = 0x20,
+   .pll[9] = 0x1,
+   .pll[10] = 0,
+   .pll[11] = 0,
+   .pll[12] = 0x58,
+   .pll[13] = 0,
+   .pll[14] = 0,
+   .pll[15] = 0xB,
+   .pll[16] = 0x6,
+   .pll[17] = 0xF,
+   .pll[18] = 0x85,
+   .pll[19] = 0x23,
+};
+
+static const struct intel_c10mpllb_state mtl_c10_hdmi_148_5 = {
+   .clock = 148500,
+   .pll[0] = 0xF4,
+   .pll[1] = 0,
+   .pll[2] = 0x7A,
+   .pll[3] = 0,
+   .pll[4] = 0,
+   .pll[5] = 0,
+   .pll[6] = 0,
+   .pll[7] = 0,
+   .pll[8] = 0x20,
+   .pll[9] = 0x1,
+   .pll[10] = 0,
+   .pll[11] = 0,
+   .pll[12] = 0x58,
+   .pll[13] = 0,
+   .pll[14] = 0,
+   .pll[15] = 0xA,
+   .pll[16] = 0x6,
+   .pll[17] = 0xF,
+   .pll[18] = 0x85,
+   .pll[19] = 0x23,
+};
+
+static const struct intel_c10mpllb_state mtl_c10_hdmi_594 = {
+   .clock = 594000,
+   .pll[0] = 0xF4,
+   .pll[1] = 0,
+   .pll[2] = 0x7A,
+   .pll[3] = 0,
+   .pll[4] = 0,
+   .pll[5] = 0,
+   .pll[6] = 0,
+   .pll[7] = 0,
+   .pll[8] = 0x20,
+   .pll[9] = 0x1,
+   .pll[10] = 0,
+   .pll[11] = 0,
+   .pll[12] = 0x58,
+   .pll[13] = 0,
+   .pll[14] = 0,
+   .pll[15] = 0x8,
+   .pll[16] = 0x6,
+   .pll[17] = 0xF,
+   .pll[18] = 0x85,
+   .pll[19] = 0x23,
+};
+
+/* Precomputed C10 HDMI PLL tables */
+static const struct intel_c10mpllb_state mtl_c10_hdmi_25175 = {
+   .clock = 25175,
+   .pll[0]=0x34,
+   .pll[1]=0x00,
+   .pll[2]=0xB0,
+   .pll[3]=0x00,
+   .pll[4]=0x00,
+   .pll[5]=0x00,
+   .pll[6]=0x00,
+   .pll[7]=0x00,
+   .pll[8]=0x20,
+   .pll[9]=0xFF,
+   .pll[10]=0xFF,
+   .pll[11]=0x55,
+   .pll[12]=0xE5,
+   .pll[13]=0x55,
+   .pll[14]=0x55,
+   .pll[15]=0x0D,
+   .pll[16]=0x09,
+   .pll[17]=0x8F,
+   .pll[18]=0x84,
+   

[Intel-gfx] [PATCH v5 06/22] drm/i915/mtl: Add vswing programming for C10 phys

2023-03-16 Thread Mika Kahola
From: Radhakrishna Sripada 

C10 phys uses direct mapping internally for voltage and pre-emphasis levels.
Program the levels directly to the fields in the VDR Registers.

Bspec: 65449

v2: From table "C10: Tx EQ settings for DP 1.4x" it shows level 1
and preemphasis 1 instead of two times of level 1 preemphasis 0.
Fix this in the driver code as well.
v3: VSwing update (Clint)

Cc: Imre Deak 
Cc: Uma Shankar 
Signed-off-by: Clint Taylor 
Signed-off-by: Radhakrishna Sripada 
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 140 --
 drivers/gpu/drm/i915/display/intel_cx0_phy.h  |   2 +
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h |  14 ++
 drivers/gpu/drm/i915/display/intel_ddi.c  |   4 +-
 .../drm/i915/display/intel_ddi_buf_trans.c|  36 -
 .../drm/i915/display/intel_ddi_buf_trans.h|   6 +
 .../i915/display/intel_display_power_map.c|   1 +
 7 files changed, 192 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index c73d2bc3e1a8..3d61afbe7bdb 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -6,11 +6,15 @@
 #include "i915_reg.h"
 #include "intel_cx0_phy.h"
 #include "intel_cx0_phy_regs.h"
+#include "intel_ddi.h"
+#include "intel_ddi_buf_trans.h"
 #include "intel_de.h"
 #include "intel_display_types.h"
 #include "intel_dp.h"
 #include "intel_panel.h"
 #include "intel_tc.h"
+#include "intel_psr.h"
+#include "intel_uncore.h"
 
 bool intel_is_c10phy(struct drm_i915_private *dev_priv, enum phy phy)
 {
@@ -20,6 +24,15 @@ bool intel_is_c10phy(struct drm_i915_private *dev_priv, enum 
phy phy)
return false;
 }
 
+static void
+assert_dc_off(struct drm_i915_private *i915)
+{
+   bool enabled;
+
+   enabled = intel_display_power_is_enabled(i915, POWER_DOMAIN_DC_OFF);
+   drm_WARN_ON(>drm, !enabled);
+}
+
 static void intel_cx0_bus_reset(struct drm_i915_private *i915, enum port port, 
int lane)
 {
enum phy phy = intel_port_to_phy(i915, port);
@@ -112,6 +125,8 @@ static u8 intel_cx0_read(struct drm_i915_private *i915, 
enum port port,
int i, status = 0;
u32 val;
 
+   assert_dc_off(i915);
+
for (i = 0; i < 3; i++) {
status = __intel_cx0_read(i915, port, lane, addr, );
 
@@ -194,6 +209,8 @@ static void __intel_cx0_write(struct drm_i915_private 
*i915, enum port port,
enum phy phy = intel_port_to_phy(i915, port);
int i, status;
 
+   assert_dc_off(i915);
+
for (i = 0; i < 3; i++) {
status = __intel_cx0_write_once(i915, port, lane, addr, data, 
committed);
 
@@ -241,6 +258,89 @@ static void intel_cx0_rmw(struct drm_i915_private *i915, 
enum port port,
}
 }
 
+/*
+ * Prepare HW for CX0 phy transactions.
+ *
+ * It is required that PSR and DC5/6 are disabled before any CX0 message
+ * bus transaction is executed.
+ */
+static intel_wakeref_t intel_cx0_phy_transaction_begin(struct intel_encoder 
*encoder)
+{
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+   struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+   intel_psr_pause(intel_dp);
+   return intel_display_power_get(i915, POWER_DOMAIN_DC_OFF);
+}
+
+static void intel_cx0_phy_transaction_end(struct intel_encoder *encoder, 
intel_wakeref_t wakeref)
+{
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+   struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+   intel_psr_resume(intel_dp);
+   intel_display_power_put(i915, POWER_DOMAIN_DC_OFF, wakeref);
+}
+
+void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder,
+const struct intel_crtc_state *crtc_state)
+{
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+   struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+   bool lane_reversal = dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL;
+   u8 master_lane = lane_reversal ? INTEL_CX0_LANE1 :
+INTEL_CX0_LANE0;
+   u8 follower_lane = lane_reversal ? INTEL_CX0_LANE0 :
+INTEL_CX0_LANE1;
+   const struct intel_ddi_buf_trans *trans;
+   intel_wakeref_t wakeref;
+   int n_entries, ln;
+
+   wakeref = intel_cx0_phy_transaction_begin(encoder);
+
+   trans = encoder->get_buf_trans(encoder, crtc_state, _entries);
+   if (drm_WARN_ON_ONCE(>drm, !trans))
+   return;
+
+   intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, 
PHY_C10_VDR_CONTROL(1),
+ 0, C10_VDR_CTRL_MSGBUS_ACCESS, MB_WRITE_COMMITTED);
+
+   for (ln = 0; ln < 4; ln++) {
+   int level = intel_ddi_level(encoder, crtc_state, ln);
+   int lane, tx;
+
+   lane = ln / 2 + 1;
+   tx = ln % 2 + 1;
+
+   

[Intel-gfx] [PATCH v5 07/22] drm/i915/mtl: Add support for PM DEMAND

2023-03-16 Thread Mika Kahola
XE_LPD+ introduces a new way to instruct the PUnit with
power and bandwidth requirements of DE. Add the functionality
to program the registers and handle waits using interrupts.
The current wait time for timeouts is programmed for 10 msecs to
factor in the worst case scenarios. Changes made to use REG_BIT
for a register that we touched(GEN8_DE_MISC_IER _MMIO).

v2:
  - Removed repeated definition of dbuf, which has been moved to struct
intel_display. (Gustavo)
  - s/dev_priv->dbuf/dev_priv->display.dbuf/ (Gustavo)
v3: Move display version check (Arun)

Bspec: 66451, 64636, 64602, 64603
Cc: Matt Atwood 
Cc: Matt Roper 
Cc: Lucas De Marchi 
Cc: Gustavo Sousa 
Signed-off-by: José Roberto de Souza 
Signed-off-by: Radhakrishna Sripada 
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_bw.c   |   4 +-
 drivers/gpu/drm/i915/display/intel_bw.h   |   2 +
 drivers/gpu/drm/i915/display/intel_display.c  |  14 +
 .../drm/i915/display/intel_display_power.c|   6 +
 drivers/gpu/drm/i915/i915_drv.h   |   6 +
 drivers/gpu/drm/i915/i915_irq.c   |  22 +-
 drivers/gpu/drm/i915/i915_reg.h   |  33 +-
 drivers/gpu/drm/i915/intel_pm.c   | 289 ++
 drivers/gpu/drm/i915/intel_pm.h   |  36 +++
 9 files changed, 407 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bw.c 
b/drivers/gpu/drm/i915/display/intel_bw.c
index 202321ffbe2a..87c20bf52123 100644
--- a/drivers/gpu/drm/i915/display/intel_bw.c
+++ b/drivers/gpu/drm/i915/display/intel_bw.c
@@ -746,8 +746,8 @@ static unsigned int intel_bw_num_active_planes(struct 
drm_i915_private *dev_priv
return num_active_planes;
 }
 
-static unsigned int intel_bw_data_rate(struct drm_i915_private *dev_priv,
-  const struct intel_bw_state *bw_state)
+unsigned int intel_bw_data_rate(struct drm_i915_private *dev_priv,
+   const struct intel_bw_state *bw_state)
 {
unsigned int data_rate = 0;
enum pipe pipe;
diff --git a/drivers/gpu/drm/i915/display/intel_bw.h 
b/drivers/gpu/drm/i915/display/intel_bw.h
index f20292143745..17fc0b61db04 100644
--- a/drivers/gpu/drm/i915/display/intel_bw.h
+++ b/drivers/gpu/drm/i915/display/intel_bw.h
@@ -62,6 +62,8 @@ int intel_bw_init(struct drm_i915_private *dev_priv);
 int intel_bw_atomic_check(struct intel_atomic_state *state);
 void intel_bw_crtc_update(struct intel_bw_state *bw_state,
  const struct intel_crtc_state *crtc_state);
+unsigned int intel_bw_data_rate(struct drm_i915_private *dev_priv,
+   const struct intel_bw_state *bw_state);
 int icl_pcode_restrict_qgv_points(struct drm_i915_private *dev_priv,
  u32 points_mask);
 int intel_bw_calc_min_cdclk(struct intel_atomic_state *state,
diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 1ac05dc68db5..505e99ef17f8 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -960,6 +960,9 @@ intel_get_crtc_new_encoder(const struct intel_atomic_state 
*state,
num_encoders++;
}
 
+   if (!encoder)
+   return NULL;
+
drm_WARN(encoder->base.dev, num_encoders != 1,
 "%d encoders for pipe %c\n",
 num_encoders, pipe_name(master_crtc->pipe));
@@ -6825,6 +6828,10 @@ int intel_atomic_check(struct drm_device *dev,
ret = intel_modeset_calc_cdclk(state);
if (ret)
return ret;
+
+   ret = intel_pmdemand_atomic_check(state);
+   if (ret)
+   goto fail;
}
 
ret = intel_atomic_check_crtcs(state);
@@ -7441,6 +7448,7 @@ static void intel_atomic_commit_tail(struct 
intel_atomic_state *state)
}
 
intel_sagv_pre_plane_update(state);
+   intel_pmdemand_pre_plane_update(state);
 
/* Complete the events for pipes that have now been disabled */
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
@@ -7553,6 +7561,7 @@ static void intel_atomic_commit_tail(struct 
intel_atomic_state *state)
intel_verify_planes(state);
 
intel_sagv_post_plane_update(state);
+   intel_pmdemand_post_plane_update(state);
 
drm_atomic_helper_commit_hw_done(>base);
 
@@ -8284,6 +8293,7 @@ void intel_init_display_hooks(struct drm_i915_private 
*dev_priv)
intel_color_init_hooks(dev_priv);
intel_init_cdclk_hooks(dev_priv);
intel_audio_hooks_init(dev_priv);
+   intel_init_pmdemand(dev_priv);
 
intel_dpll_init_clock_hook(dev_priv);
 
@@ -8510,6 +8520,10 @@ int intel_modeset_init_noirq(struct drm_i915_private 
*i915)
if (ret)
goto cleanup_vga_client_pw_domain_dmc;
 
+   ret = intel_pmdemand_init(i915);
+   if 

[Intel-gfx] [PATCH v5 03/22] drm/i915/mtl: Create separate reg file for PICA registers

2023-03-16 Thread Mika Kahola
Create a separate file to store registers for PICA chips
C10 and C20.

v2: Rename file (Jani)
v3: Use _PICK_EVEN_2RANGES() macro (Lucas)

Signed-off-by: Radhakrishna Sripada 
Signed-off-by: Mika Kahola 
---
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h | 139 ++
 1 file changed, 139 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h 
b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
new file mode 100644
index ..13e9bdd5df9d
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
@@ -0,0 +1,139 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright © 2022 Intel Corporation
+ */
+
+#ifndef __INTEL_CX0_PHY_REGS_H__
+#define __INTEL_CX0_PHY_REGS_H__
+
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_A  0x64040
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_B  0x64140
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC1  0x16F240
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC2  0x16F440
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC3  0x16F640
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC4  0x16F840
+#define _XELPDP_PORT_M2P_MSGBUS_CTL(port, lane)(_PICK(port, \
+   [PORT_A] = 
_XELPDP_PORT_M2P_MSGBUS_CTL_LN0_A, \
+   [PORT_B] = 
_XELPDP_PORT_M2P_MSGBUS_CTL_LN0_B, \
+   [PORT_TC1] = 
_XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC1, \
+   [PORT_TC2] = 
_XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC2, \
+   [PORT_TC3] = 
_XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC3, \
+   [PORT_TC4] = 
_XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC4) + ((lane) * 4))
+#define XELPDP_PORT_M2P_MSGBUS_CTL(port, lane) 
_MMIO(_PICK_EVEN_2RANGES(port, PORT_TC1, \
+   
 _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_A, \
+   
 _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_B, \
+   
 _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC1, \
+   
 _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC2))
+#define XELPDP_PORT_M2P_TRANSACTION_PENDINGREG_BIT(31)
+#define XELPDP_PORT_M2P_COMMAND_TYPE_MASK  REG_GENMASK(30, 27)
+#define XELPDP_PORT_M2P_COMMAND_WRITE_UNCOMMITTED  
REG_FIELD_PREP(XELPDP_PORT_M2P_COMMAND_TYPE_MASK, 0x1)
+#define XELPDP_PORT_M2P_COMMAND_WRITE_COMMITTED
REG_FIELD_PREP(XELPDP_PORT_M2P_COMMAND_TYPE_MASK, 0x2)
+#define XELPDP_PORT_M2P_COMMAND_READ   
REG_FIELD_PREP(XELPDP_PORT_M2P_COMMAND_TYPE_MASK, 0x3)
+#define XELPDP_PORT_M2P_DATA_MASK  REG_GENMASK(23, 16)
+#define XELPDP_PORT_M2P_DATA(val)  
REG_FIELD_PREP(XELPDP_PORT_M2P_DATA_MASK, val)
+#define XELPDP_PORT_M2P_TRANSACTION_RESET  REG_BIT(15)
+#define XELPDP_PORT_M2P_ADDRESS_MASK   REG_GENMASK(11, 0)
+#define XELPDP_PORT_M2P_ADDRESS(val)   
REG_FIELD_PREP(XELPDP_PORT_M2P_ADDRESS_MASK, val)
+
+#define XELPDP_PORT_P2M_MSGBUS_STATUS(port, lane)  
_MMIO(_XELPDP_PORT_M2P_MSGBUS_CTL(port, lane) + 8)
+#define XELPDP_PORT_P2M_RESPONSE_READY REG_BIT(31)
+#define XELPDP_PORT_P2M_COMMAND_TYPE_MASK  REG_GENMASK(30, 27)
+#define XELPDP_PORT_P2M_COMMAND_READ_ACK   0x4
+#define XELPDP_PORT_P2M_COMMAND_WRITE_ACK  0x5
+#define XELPDP_PORT_P2M_DATA_MASK  REG_GENMASK(23, 16)
+#define XELPDP_PORT_P2M_DATA(val)  
REG_FIELD_PREP(XELPDP_PORT_P2M_DATA_MASK, val)
+#define XELPDP_PORT_P2M_ERROR_SET  REG_BIT(15)
+#define XELPDP_MSGBUS_TIMEOUT_SLOW 1
+#define XELPDP_MSGBUS_TIMEOUT_FAST_US  2
+
+#define XELPDP_PCLK_PLL_ENABLE_TIMEOUT_US  3200
+#define XELPDP_PCLK_PLL_DISABLE_TIMEOUT_US 20
+#define XELPDP_PORT_BUF_SOC_READY_TIMEOUT_US   100
+#define XELPDP_PORT_RESET_START_TIMEOUT_US 5
+#define XELPDP_PORT_POWERDOWN_UPDATE_TIMEOUT_US100
+#define XELPDP_PORT_RESET_END_TIMEOUT  15
+#define XELPDP_REFCLK_ENABLE_TIMEOUT_US1
+
+#define _XELPDP_PORT_BUF_CTL1_LN0_A0x64004
+#define _XELPDP_PORT_BUF_CTL1_LN0_B0x64104
+#define _XELPDP_PORT_BUF_CTL1_LN0_USBC10x16F200
+#define _XELPDP_PORT_BUF_CTL1_LN0_USBC20x16F400
+#define _XELPDP_PORT_BUF_CTL1_LN0_USBC30x16F600
+#define _XELPDP_PORT_BUF_CTL1_LN0_USBC4   

[Intel-gfx] [PATCH v5 04/22] drm/i915/mtl: Add Support for C10 PHY message bus and pll programming

2023-03-16 Thread Mika Kahola
From: Radhakrishna Sripada 

XELPDP has C10 and C20 phys from Synopsys to drive displays. Each phy
has a dedicated PIPE 5.2 Message bus for configuration. This message
bus is used to configure the phy internal registers.

XELPDP has C10 phys to drive output to the EDP and the native output
from the display engine. Add structures, programming hardware state
readout logic. Port clock calculations are similar to DG2. Use the DG2
formulae to calculate the port clock but use the relevant pll signals.
Note: PHY lane 0 is always used for PLL programming.

Add sequences for C10 phy enable/disable phy lane reset,
powerdown change sequence and phy lane programming.

Bspec: 64539, 64568, 64599, 65100, 65101, 65450, 65451, 67610, 67636

v2: Squash patches related to C10 phy message bus and pll
programming support (Jani)
Move register definitions to a new file i.e. intel_cx0_reg_defs.h (Jani)
Move macro definitions (Jani)
DP rates as separate patch (Jani)
Spin out xelpdp register definitions into a separate file (Jani)
Replace macro to select registers based on phy lane with
function calls (Jani)
Fix styling issues (Jani)
Call XELPDP_PORT_P2M_MSGBUS_STATUS() with port instead of phy (Lucas)
v3: Move clear request flag into try-loop
v4: On PHY idle change drm_err_once() as drm_dbg_kms() (Jani)
use __intel_de_wait_for_register() instead of __intel_wait_for_register
and uncomment intel_uncore.h (Jani)
Add DP-alt support for PHY lane programming (Khaled)

Cc: Imre Deak 
Cc: Uma Shankar 
Signed-off-by: Radhakrishna Sripada 
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/Makefile |1 +
 drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 1120 +
 drivers/gpu/drm/i915/display/intel_cx0_phy.h  |   43 +
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h |   34 +
 drivers/gpu/drm/i915/display/intel_ddi.c  |   22 +-
 .../drm/i915/display/intel_display_power.c|3 +-
 .../i915/display/intel_display_power_well.c   |2 +-
 .../drm/i915/display/intel_display_types.h|6 +
 drivers/gpu/drm/i915/display/intel_dpll.c |   22 +-
 drivers/gpu/drm/i915/display/intel_dpll_mgr.c |2 +-
 .../drm/i915/display/intel_modeset_verify.c   |2 +
 drivers/gpu/drm/i915/i915_reg.h   |5 +
 drivers/gpu/drm/i915/i915_reg_defs.h  |   57 +
 13 files changed, 1314 insertions(+), 5 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_cx0_phy.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_cx0_phy.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 8e46f57e4569..27d81ba37187 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -295,6 +295,7 @@ i915-y += \
display/icl_dsi.o \
display/intel_backlight.o \
display/intel_crt.o \
+   display/intel_cx0_phy.o \
display/intel_ddi.o \
display/intel_ddi_buf_trans.o \
display/intel_display_trace.o \
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
new file mode 100644
index ..dce55f0ed5e1
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -0,0 +1,1120 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#include "i915_reg.h"
+#include "intel_cx0_phy.h"
+#include "intel_cx0_phy_regs.h"
+#include "intel_de.h"
+#include "intel_display_types.h"
+#include "intel_dp.h"
+#include "intel_panel.h"
+#include "intel_tc.h"
+
+bool intel_is_c10phy(struct drm_i915_private *dev_priv, enum phy phy)
+{
+   if (IS_METEORLAKE(dev_priv) && (phy < PHY_C))
+   return true;
+
+   return false;
+}
+
+static void intel_cx0_bus_reset(struct drm_i915_private *i915, enum port port, 
int lane)
+{
+   enum phy phy = intel_port_to_phy(i915, port);
+
+   /* Bring the phy to idle. */
+   intel_de_write(i915, XELPDP_PORT_M2P_MSGBUS_CTL(port, lane-1),
+  XELPDP_PORT_M2P_TRANSACTION_RESET);
+
+   /* Wait for Idle Clear. */
+   if (intel_de_wait_for_clear(i915, XELPDP_PORT_M2P_MSGBUS_CTL(port, 
lane-1),
+   XELPDP_PORT_M2P_TRANSACTION_RESET,
+   XELPDP_MSGBUS_TIMEOUT_SLOW)) {
+   drm_dbg_kms(>drm, "Failed to bring PHY %c to idle.\n", 
phy_name(phy));
+   return;
+   }
+
+   intel_de_write(i915, XELPDP_PORT_P2M_MSGBUS_STATUS(port, lane-1), ~0);
+}
+
+static int intel_cx0_wait_for_ack(struct drm_i915_private *i915, enum port 
port, int lane, u32 *val)
+{
+   enum phy phy = intel_port_to_phy(i915, port);
+
+   if (__intel_de_wait_for_register(i915,
+XELPDP_PORT_P2M_MSGBUS_STATUS(port, 
lane-1),
+XELPDP_PORT_P2M_RESPONSE_READY,
+XELPDP_PORT_P2M_RESPONSE_READY,
+

[Intel-gfx] [PATCH v5 02/22] drm/i915/mtl: Add DP rates

2023-03-16 Thread Mika Kahola
Add DP rates for Meteorlake.

Signed-off-by: Radhakrishna Sripada 
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index da1c00ee92fb..4927aeb64f23 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -420,6 +420,11 @@ static int ehl_max_source_rate(struct intel_dp *intel_dp)
return 81;
 }
 
+static int mtl_max_source_rate(struct intel_dp *intel_dp)
+{
+   return intel_dp_is_edp(intel_dp) ? 675000 : 81;
+}
+
 static int vbt_max_link_rate(struct intel_dp *intel_dp)
 {
struct intel_encoder *encoder = _to_dig_port(intel_dp)->base;
@@ -444,6 +449,10 @@ static void
 intel_dp_set_source_rates(struct intel_dp *intel_dp)
 {
/* The values must be in increasing order */
+   static const int mtl_rates[] = {
+   162000, 216000, 243000, 27, 324000, 432000, 54, 675000,
+   81,
+   };
static const int icl_rates[] = {
162000, 216000, 27, 324000, 432000, 54, 648000, 81,
100, 135,
@@ -469,7 +478,11 @@ intel_dp_set_source_rates(struct intel_dp *intel_dp)
drm_WARN_ON(_priv->drm,
intel_dp->source_rates || intel_dp->num_source_rates);
 
-   if (DISPLAY_VER(dev_priv) >= 11) {
+   if (DISPLAY_VER(dev_priv) >= 14) {
+   source_rates = mtl_rates;
+   size = ARRAY_SIZE(mtl_rates);
+   max_rate = mtl_max_source_rate(intel_dp);
+   } else if (DISPLAY_VER(dev_priv) >= 11) {
source_rates = icl_rates;
size = ARRAY_SIZE(icl_rates);
if (IS_DG2(dev_priv))
-- 
2.34.1



[Intel-gfx] [PATCH v5 01/22] drm/i915/mtl: Initial DDI port setup

2023-03-16 Thread Mika Kahola
From: Clint Taylor 

Initialize c10 combo phy ports. TODO Type-C ports.

Cc: Radhakrishna Sripada 

Signed-off-by: Clint Taylor 
---
 drivers/gpu/drm/i915/display/intel_display.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 410c84fd905c..1ac05dc68db5 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -7832,7 +7832,11 @@ static void intel_setup_outputs(struct drm_i915_private 
*dev_priv)
if (!HAS_DISPLAY(dev_priv))
return;
 
-   if (IS_DG2(dev_priv)) {
+   if (IS_METEORLAKE(dev_priv)) {
+   /* TODO: initialize TC ports as well */
+   intel_ddi_init(dev_priv, PORT_A);
+   intel_ddi_init(dev_priv, PORT_B);
+   } else if (IS_DG2(dev_priv)) {
intel_ddi_init(dev_priv, PORT_A);
intel_ddi_init(dev_priv, PORT_B);
intel_ddi_init(dev_priv, PORT_C);
-- 
2.34.1



[Intel-gfx] [PATCH v5 00/22] drm/i915/mtl: Add C10 and C20 phy support

2023-03-16 Thread Mika Kahola
PHY programming support for PICA C10 and C20 Type-C chips.

v2: Move intel_cx0_reg_defs.h to intel_cx0_phy_regs.h (Jani)
Move pmdemand as part of intel_display structure
PLL table updates
v3: Renaming C20 read/write functions (Gustavo)
Code readibility fixes (Gustavo)
HDMI PLL table updates
PICA hotplug handling updates
v4: Initialize parameters for C20 port clock calculation
v5: Rebase

Anusha Srivatsa (1):
  drm/i915/mtl: Pin assignment for TypeC

Clint Taylor (1):
  drm/i915/mtl: Initial DDI port setup

Gustavo Sousa (1):
  drm/i915/mtl: Define mask for DDI AUX interrupts

Imre Deak (1):
  drm/i915/mtl: TypeC HPD live status query

Mika Kahola (15):
  drm/i915/mtl: Add DP rates
  drm/i915/mtl: Create separate reg file for PICA registers
  drm/i915/mtl: Add support for PM DEMAND
  drm/i915/mtl: C20 PLL programming
  drm/i915/mtl: C20 HW readout
  drm/i915/mtl: Dump C20 pll hw state
  drm/i915/mtl: C20 port clock calculation
  drm/i915/mtl: C20 HDMI state calculations
  drm/i915/mtl: Add voltage swing sequence for C20
  drm/i915/mtl: For DP2.0 10G and 20G rates use MPLLA
  drm/i915/mtl: Enabling/disabling sequence Thunderbolt pll
  drm/i915/mtl: Readout Thunderbolt HW state
  drm/i915/mtl: Enable TC ports
  drm/i915/mtl: MTL PICA hotplug detection
  drm/i915/mtl: Power up TCSS

Radhakrishna Sripada (3):
  drm/i915/mtl: Add Support for C10 PHY message bus and pll programming
  drm/i915/mtl: Add C10 phy programming for HDMI
  drm/i915/mtl: Add vswing programming for C10 phys

 drivers/gpu/drm/i915/Makefile |1 +
 drivers/gpu/drm/i915/display/intel_bw.c   |4 +-
 drivers/gpu/drm/i915/display/intel_bw.h   |2 +
 drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 2802 +
 drivers/gpu/drm/i915/display/intel_cx0_phy.h  |   57 +
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h |  225 ++
 drivers/gpu/drm/i915/display/intel_ddi.c  |   38 +-
 .../drm/i915/display/intel_ddi_buf_trans.c|   85 +-
 .../drm/i915/display/intel_ddi_buf_trans.h|6 +
 drivers/gpu/drm/i915/display/intel_display.c  |   25 +-
 .../drm/i915/display/intel_display_power.c|9 +-
 .../i915/display/intel_display_power_map.c|1 +
 .../i915/display/intel_display_power_well.c   |2 +-
 .../drm/i915/display/intel_display_types.h|   23 +
 drivers/gpu/drm/i915/display/intel_dp.c   |   23 +-
 drivers/gpu/drm/i915/display/intel_dpll.c |   22 +-
 drivers/gpu/drm/i915/display/intel_dpll_mgr.c |2 +-
 drivers/gpu/drm/i915/display/intel_hdmi.c |7 +-
 drivers/gpu/drm/i915/display/intel_hdmi.h |1 +
 .../drm/i915/display/intel_modeset_verify.c   |2 +
 drivers/gpu/drm/i915/display/intel_tc.c   |  177 +-
 drivers/gpu/drm/i915/i915_drv.h   |6 +
 drivers/gpu/drm/i915/i915_irq.c   |  276 +-
 drivers/gpu/drm/i915/i915_reg.h   |   69 +-
 drivers/gpu/drm/i915/i915_reg_defs.h  |   57 +
 drivers/gpu/drm/i915/intel_pm.c   |  289 ++
 drivers/gpu/drm/i915/intel_pm.h   |   36 +
 27 files changed, 4218 insertions(+), 29 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_cx0_phy.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_cx0_phy.h
 create mode 100644 drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h

-- 
2.34.1



[Intel-gfx] ✓ Fi.CI.IGT: success for drm/i915/hdcp: Remove drm_modeset_lock in intel_conn_to_vcpi

2023-03-16 Thread Patchwork
== Series Details ==

Series: drm/i915/hdcp: Remove drm_modeset_lock in intel_conn_to_vcpi
URL   : https://patchwork.freedesktop.org/series/115240/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_12867_full -> Patchwork_115240v1_full


Summary
---

  **SUCCESS**

  No regressions found.

  

Participating hosts (8 -> 7)
--

  Missing(1): shard-rkl0 

Possible new issues
---

  Here are the unknown changes that may have been introduced in 
Patchwork_115240v1_full:

### IGT changes ###

 Suppressed 

  The following results come from untrusted machines, tests, or statuses.
  They do not affect the overall result.

  * igt@kms_cursor_crc@cursor-suspend@pipe-c-hdmi-a-1:
- {shard-tglu}:   [PASS][1] -> [DMESG-WARN][2]
   [1]: 
https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12867/shard-tglu-5/igt@kms_cursor_crc@cursor-susp...@pipe-c-hdmi-a-1.html
   [2]: 
https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_115240v1/shard-tglu-5/igt@kms_cursor_crc@cursor-susp...@pipe-c-hdmi-a-1.html

  
Known issues


  Here are the changes found in Patchwork_115240v1_full that come from known 
issues:

### IGT changes ###

 Issues hit 

  * igt@gem_exec_fair@basic-none-rrul@rcs0:
- shard-glk:  [PASS][3] -> [FAIL][4] ([i915#2842]) +1 similar issue
   [3]: 
https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12867/shard-glk8/igt@gem_exec_fair@basic-none-r...@rcs0.html
   [4]: 
https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_115240v1/shard-glk7/igt@gem_exec_fair@basic-none-r...@rcs0.html

  * igt@gem_lmem_swapping@heavy-multi:
- shard-glk:  NOTRUN -> [SKIP][5] ([fdo#109271] / [i915#4613])
   [5]: 
https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_115240v1/shard-glk1/igt@gem_lmem_swapp...@heavy-multi.html

  * igt@gen9_exec_parse@allowed-single:
- shard-glk:  [PASS][6] -> [ABORT][7] ([i915#5566])
   [6]: 
https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12867/shard-glk2/igt@gen9_exec_pa...@allowed-single.html
   [7]: 
https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_115240v1/shard-glk5/igt@gen9_exec_pa...@allowed-single.html

  * igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions:
- shard-glk:  [PASS][8] -> [FAIL][9] ([i915#2346])
   [8]: 
https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12867/shard-glk1/igt@kms_cursor_leg...@flip-vs-cursor-atomic-transitions.html
   [9]: 
https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_115240v1/shard-glk7/igt@kms_cursor_leg...@flip-vs-cursor-atomic-transitions.html
- shard-apl:  [PASS][10] -> [FAIL][11] ([i915#2346])
   [10]: 
https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12867/shard-apl7/igt@kms_cursor_leg...@flip-vs-cursor-atomic-transitions.html
   [11]: 
https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_115240v1/shard-apl6/igt@kms_cursor_leg...@flip-vs-cursor-atomic-transitions.html

  * igt@kms_flip@flip-vs-expired-vblank@b-dp1:
- shard-apl:  [PASS][12] -> [FAIL][13] ([i915#79])
   [12]: 
https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12867/shard-apl7/igt@kms_flip@flip-vs-expired-vbl...@b-dp1.html
   [13]: 
https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_115240v1/shard-apl4/igt@kms_flip@flip-vs-expired-vbl...@b-dp1.html

  * igt@kms_frontbuffer_tracking@psr-1p-primscrn-pri-indfb-draw-mmap-gtt:
- shard-glk:  NOTRUN -> [SKIP][14] ([fdo#109271]) +36 similar issues
   [14]: 
https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_115240v1/shard-glk1/igt@kms_frontbuffer_track...@psr-1p-primscrn-pri-indfb-draw-mmap-gtt.html

  * igt@kms_psr2_sf@cursor-plane-update-sf:
- shard-glk:  NOTRUN -> [SKIP][15] ([fdo#109271] / [i915#658])
   [15]: 
https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_115240v1/shard-glk1/igt@kms_psr2...@cursor-plane-update-sf.html

  
 Possible fixes 

  * igt@fbdev@info:
- {shard-rkl}:[SKIP][16] ([i915#2582]) -> [PASS][17]
   [16]: 
https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12867/shard-rkl-4/igt@fb...@info.html
   [17]: 
https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_115240v1/shard-rkl-6/igt@fb...@info.html

  * igt@feature_discovery@psr2:
- {shard-rkl}:[SKIP][18] ([i915#658]) -> [PASS][19]
   [18]: 
https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12867/shard-rkl-2/igt@feature_discov...@psr2.html
   [19]: 
https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_115240v1/shard-rkl-6/igt@feature_discov...@psr2.html

  * igt@gem_ctx_exec@basic-nohangcheck:
- {shard-rkl}:[FAIL][20] ([i915#6268]) -> [PASS][21]
   [20]: 
https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12867/shard-rkl-2/igt@gem_ctx_e...@basic-nohangcheck.html
   [21]: 
https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_115240v1/shard-rkl-5/igt@gem_ctx_e...@basic-nohangcheck.html

  * igt@gem_ctx_persistence@hang:
- {shard-rkl}:[SKIP][22] ([i915#6252]) -> [PASS][23]
   [22]: 

[Intel-gfx] [PATCH i-g-t 2/2] intel_gpu_top: Use full console width for global metrics

2023-03-16 Thread Tvrtko Ursulin
From: Tvrtko Ursulin 

It appears we had an off by one of a kind where we were not using the full
width of the terminal window for the global metrics section.

Signed-off-by: Tvrtko Ursulin 
---
 tools/intel_gpu_top.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
index 39be916297e4..36da016c3df0 100644
--- a/tools/intel_gpu_top.c
+++ b/tools/intel_gpu_top.c
@@ -1960,8 +1960,7 @@ print_engines_header(struct engines *engines, double t,
a = "  ENGINE BUSY  ";
 
printf("\033[7m%s%*s%s\033[0m\n",
-  a, (int)(con_w - 1 - strlen(a) - strlen(b)),
-  " ", b);
+  a, (int)(con_w - strlen(a) - strlen(b)), " ", b);
 
lines++;
}
@@ -2000,7 +1999,6 @@ print_engine(struct engines *engines, unsigned int i, 
double t,
print_groups(groups);
 
if (output_mode == INTERACTIVE) {
-   unsigned int max_w = con_w - 1;
unsigned int len;
char buf[128];
double val;
@@ -2012,7 +2010,7 @@ print_engine(struct engines *engines, unsigned int i, 
double t,
  engine->display_name, engine_items[0].buf);
 
val = pmu_calc(>busy.val, 1e9, t, 100);
-   print_percentage_bar(val, max_w > len ? max_w - len : 0, false);
+   print_percentage_bar(val, con_w > len ? con_w - len : 0, false);
 
printf("%s\n", buf);
 
-- 
2.37.2



[Intel-gfx] [PATCH i-g-t 1/2] intel_gpu_top: Display large pids nicely in interactive mode

2023-03-16 Thread Tvrtko Ursulin
From: Tvrtko Ursulin 

So far the width of the PID column was hardcoded to six characters which
is not enough on systems with high uptime, where PID numbers can grow
large, and results in broken line formatting.

Fix it by tracking the largest width for both the pid and name fields and
use them dynamically.

Signed-off-by: Tvrtko Ursulin 
---
 tools/intel_gpu_top.c | 66 +--
 1 file changed, 58 insertions(+), 8 deletions(-)

diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
index a4302aa389b4..39be916297e4 100644
--- a/tools/intel_gpu_top.c
+++ b/tools/intel_gpu_top.c
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2007-2021 Intel Corporation
+ * Copyright © 2007-2023 Intel Corporation
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -693,6 +693,7 @@ struct client {
enum client_status status;
unsigned int id;
unsigned int pid;
+   char pid_str[10];
char name[24];
char print_name[24];
unsigned int samples;
@@ -709,6 +710,9 @@ struct clients {
unsigned int num_classes;
struct engine_class *class;
 
+   int max_pid_len;
+   int max_name_len;
+
char pci_slot[64];
 
struct client *client;
@@ -758,9 +762,14 @@ update_client(struct client *c, unsigned int pid, char 
*name,
  const struct drm_client_fdinfo *info)
 {
unsigned int i;
+   int len;
 
-   if (c->pid != pid)
+   if (c->pid != pid) {
c->pid = pid;
+   len = snprintf(c->pid_str, sizeof(c->pid_str) - 1, "%u", pid);
+   if (len > c->clients->max_pid_len)
+   c->clients->max_pid_len = len;
+   }
 
if (strcmp(c->name, name)) {
char *p;
@@ -774,6 +783,10 @@ update_client(struct client *c, unsigned int pid, char 
*name,
*p = '*';
p++;
}
+
+   len = strlen(c->print_name);
+   if (len > c->clients->max_name_len)
+   c->clients->max_name_len = len;
}
 
c->last_runtime = 0;
@@ -990,6 +1003,7 @@ static struct clients *display_clients(struct clients 
*clients)
ac->id = -c->pid;
ac->pid = c->pid;
strcpy(ac->name, c->name);
+   strcpy(ac->pid_str, c->pid_str);
strcpy(ac->print_name, c->print_name);
ac->val = calloc(clients->num_classes,
 sizeof(ac->val[0]));
@@ -1013,6 +1027,9 @@ static struct clients *display_clients(struct clients 
*clients)
aggregated->num_clients = num;
aggregated->active_clients = num;
 
+   aggregated->max_pid_len = clients->max_pid_len;
+   aggregated->max_name_len = clients->max_name_len;
+
clients = aggregated;
 
 out:
@@ -1104,9 +1121,34 @@ static size_t readat2buf(int at, const char *name, char 
*buf, const size_t sz)
}
 }
 
+static void clients_update_max_lengths(struct clients *clients)
+{
+   struct client *c;
+   int tmp;
+
+   clients->max_name_len = 0;
+   clients->max_pid_len = 0;
+
+   for_each_client(clients, c, tmp) {
+   int len;
+
+   if (c->status != ALIVE)
+   continue; /* Array not yet sorted by the caller. */
+
+   len = strlen(c->print_name);
+   if (len > clients->max_name_len)
+   clients->max_name_len = len;
+
+   len = strlen(c->pid_str);
+   if (len > clients->max_pid_len)
+   clients->max_pid_len = len;
+   }
+}
+
 static struct clients *scan_clients(struct clients *clients, bool display)
 {
struct dirent *proc_dent;
+   bool freed = false;
struct client *c;
DIR *proc_dir;
int tmp;
@@ -1208,12 +1250,17 @@ next:
closedir(proc_dir);
 
for_each_client(clients, c, tmp) {
-   if (c->status == PROBE)
+   if (c->status == PROBE) {
free_client(c);
-   else if (c->status == FREE)
+   freed = true;
+   } else if (c->status == FREE) {
break;
+   }
}
 
+   if (freed)
+   clients_update_max_lengths(clients);
+
return display ? display_clients(clients) : clients;
 }
 
@@ -2172,15 +2219,16 @@ print_clients_header(struct clients *clients, int lines,
 int con_w, int con_h, int *class_w)
 {
if (output_mode == INTERACTIVE) {
-   const char *pidname = "   PID  NAME ";
unsigned int num_active = 0;
-   int len = strlen(pidname);
+   int len;
 
if (lines++ >= con_h)
 

Re: [Intel-gfx] [PATCH] drm/i915/hdcp: Remove drm_modeset_lock in intel_conn_to_vcpi

2023-03-16 Thread Ville Syrjälä
On Thu, Mar 16, 2023 at 01:52:32PM +0530, Suraj Kandpal wrote:
> Remove drm_modeset_lock in intel_conn_to_vcpi as we don't need it
> anymore since all the required locks are taken in atomic check and
> prepare phases.
> 
> Signed-off-by: Suraj Kandpal 
> ---
>  drivers/gpu/drm/i915/display/intel_hdcp.c | 2 --
>  1 file changed, 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c 
> b/drivers/gpu/drm/i915/display/intel_hdcp.c
> index 2984d2810e42..f957b4bd9c26 100644
> --- a/drivers/gpu/drm/i915/display/intel_hdcp.c
> +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c
> @@ -41,7 +41,6 @@ static int intel_conn_to_vcpi(struct intel_connector 
> *connector)
>   return 0;
>   mgr = connector->port->mgr;
>  
> - drm_modeset_lock(>base.lock, NULL);
>   mst_state = to_drm_dp_mst_topology_state(mgr->base.state);
>   payload = drm_atomic_get_mst_payload_state(mst_state, connector->port);
>   if (drm_WARN_ON(mgr->dev, !payload))
> @@ -53,7 +52,6 @@ static int intel_conn_to_vcpi(struct intel_connector 
> *connector)
>   goto out;
>   }
>  out:
> - drm_modeset_unlock(>base.lock);
>   return vcpi;
>  }

That whole function looks like it something that should be
part of the drm_dp_mst_helper.c.

Also, it's directly accessing mgr->base.state which is just
wrong.

And it looks like it can get called from outside the normal
atomic commit flows (like so many other things in the hdcp
code, sigh), so what you're doing here is also wrong in
that case.

So the whole thing looks just very broken to me. Not to
mention the HDCP vs. MST<->SST switch is also still
fundementally broken. I'm really tempted to just send
a patch to nuke the entire HDCP MST code.

-- 
Ville Syrjälä
Intel


Re: [Intel-gfx] [PATCH v2 20/27] KVM: x86/mmu: Use page-track notifiers iff there are external users

2023-03-16 Thread Yan Zhao
On Wed, Mar 15, 2023 at 09:21:34AM -0700, Sean Christopherson wrote:
> On Wed, Mar 15, 2023, Yan Zhao wrote:
> > Nit: there is a typo in the commit header: "iff" -> "if"
> > 
> > > -void kvm_page_track_write(struct kvm_vcpu *vcpu, gpa_t gpa, const u8 
> > > *new,
> > > -   int bytes)
> > > +void __kvm_page_track_write(struct kvm *kvm, gpa_t gpa, const u8 *new, 
> > > int bytes)
> > Line length is 81 characters. A little longer than 80 :)
> > 
> > > +static inline bool kvm_page_track_has_external_user(struct kvm *kvm) { 
> > > return false; }
> > This line is also too long.
> 
> The 80 character limit is a "soft" limit these days, e.g. checkpatch only 
> complains
> if a line is 100+.  In KVM x86, the preferred style is to treat the 80 char 
> limit
> as "firm", for lack of a better word.  E.g. let a line run over if it's just a
> char or two and there's no other wrapping in the declaration, but don't 
> create long
> lines just because checkpatch no longer yells.
> 
Got it. It's helpful to me!

> There's obviously a fair bit of subjectivity, but the guideline has worked 
> well
> so far (hopefully I didn't just jinx us).




Re: [Intel-gfx] [PATCH v2 14/27] KVM: x86: Reject memslot MOVE operations if KVMGT is attached

2023-03-16 Thread Yan Zhao
On Wed, Mar 15, 2023 at 08:43:54AM -0700, Sean Christopherson wrote:
> > So, in theory, the new GFNs are not write tracked though the old ones are.
> > 
> > Is that acceptable for the internal page-track user?
> 
> It works because KVM zaps all SPTEs when a memslot is moved, i.e. the fact 
> that
Oh, yes!
And KVM will not shadow SPTEs for a invalid memslot, so there's no
problem.
Thanks~

> KVM loses the write-tracking counts is benign.  I suspect no VMM actually does
> does KVM_MR_MOVE in conjunction with shadow paging, but the ongoing 
> maintenance
> cost of supporting KVM_MR_MOVE is quite low at this point, so trying to rip it
> out isn't worth the pain of having to deal with potential ABI breakage.
> 
> Though in hindsight I wish I had tried disallowed moving memslots instead of
> fixing the various bugs a few years back. :-(


Re: [Intel-gfx] [PATCH 3/9] drm/i915: Define more pipe timestamp registers

2023-03-16 Thread Ville Syrjälä
On Thu, Mar 16, 2023 at 08:43:12AM +, Hogander, Jouni wrote:
> On Tue, 2023-03-14 at 15:02 +0200, Ville Syrjala wrote:
> > From: Ville Syrjälä 
> > 
> > Add definitions for various pipe timestamp registers:
> > - frame timestamp (last start of vblank) (g4x+), already had this
> > defined
> > - flip timestamp (when SURF was last written) (g4x+)
> > - flipdone timestamp (when last flipdone was signalled) (tgl+)
> > 
> > Note that on pre-tgl the flip related timestamps are only updated
> > for primary plane flips, but on tgl+ we can select which plane
> > updates them (via PIPE_MISC2). Let's define those related bits
> > as well.
> > 
> > Curiously VLV/CHV do not have the frame/flip timestamp registers,
> > despite all the other related registers being inherited from g4x.
> > This means we can get rid of the pipe_offsets[] usage for these,
> > and thus the implicit dev_priv is gone as well.
> 
> According to bspec these exist in VLV (Bspec: 8264, 8261) ?

It is lying to you.

> 
> > 
> > Signed-off-by: Ville Syrjälä 
> > ---
> >  drivers/gpu/drm/i915/i915_reg.h | 18 +-
> >  1 file changed, 17 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_reg.h
> > b/drivers/gpu/drm/i915/i915_reg.h
> > index a383397ebeca..66b6f451b80a 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -3526,6 +3526,8 @@
> >  #define   PIPE_MISC2_BUBBLE_COUNTER_MASK   REG_GENMASK(31, 24)
> >  #define  
> > PIPE_MISC2_BUBBLE_COUNTER_SCALER_EN  REG_FIELD_PREP(PIPE_MISC2_BUBBLE
> > _COUNTER_MASK, 80)
> >  #define  
> > PIPE_MISC2_BUBBLE_COUNTER_SCALER_DIS REG_FIELD_PREP(PIPE_MISC2_BUBBLE
> > _COUNTER_MASK, 20)
> > +#define  
> > PIPE_MISC2_FLIP_INFO_PLANE_SEL_MASK  REG_GENMASK(2, 0) /*
> > tgl+ */
> > +#define  
> > PIPE_MISC2_FLIP_INFO_PLANE_SEL(plane_id) REG_FIELD_PREP(PIPE_MISC
> > 2_FLIP_INFO_PLANE_SEL_MASK, (plane_id))
> >  #define PIPE_MISC2(pipe)   _MMIO_PIPE(pipe,
> > _PIPE_MISC2_A, _PIPE_MISC2_B)
> >  
> >  /* Skylake+ pipe bottom (background) color */
> > @@ -7545,9 +7547,23 @@ enum skl_power_gate {
> >  #define  GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DENOMINATOR_SHIFT  12
> >  #define  GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DENOMINATOR_MASK   (0xf
> > << 12)
> >  
> > +/* g4x+, except vlv/chv! */
> >  #define _PIPE_FRMTMSTMP_A  0x70048
> > +#define _PIPE_FRMTMSTMP_B  0x71048
> >  #define PIPE_FRMTMSTMP(pipe)   \
> > -   _MMIO_PIPE2(pipe, _PIPE_FRMTMSTMP_A)
> > +   _MMIO_PIPE(pipe, _PIPE_FRMTMSTMP_A, _PIPE_FRMTMSTMP_B)
> > +
> > +/* g4x+, except vlv/chv! */
> > +#define _PIPE_FLIPTMSTMP_A 0x7004C
> > +#define _PIPE_FLIPTMSTMP_B 0x7104C
> > +#define PIPE_FLIPTMSTMP(pipe)  \
> > +   _MMIO_PIPE(pipe, _PIPE_FLIPTMSTMP_A, _PIPE_FLIPTMSTMP_B)
> > +
> > +/* tgl+ */
> 
> This is mentioned in pre tgl documentation as well? (Bspec: 29591)

I think that is only a leftover artifact from before the
gen12+ split. If you set the filter to ICLLP (or earlier)
the register should disappear for you.

> 
> > +#define _PIPE_FLIPDONETMSTMP_A 0x70054
> > +#define _PIPE_FLIPDONETMSTMP_B 0x71054
> > +#define PIPE_FLIPDONETIMSTMP(pipe) \
> > +   _MMIO_PIPE(pipe, _PIPE_FLIPDONETMSTMP_A,
> > _PIPE_FLIPDONETMSTMP_B)
> >  
> >  #define GGC_MMIO(0x108040)
> >  #define   GMS_MASK REG_GENMASK(15, 8)
> 
> BR,
> 
> Jouni Högander

-- 
Ville Syrjälä
Intel


Re: [Intel-gfx] [PATCH v2 19/27] KVM: x86/mmu: Move KVM-only page-track declarations to internal header

2023-03-16 Thread Yan Zhao
On Wed, Mar 15, 2023 at 08:13:37AM -0700, Sean Christopherson wrote:
> > A curious question:
> > are arch/x86/include/asm/kvm_*.h all expected to be external accessible?
> 
> Depends on what you mean by "expected".  Currently, yes, everything in there 
> is
> globally visible.  But the vast majority of structs, defines, functions, etc. 
> aren't
> intended for external non-KVM consumption, things ended up being globally 
> visible
> largely through carelessness and/or a lack of a forcing function.
> 
> E.g. there is absolutely no reason anything outside of KVM should need
> arch/x86/include/asm/kvm-x86-ops.h, but it landed in asm/ because, at the 
> time it
> was added, nothing would be harmed by making kvm-x86-ops.h "public" and we 
> didn't
> scrutinize the patches well enough.
> 
> My primary motivation for this series is to (eventually) get to a state where 
> only
> select symbols/defines/etc. are exposed by KVM to the outside world, and 
> everything
> else is internal only.  The end goal of tightly restricting KVM's global API 
> is to
> allow concurrently loading multiple instances of kvm.ko so that userspace can
> upgrade/rollback KVM without needed to move VMs off the host, i.e. by 
> performing
> intrahost migration between differenate instances of KVM on the same host.  
> To do
> that safely, anything that is visible outside of KVM needs to be compatible 
> across
> different instances of KVM, e.g. if kvm_vcpu is "public" then a KVM 
> upgrade/rollback
> wouldn't be able to touch "struct kvm_vcpu" in any way.  We'll definitely 
> want to be
> able to modify things like the vCPU structures, thus the push to restrict the 
> API.
> 
> But even if we never realize that end goal, IMO drastically reducing KVM's 
> "public"
> API surface is worthy goal in and of itself.
Got it. Thanks for explanation!


Re: [Intel-gfx] [PATCH 6/9] drm/i915: Define vlv/chv sprite plane SURFLIVE registers

2023-03-16 Thread Ville Syrjälä
On Thu, Mar 16, 2023 at 09:12:00AM +, Hogander, Jouni wrote:
> On Tue, 2023-03-14 at 15:02 +0200, Ville Syrjala wrote:
> > From: Ville Syrjälä 
> > 
> > Might as well complete the SURFLIVE register definitions
> > for all platforms/plane types. We are only missing the
> > VLV/CHV sprite planes.
> 
> Can you please point out Bspec you used for these definitions?

For vlv/chv you need magic offline docs.

> 
> > 
> > Signed-off-by: Ville Syrjälä 
> > ---
> >  drivers/gpu/drm/i915/i915_reg.h | 3 +++
> >  1 file changed, 3 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_reg.h
> > b/drivers/gpu/drm/i915/i915_reg.h
> > index a2b4af711e6d..e908959dba4a 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -4394,6 +4394,7 @@
> >  #define   SP_CONST_ALPHA_ENABLEREG_BIT(31)
> >  #define   SP_CONST_ALPHA_MASK  REG_GENMASK(7, 0)
> >  #define  
> > SP_CONST_ALPHA(alpha)REG_FIELD_PREP(SP_CONST_ALPHA_MA
> > SK, (alpha))
> > +#define _SPASURFLIVE   (VLV_DISPLAY_BASE + 0x721ac)
> >  #define _SPACLRC0  (VLV_DISPLAY_BASE + 0x721d0)
> >  #define   SP_CONTRAST_MASK REG_GENMASK(26, 18)
> >  #define  
> > SP_CONTRAST(x)   REG_FIELD_PREP(SP_CONTRAST_MASK, (x)) /*
> > u3.6 */
> > @@ -4417,6 +4418,7 @@
> >  #define _SPBKEYMAXVAL  (VLV_DISPLAY_BASE + 0x722a0)
> >  #define _SPBTILEOFF(VLV_DISPLAY_BASE + 0x722a4)
> >  #define _SPBCONSTALPHA (VLV_DISPLAY_BASE + 0x722a8)
> > +#define _SPBSURFLIVE   (VLV_DISPLAY_BASE + 0x722ac)
> >  #define _SPBCLRC0  (VLV_DISPLAY_BASE + 0x722d0)
> >  #define _SPBCLRC1  (VLV_DISPLAY_BASE + 0x722d4)
> >  #define _SPBGAMC   (VLV_DISPLAY_BASE + 0x722e0)
> > @@ -4437,6 +4439,7 @@
> >  #define SPKEYMAXVAL(pipe, plane_id)_MMIO_VLV_SPR((pipe),
> > (plane_id), _SPAKEYMAXVAL, _SPBKEYMAXVAL)
> >  #define SPTILEOFF(pipe, plane_id)  _MMIO_VLV_SPR((pipe),
> > (plane_id), _SPATILEOFF, _SPBTILEOFF)
> >  #define SPCONSTALPHA(pipe, plane_id)   _MMIO_VLV_SPR((pipe),
> > (plane_id), _SPACONSTALPHA, _SPBCONSTALPHA)
> > +#define SPSURFLIVE(pipe, plane_id) _MMIO_VLV_SPR((pipe),
> > (plane_id), _SPASURFLIVE, _SPBSURFLIVE)
> >  #define SPCLRC0(pipe, plane_id)_MMIO_VLV_SPR((pipe),
> > (plane_id), _SPACLRC0, _SPBCLRC0)
> >  #define SPCLRC1(pipe, plane_id)_MMIO_VLV_SPR((pipe),
> > (plane_id), _SPACLRC1, _SPBCLRC1)
> >  #define SPGAMC(pipe, plane_id, i)  _MMIO(_VLV_SPR((pipe),
> > (plane_id), _SPAGAMC, _SPBGAMC) + (5 - (i)) * 4) /* 6 x u0.10 */
> 
> BR,
> 
> Jouni Högander
> 

-- 
Ville Syrjälä
Intel


Re: [Intel-gfx] [PATCH 4/9] drm/i915: Program VLV/CHV PIPE_MSA_MISC register

2023-03-16 Thread Ville Syrjälä
On Thu, Mar 16, 2023 at 08:55:01AM +, Hogander, Jouni wrote:
> On Tue, 2023-03-14 at 15:02 +0200, Ville Syrjala wrote:
> > From: Ville Syrjälä 
> > 
> > VLV/CHV have an extra register to configure some stereo3d
> > signalling details via DP MSA. Make sure we reset that
> > register to zero (since we don't do any stereo3d stuff).
> 
> Maybe add Bspec here? It took me a while to find this documentation.

Bpec + vlv/chv is lost cause. I never even bother looking there.

> 
> Can you please check also Bspec: 8125 ?

That's the HSW+ MSA register. Different beast.

> 
> > 
> > Signed-off-by: Ville Syrjälä 
> > ---
> >  drivers/gpu/drm/i915/display/intel_display.c | 2 ++
> >  drivers/gpu/drm/i915/i915_reg.h  | 6 ++
> >  2 files changed, 8 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/i915/display/intel_display.c
> > b/drivers/gpu/drm/i915/display/intel_display.c
> > index d95817288966..7b371d2746b5 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display.c
> > +++ b/drivers/gpu/drm/i915/display/intel_display.c
> > @@ -2139,6 +2139,8 @@ static void valleyview_crtc_enable(struct
> > intel_atomic_state *state,
> >  
> > intel_set_pipe_src_size(new_crtc_state);
> >  
> > +   intel_de_write(dev_priv, VLV_PIPE_MSA_MISC(pipe), 0);
> > +
> > if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
> > intel_de_write(dev_priv, CHV_BLEND(pipe),
> > CHV_BLEND_LEGACY);
> > intel_de_write(dev_priv, CHV_CANVAS(pipe), 0);
> > diff --git a/drivers/gpu/drm/i915/i915_reg.h
> > b/drivers/gpu/drm/i915/i915_reg.h
> > index 66b6f451b80a..8f301bf4e2b6 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -7565,6 +7565,12 @@ enum skl_power_gate {
> >  #define PIPE_FLIPDONETIMSTMP(pipe) \
> > _MMIO_PIPE(pipe, _PIPE_FLIPDONETMSTMP_A,
> > _PIPE_FLIPDONETMSTMP_B)
> >  
> > +#define _VLV_PIPE_MSA_MISC_A   0x70048
> > +#define VLV_PIPE_MSA_MISC(pipe)\
> > +   _MMIO_PIPE2(pipe, _VLV_PIPE_MSA_MISC_A)
> > +#define   VLV_MSA_MISC1_HW_ENABLE  REG_BIT(31)
> > +#define  
> > VLV_MSA_MISC1_SW_S3D_MASKREG_GENMASK(2, 0) /* MSA
> > MISC1 3:1 */
> > +
> >  #define GGC_MMIO(0x108040)
> >  #define   GMS_MASK REG_GENMASK(15, 8)
> >  #define   GGMS_MASKREG_GENMASK(7, 6)
> 
> BR,
> 
> Jouni Högander

-- 
Ville Syrjälä
Intel


[Intel-gfx] [PATCH v13 3/6] drm/i915/hdcp: HDCP2.x Refactoring to agnostic hdcp

2023-03-16 Thread Suraj Kandpal
There are more than type of content protection security firmware.
Make the name generic
%s/_mei_/_

--v3
-Changing names to drop cp_fw to make naming more agnostic[Jani]

--v4
-remove header reference in intel_display_core.h [Uma]
-fix commit message and prefix drm [Uma]

Cc: Tomas Winkler 
Cc: Rodrigo Vivi 
Cc: Uma Shankar 
Cc: Ankit Nautiyal 
Signed-off-by: Anshuman Gupta 
Signed-off-by: Suraj Kandpal 
Reviewed-by: Ankit Nautiyal 
Reviewed-by: Uma Shankar 
---
 drivers/gpu/drm/i915/display/intel_hdcp.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c 
b/drivers/gpu/drm/i915/display/intel_hdcp.c
index 1ae0882dc1d4..3b9bdc4a764d 100644
--- a/drivers/gpu/drm/i915/display/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_hdcp.c
@@ -1409,7 +1409,7 @@ static int hdcp2_authenticate_port(struct intel_connector 
*connector)
return ret;
 }
 
-static int hdcp2_close_mei_session(struct intel_connector *connector)
+static int hdcp2_close_session(struct intel_connector *connector)
 {
struct intel_digital_port *dig_port = 
intel_attached_dig_port(connector);
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
@@ -1433,7 +1433,7 @@ static int hdcp2_close_mei_session(struct intel_connector 
*connector)
 
 static int hdcp2_deauthenticate_port(struct intel_connector *connector)
 {
-   return hdcp2_close_mei_session(connector);
+   return hdcp2_close_session(connector);
 }
 
 /* Authentication flow starts from here */
-- 
2.25.1



[Intel-gfx] [PATCH v13 5/6] drm/i915/mtl: Add function to send command to GSC CS

2023-03-16 Thread Suraj Kandpal
Add function that takes care of sending command to gsc cs. We start
of with allocation of memory for our command intel_hdcp_gsc_message that
contains gsc cs memory header as directed in specs followed by the
actual payload hdcp message that we want to send.
Spec states that we need to poll pending bit of response header around
20 times each try being 50ms apart hence adding that to current
gsc_msg_send function
Also we use the same function to take care of both sending and receiving
hence no separate function to get the response.

--v4
-Create common function to fill in gsc_mtl_header [Alan]
-define host session bitmask [Alan]

--v5
-use i915 directly instead of gt->i915 [Alan]
-No need to make fields NULL as we are already
using kzalloc [Alan]

--v8
-change mechanism to reuse the same memory for one hdcp session[Alan]
-fix header ordering
-add comments to explain flags and host session mask [Alan]

--v9
-remove gem obj from hdcp message as we can use
i915_vma_unpin_and_release [Alan]
-move hdcp message allocation and deallocation from hdcp2_enable and
hdcp2_disable to init and teardown of HDCP [Alan]

--v10
-remove unnecessary i915_vma_unpin [Alan]

--v11
-fix comment style [Uma]

Cc: Ankit Nautiyal 
Cc: Daniele Ceraolo Spurio 
Cc: Alan Pervin Teres 
Cc: Uma Shankar 
Cc: Anshuman Gupta 
Signed-off-by: Suraj Kandpal 
Reviewed-by: Alan Previn 
Reviewed-by: Uma Shankar 
---
 drivers/gpu/drm/i915/Makefile |   1 +
 .../gpu/drm/i915/display/intel_display_core.h |   6 +
 drivers/gpu/drm/i915/display/intel_hdcp_gsc.c | 200 ++
 drivers/gpu/drm/i915/display/intel_hdcp_gsc.h |  23 ++
 .../i915/gt/uc/intel_gsc_uc_heci_cmd_submit.c |  15 ++
 .../i915/gt/uc/intel_gsc_uc_heci_cmd_submit.h |  16 ++
 6 files changed, 261 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/display/intel_hdcp_gsc.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_hdcp_gsc.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 8c6b3808c49f..53318809f4a1 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -256,6 +256,7 @@ i915-y += \
display/intel_frontbuffer.o \
display/intel_global_state.o \
display/intel_hdcp.o \
+   display/intel_hdcp_gsc.o \
display/intel_hotplug.o \
display/intel_hti.o \
display/intel_lpe_audio.o \
diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h 
b/drivers/gpu/drm/i915/display/intel_display_core.h
index d7cb649be915..cc5c9382c24e 100644
--- a/drivers/gpu/drm/i915/display/intel_display_core.h
+++ b/drivers/gpu/drm/i915/display/intel_display_core.h
@@ -387,6 +387,12 @@ struct intel_display {
struct i915_hdcp_master *master;
bool comp_added;
 
+   /*
+* HDCP message struct for allocation of memory which can be
+* reused when sending message to gsc cs.
+* this is only populated post Meteorlake
+*/
+   struct intel_hdcp_gsc_message *hdcp_message;
/* Mutex to protect the above hdcp component related values. */
struct mutex comp_mutex;
} hdcp;
diff --git a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c 
b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c
new file mode 100644
index ..4234fabd62ad
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c
@@ -0,0 +1,200 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2023, Intel Corporation.
+ */
+
+#include "display/intel_hdcp_gsc.h"
+#include "gem/i915_gem_region.h"
+#include "gt/uc/intel_gsc_uc_heci_cmd_submit.h"
+#include "i915_drv.h"
+#include "i915_utils.h"
+
+/*This function helps allocate memory for the command that we will send to gsc 
cs */
+static int intel_hdcp_gsc_initialize_message(struct drm_i915_private *i915,
+struct intel_hdcp_gsc_message 
*hdcp_message)
+{
+   struct intel_gt *gt = i915->media_gt;
+   struct drm_i915_gem_object *obj = NULL;
+   struct i915_vma *vma = NULL;
+   void *cmd;
+   int err;
+
+   /* allocate object of one page for HDCP command memory and store it */
+   obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
+
+   if (IS_ERR(obj)) {
+   drm_err(>drm, "Failed to allocate HDCP streaming 
command!\n");
+   return PTR_ERR(obj);
+   }
+
+   cmd = i915_gem_object_pin_map_unlocked(obj, 
i915_coherent_map_type(i915, obj, true));
+   if (IS_ERR(cmd)) {
+   drm_err(>drm, "Failed to map gsc message page!\n");
+   err = PTR_ERR(cmd);
+   goto out_unpin;
+   }
+
+   vma = i915_vma_instance(obj, >ggtt->vm, NULL);
+   if (IS_ERR(vma)) {
+   err = PTR_ERR(vma);
+   goto out_unmap;
+   }
+
+   err = i915_vma_pin(vma, 0, 0, PIN_GLOBAL);
+   if (err)
+   goto out_unmap;
+
+   memset(cmd, 0, 

<    1   2   3   >