linux/drivers/gpu/drm/xe/xe_gt_sriov_pf_control.c

// SPDX-License-Identifier: MIT
/*
 * Copyright © 2023-2024 Intel Corporation
 */

#include <drm/drm_managed.h>

#include "abi/guc_actions_sriov_abi.h"

#include "xe_device.h"
#include "xe_gt.h"
#include "xe_gt_sriov_pf_config.h"
#include "xe_gt_sriov_pf_control.h"
#include "xe_gt_sriov_pf_helpers.h"
#include "xe_gt_sriov_pf_monitor.h"
#include "xe_gt_sriov_pf_service.h"
#include "xe_gt_sriov_printk.h"
#include "xe_guc_ct.h"
#include "xe_sriov.h"

static const char *control_cmd_to_string(u32 cmd)
{}

static int guc_action_vf_control_cmd(struct xe_guc *guc, u32 vfid, u32 cmd)
{}

static int pf_send_vf_control_cmd(struct xe_gt *gt, unsigned int vfid, u32 cmd)
{}

static int pf_send_vf_pause(struct xe_gt *gt, unsigned int vfid)
{}

static int pf_send_vf_resume(struct xe_gt *gt, unsigned int vfid)
{}

static int pf_send_vf_stop(struct xe_gt *gt, unsigned int vfid)
{}

static int pf_send_vf_flr_start(struct xe_gt *gt, unsigned int vfid)
{}

static int pf_send_vf_flr_finish(struct xe_gt *gt, unsigned int vfid)
{}

/**
 * DOC: The VF state machine
 *
 * The simplified VF state machine could be presented as::
 *
 *	               pause--------------------------o
 *	              /                               |
 *	             /                                v
 *	      (READY)<------------------resume-----(PAUSED)
 *	         ^   \                             /    /
 *	         |    \                           /    /
 *	         |     stop---->(STOPPED)<----stop    /
 *	         |                  /                /
 *	         |                 /                /
 *	         o--------<-----flr                /
 *	          \                               /
 *	           o------<--------------------flr
 *
 * Where:
 *
 * * READY - represents a state in which VF is fully operable
 * * PAUSED - represents a state in which VF activity is temporarily suspended
 * * STOPPED - represents a state in which VF activity is definitely halted
 * * pause - represents a request to temporarily suspend VF activity
 * * resume - represents a request to resume VF activity
 * * stop - represents a request to definitely halt VF activity
 * * flr - represents a request to perform VF FLR to restore VF activity
 *
 * However, each state transition requires additional steps that involves
 * communication with GuC that might fail or be interrupted by other requests::
 *
 *	                   .................................WIP....
 *	                   :                                      :
 *	          pause--------------------->PAUSE_WIP----------------------------o
 *	         /         :                /         \           :               |
 *	        /          :    o----<---stop          flr--o     :               |
 *	       /           :    |           \         /     |     :               V
 *	(READY,RESUMED)<--------+------------RESUME_WIP<----+--<-----resume--(PAUSED)
 *	  ^ \  \           :    |                           |     :          /   /
 *	  |  \  \          :    |                           |     :         /   /
 *	  |   \  \         :    |                           |     :        /   /
 *	  |    \  \        :    o----<----------------------+--<-------stop   /
 *	  |     \  \       :    |                           |     :          /
 *	  |      \  \      :    V                           |     :         /
 *	  |       \  stop----->STOP_WIP---------flr--->-----o     :        /
 *	  |        \       :    |                           |     :       /
 *	  |         \      :    |                           V     :      /
 *	  |          flr--------+----->----------------->FLR_WIP<-----flr
 *	  |                :    |                        /  ^     :
 *	  |                :    |                       /   |     :
 *	  o--------<-------:----+-----<----------------o    |     :
 *	                   :    |                           |     :
 *	                   :....|...........................|.....:
 *	                        |                           |
 *	                        V                           |
 *	                     (STOPPED)--------------------flr
 *
 * For details about each internal WIP state machine see:
 *
 * * `The VF PAUSE state machine`_
 * * `The VF RESUME state machine`_
 * * `The VF STOP state machine`_
 * * `The VF FLR state machine`_
 */

#ifdef CONFIG_DRM_XE_DEBUG_SRIOV
static const char *control_bit_to_string(enum xe_gt_sriov_control_bits bit)
{}
#endif

static unsigned long pf_get_default_timeout(enum xe_gt_sriov_control_bits bit)
{}

static struct xe_gt_sriov_control_state *pf_pick_vf_control(struct xe_gt *gt, unsigned int vfid)
{}

static unsigned long *pf_peek_vf_state(struct xe_gt *gt, unsigned int vfid)
{}

static bool pf_check_vf_state(struct xe_gt *gt, unsigned int vfid,
			      enum xe_gt_sriov_control_bits bit)
{}

static void pf_dump_vf_state(struct xe_gt *gt, unsigned int vfid)
{}

static bool pf_expect_vf_state(struct xe_gt *gt, unsigned int vfid,
			       enum xe_gt_sriov_control_bits bit)
{}

static bool pf_expect_vf_not_state(struct xe_gt *gt, unsigned int vfid,
				   enum xe_gt_sriov_control_bits bit)
{}

static bool pf_enter_vf_state(struct xe_gt *gt, unsigned int vfid,
			      enum xe_gt_sriov_control_bits bit)
{}

static bool pf_exit_vf_state(struct xe_gt *gt, unsigned int vfid,
			     enum xe_gt_sriov_control_bits bit)
{}

static void pf_escape_vf_state(struct xe_gt *gt, unsigned int vfid,
			       enum xe_gt_sriov_control_bits bit)
{}

static void pf_enter_vf_mismatch(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_exit_vf_mismatch(struct xe_gt *gt, unsigned int vfid)
{}

#define pf_enter_vf_state_machine_bug(gt, vfid)

static void pf_queue_control_worker(struct xe_gt *gt)
{}

static void pf_queue_vf(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_exit_vf_flr_wip(struct xe_gt *gt, unsigned int vfid);
static void pf_exit_vf_stop_wip(struct xe_gt *gt, unsigned int vfid);
static void pf_exit_vf_pause_wip(struct xe_gt *gt, unsigned int vfid);
static void pf_exit_vf_resume_wip(struct xe_gt *gt, unsigned int vfid);

static bool pf_enter_vf_wip(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_exit_vf_wip(struct xe_gt *gt, unsigned int vfid)
{}

static int pf_wait_vf_wip_done(struct xe_gt *gt, unsigned int vfid, unsigned long timeout)
{}

static void pf_enter_vf_ready(struct xe_gt *gt, unsigned int vfid)
{}

/**
 * DOC: The VF PAUSE state machine
 *
 * The VF PAUSE state machine looks like::
 *
 *	 (READY,RESUMED)<-------------<---------------------o---------o
 *	    |                                                \         \
 *	   pause                                              \         \
 *	    |                                                  \         \
 *	....V...........................PAUSE_WIP........       \         \
 *	:    \                                          :        o         \
 *	:     \   o------<-----busy                     :        |          \
 *	:      \ /              /                       :        |           |
 *	:       PAUSE_SEND_PAUSE ---failed--->----------o--->(PAUSE_FAILED)  |
 *	:        |              \                       :        |           |
 *	:      acked             rejected---->----------o--->(MISMATCH)     /
 *	:        |                                      :                  /
 *	:        v                                      :                 /
 *	:       PAUSE_WAIT_GUC                          :                /
 *	:        |                                      :               /
 *	:       done                                    :              /
 *	:        |                                      :             /
 *	:        v                                      :            /
 *	:       PAUSE_GUC_DONE                          o-----restart
 *	:      /                                        :
 *	:     /                                         :
 *	:....o..............o...............o...........:
 *	     |              |               |
 *	  completed        flr             stop
 *	     |              |               |
 *	     V         .....V.....    ......V.....
 *	 (PAUSED)      : FLR_WIP :    : STOP_WIP :
 *	               :.........:    :..........:
 *
 * For the full state machine view, see `The VF state machine`_.
 */

static void pf_exit_vf_pause_wip(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_enter_vf_paused(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_enter_vf_pause_completed(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_enter_vf_pause_failed(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_enter_vf_pause_rejected(struct xe_gt *gt, unsigned int vfid)
{}

static bool pf_exit_vf_pause_guc_done(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_enter_vf_pause_guc_done(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_enter_pause_wait_guc(struct xe_gt *gt, unsigned int vfid)
{}

static bool pf_exit_pause_wait_guc(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_enter_vf_pause_send_pause(struct xe_gt *gt, unsigned int vfid)
{}

static bool pf_exit_vf_pause_send_pause(struct xe_gt *gt, unsigned int vfid)
{}

static bool pf_enter_vf_pause_wip(struct xe_gt *gt, unsigned int vfid)
{}

/**
 * xe_gt_sriov_pf_control_pause_vf - Pause a VF.
 * @gt: the &xe_gt
 * @vfid: the VF identifier
 *
 * This function is for PF only.
 *
 * Return: 0 on success or a negative error code on failure.
 */
int xe_gt_sriov_pf_control_pause_vf(struct xe_gt *gt, unsigned int vfid)
{}

/**
 * DOC: The VF RESUME state machine
 *
 * The VF RESUME state machine looks like::
 *
 *	 (PAUSED)<-----------------<------------------------o
 *	    |                                                \
 *	   resume                                             \
 *	    |                                                  \
 *	....V............................RESUME_WIP......       \
 *	:    \                                          :        o
 *	:     \   o-------<-----busy                    :        |
 *	:      \ /                /                     :        |
 *	:       RESUME_SEND_RESUME ---failed--->--------o--->(RESUME_FAILED)
 *	:       /                \                      :        |
 *	:    acked                rejected---->---------o--->(MISMATCH)
 *	:     /                                         :
 *	:....o..............o...............o.....o.....:
 *	     |              |               |      \
 *	  completed        flr            stop      restart-->(READY)
 *	     |              |               |
 *	     V         .....V.....    ......V.....
 *	 (RESUMED)     : FLR_WIP :    : STOP_WIP :
 *	               :.........:    :..........:
 *
 * For the full state machine view, see `The VF state machine`_.
 */

static void pf_exit_vf_resume_wip(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_enter_vf_resumed(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_enter_vf_resume_completed(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_enter_vf_resume_failed(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_enter_vf_resume_rejected(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_enter_vf_resume_send_resume(struct xe_gt *gt, unsigned int vfid)
{}

static bool pf_exit_vf_resume_send_resume(struct xe_gt *gt, unsigned int vfid)
{}

static bool pf_enter_vf_resume_wip(struct xe_gt *gt, unsigned int vfid)
{}

/**
 * xe_gt_sriov_pf_control_resume_vf - Resume a VF.
 * @gt: the &xe_gt
 * @vfid: the VF identifier
 *
 * This function is for PF only.
 *
 * Return: 0 on success or a negative error code on failure.
 */
int xe_gt_sriov_pf_control_resume_vf(struct xe_gt *gt, unsigned int vfid)
{}

/**
 * DOC: The VF STOP state machine
 *
 * The VF STOP state machine looks like::
 *
 *	 (READY,PAUSED,RESUMED)<-------<--------------------o
 *	    |                                                \
 *	   stop                                               \
 *	    |                                                  \
 *	....V..............................STOP_WIP......       \
 *	:    \                                          :        o
 *	:     \   o----<----busy                        :        |
 *	:      \ /            /                         :        |
 *	:       STOP_SEND_STOP--------failed--->--------o--->(STOP_FAILED)
 *	:       /             \                         :        |
 *	:    acked             rejected-------->--------o--->(MISMATCH)
 *	:     /                                         :
 *	:....o..............o...............o...........:
 *	     |              |               |
 *	  completed        flr            restart
 *	     |              |               |
 *	     V         .....V.....          V
 *	 (STOPPED)     : FLR_WIP :       (READY)
 *	               :.........:
 *
 * For the full state machine view, see `The VF state machine`_.
 */

static void pf_exit_vf_stop_wip(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_enter_vf_stopped(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_enter_vf_stop_completed(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_enter_vf_stop_failed(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_enter_vf_stop_rejected(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_enter_vf_stop_send_stop(struct xe_gt *gt, unsigned int vfid)
{}

static bool pf_exit_vf_stop_send_stop(struct xe_gt *gt, unsigned int vfid)
{}

static bool pf_enter_vf_stop_wip(struct xe_gt *gt, unsigned int vfid)
{}

/**
 * xe_gt_sriov_pf_control_stop_vf - Stop a VF.
 * @gt: the &xe_gt
 * @vfid: the VF identifier
 *
 * This function is for PF only.
 *
 * Return: 0 on success or a negative error code on failure.
 */
int xe_gt_sriov_pf_control_stop_vf(struct xe_gt *gt, unsigned int vfid)
{}

/**
 * DOC: The VF FLR state machine
 *
 * The VF FLR state machine looks like::
 *
 *	 (READY,PAUSED,STOPPED)<------------<--------------o
 *	    |                                               \
 *	   flr                                               \
 *	    |                                                 \
 *	....V..........................FLR_WIP...........      \
 *	:    \                                          :       \
 *	:     \   o----<----busy                        :        |
 *	:      \ /            /                         :        |
 *	:       FLR_SEND_START---failed----->-----------o--->(FLR_FAILED)<---o
 *	:        |            \                         :        |           |
 *	:      acked           rejected----->-----------o--->(MISMATCH)      |
 *	:        |                                      :        ^           |
 *	:        v                                      :        |           |
 *	:       FLR_WAIT_GUC                            :        |           |
 *	:        |                                      :        |           |
 *	:       done                                    :        |           |
 *	:        |                                      :        |           |
 *	:        v                                      :        |           |
 *	:       FLR_GUC_DONE                            :        |           |
 *	:        |                                      :        |           |
 *	:       FLR_RESET_CONFIG---failed--->-----------o--------+-----------o
 *	:        |                                      :        |           |
 *	:       FLR_RESET_DATA                          :        |           |
 *	:        |                                      :        |           |
 *	:       FLR_RESET_MMIO                          :        |           |
 *	:        |                                      :        |           |
 *	:        | o----<----busy                       :        |           |
 *	:        |/            /                        :        |           |
 *	:       FLR_SEND_FINISH----failed--->-----------o--------+-----------o
 *	:       /             \                         :        |
 *	:     acked            rejected----->-----------o--------o
 *	:     /                                         :
 *	:....o..............................o...........:
 *	     |                              |
 *	  completed                       restart
 *	     |                             /
 *	     V                            /
 *	  (READY)<----------<------------o
 *
 * For the full state machine view, see `The VF state machine`_.
 */

static void pf_enter_vf_flr_send_start(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_enter_vf_flr_wip(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_exit_vf_flr_wip(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_enter_vf_flr_completed(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_enter_vf_flr_failed(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_enter_vf_flr_rejected(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_enter_vf_flr_send_finish(struct xe_gt *gt, unsigned int vfid)
{}

static bool pf_exit_vf_flr_send_finish(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_enter_vf_flr_reset_mmio(struct xe_gt *gt, unsigned int vfid)
{}

static bool pf_exit_vf_flr_reset_mmio(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_enter_vf_flr_reset_data(struct xe_gt *gt, unsigned int vfid)
{}

static bool pf_exit_vf_flr_reset_data(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_enter_vf_flr_reset_config(struct xe_gt *gt, unsigned int vfid)
{}

static bool pf_exit_vf_flr_reset_config(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_enter_vf_flr_wait_guc(struct xe_gt *gt, unsigned int vfid)
{}

static bool pf_exit_vf_flr_wait_guc(struct xe_gt *gt, unsigned int vfid)
{}

static bool pf_exit_vf_flr_send_start(struct xe_gt *gt, unsigned int vfid)
{}

static bool pf_exit_vf_flr_guc_done(struct xe_gt *gt, unsigned int vfid)
{}

static void pf_enter_vf_flr_guc_done(struct xe_gt *gt, unsigned int vfid)
{}

/**
 * xe_gt_sriov_pf_control_trigger_flr - Start a VF FLR sequence.
 * @gt: the &xe_gt
 * @vfid: the VF identifier
 *
 * This function is for PF only.
 *
 * Return: 0 on success or a negative error code on failure.
 */
int xe_gt_sriov_pf_control_trigger_flr(struct xe_gt *gt, unsigned int vfid)
{}

/**
 * DOC: The VF FLR Flow with GuC
 *
 * The VF FLR flow includes several steps::
 *
 *	         PF                        GUC             PCI
 *	========================================================
 *	         |                          |               |
 *	(1)      |                         [ ] <----- FLR --|
 *	         |                         [ ]              :
 *	(2)     [ ] <-------- NOTIFY FLR --[ ]
 *	        [ ]                         |
 *	(3)     [ ]                         |
 *	        [ ]                         |
 *	        [ ]-- START FLR ---------> [ ]
 *	         |                         [ ]
 *	(4)      |                         [ ]
 *	         |                         [ ]
 *	        [ ] <--------- FLR DONE -- [ ]
 *	        [ ]                         |
 *	(5)     [ ]                         |
 *	        [ ]                         |
 *	        [ ]-- FINISH FLR --------> [ ]
 *	         |                          |
 *
 * * Step 1: PCI HW generates interrupt to the GuC about VF FLR
 * * Step 2: GuC FW sends G2H notification to the PF about VF FLR
 * * Step 2a: on some platforms G2H is only received from root GuC
 * * Step 3: PF sends H2G request to the GuC to start VF FLR sequence
 * * Step 3a: on some platforms PF must send H2G to all other GuCs
 * * Step 4: GuC FW performs VF FLR cleanups and notifies the PF when done
 * * Step 5: PF performs VF FLR cleanups and notifies the GuC FW when finished
 */

static bool needs_dispatch_flr(struct xe_device *xe)
{}

static void pf_handle_vf_flr(struct xe_gt *gt, u32 vfid)
{}

static void pf_handle_vf_flr_done(struct xe_gt *gt, u32 vfid)
{}

static void pf_handle_vf_pause_done(struct xe_gt *gt, u32 vfid)
{}

static int pf_handle_vf_event(struct xe_gt *gt, u32 vfid, u32 eventid)
{}

static int pf_handle_pf_event(struct xe_gt *gt, u32 eventid)
{}

/**
 * xe_gt_sriov_pf_control_process_guc2pf - Handle VF state notification from GuC.
 * @gt: the &xe_gt
 * @msg: the G2H message
 * @len: the length of the G2H message
 *
 * This function is for PF only.
 *
 * Return: 0 on success or a negative error code on failure.
 */
int xe_gt_sriov_pf_control_process_guc2pf(struct xe_gt *gt, const u32 *msg, u32 len)
{}

static bool pf_process_vf_state_machine(struct xe_gt *gt, unsigned int vfid)
{}

static unsigned int pf_control_state_index(struct xe_gt *gt,
					   struct xe_gt_sriov_control_state *cs)
{}

static void pf_worker_find_work(struct xe_gt *gt)
{}

static void control_worker_func(struct work_struct *w)
{}

static void pf_stop_worker(struct xe_gt *gt)
{}

static void control_fini_action(struct drm_device *dev, void *data)
{}

/**
 * xe_gt_sriov_pf_control_init() - Initialize PF's control data.
 * @gt: the &xe_gt
 *
 * This function is for PF only.
 *
 * Return: 0 on success or a negative error code on failure.
 */
int xe_gt_sriov_pf_control_init(struct xe_gt *gt)
{}

/**
 * xe_gt_sriov_pf_control_restart() - Restart SR-IOV control data after a GT reset.
 * @gt: the &xe_gt
 *
 * Any per-VF status maintained by the PF or any ongoing VF control activity
 * performed by the PF must be reset or cancelled when the GT is reset.
 *
 * This function is for PF only.
 */
void xe_gt_sriov_pf_control_restart(struct xe_gt *gt)
{}