Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/xe/pf: Add FLR_PREPARE state to VF control flow

Our xe-vfio-pci component relies on the confirmation from the PF
that VF FLR processing has finished, but due to the notification
latency on the HW/FW side, PF might be unaware yet of the already
triggered VF FLR.

Update VF state machine with new FLR_PREPARE state that indicate
imminent VF FLR notification and treat that as a begin of the FLR
sequence. Also introduce function that xe-vfio-pci should call to
guarantee correct synchronization.

v2: move PREPARE into WIP, update commit msg (Michal)

Signed-off-by: Piotr Piórkowski <piotr.piorkowski@intel.com>
Co-developed-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Reviewed-by: Michał Winiarski <michal.winiarski@intel.com>
Link: https://patch.msgid.link/20260309152449.910636-2-piotr.piorkowski@intel.com
Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>

authored by

Piotr Piórkowski and committed by
Michał Winiarski
2de36e3f a3156676

+102 -16
+62 -16
drivers/gpu/drm/xe/xe_gt_sriov_pf_control.c
··· 171 171 case XE_GT_SRIOV_STATE_##_X: return #_X 172 172 CASE2STR(WIP); 173 173 CASE2STR(FLR_WIP); 174 + CASE2STR(FLR_PREPARE); 174 175 CASE2STR(FLR_SEND_START); 175 176 CASE2STR(FLR_WAIT_GUC); 176 177 CASE2STR(FLR_GUC_DONE); ··· 1487 1486 * The VF FLR state machine looks like:: 1488 1487 * 1489 1488 * (READY,PAUSED,STOPPED)<------------<--------------o 1490 - * | \ 1491 - * flr \ 1492 - * | \ 1493 - * ....V..........................FLR_WIP........... \ 1494 - * : \ : \ 1489 + * | | \ 1490 + * flr prepare \ 1491 + * | | \ 1492 + * ....V.............V............FLR_WIP........... \ 1493 + * : | | : \ 1494 + * : | FLR_PREPARE : | 1495 + * : | / : | 1496 + * : \ flr : | 1497 + * : \ / : | 1495 1498 * : \ o----<----busy : | 1496 1499 * : \ / / : | 1497 1500 * : FLR_SEND_START---failed----->-----------o--->(FLR_FAILED)<---o ··· 1544 1539 pf_queue_vf(gt, vfid); 1545 1540 } 1546 1541 1547 - static void pf_enter_vf_flr_wip(struct xe_gt *gt, unsigned int vfid) 1542 + static bool pf_exit_vf_flr_prepare(struct xe_gt *gt, unsigned int vfid) 1548 1543 { 1549 - if (!pf_enter_vf_state(gt, vfid, XE_GT_SRIOV_STATE_FLR_WIP)) { 1550 - xe_gt_sriov_dbg(gt, "VF%u FLR is already in progress\n", vfid); 1551 - return; 1552 - } 1544 + if (!pf_exit_vf_state(gt, vfid, XE_GT_SRIOV_STATE_FLR_PREPARE)) 1545 + return false; 1546 + 1547 + pf_enter_vf_flr_send_start(gt, vfid); 1548 + return true; 1549 + } 1550 + 1551 + static bool pf_enter_vf_flr_wip(struct xe_gt *gt, unsigned int vfid) 1552 + { 1553 + if (!pf_enter_vf_state(gt, vfid, XE_GT_SRIOV_STATE_FLR_WIP)) 1554 + return false; 1553 1555 1554 1556 pf_enter_vf_wip(gt, vfid); 1555 - pf_enter_vf_flr_send_start(gt, vfid); 1557 + return true; 1556 1558 } 1557 1559 1558 1560 static void pf_exit_vf_flr_wip(struct xe_gt *gt, unsigned int vfid) 1559 1561 { 1560 1562 if (pf_exit_vf_state(gt, vfid, XE_GT_SRIOV_STATE_FLR_WIP)) { 1563 + pf_escape_vf_state(gt, vfid, XE_GT_SRIOV_STATE_FLR_PREPARE); 1561 1564 pf_escape_vf_state(gt, vfid, XE_GT_SRIOV_STATE_FLR_SEND_FINISH); 1562 1565 pf_escape_vf_state(gt, vfid, XE_GT_SRIOV_STATE_FLR_RESET_MMIO); 1563 1566 pf_escape_vf_state(gt, vfid, XE_GT_SRIOV_STATE_FLR_RESET_DATA); ··· 1773 1760 } 1774 1761 1775 1762 /** 1763 + * xe_gt_sriov_pf_control_prepare_flr() - Notify PF that VF FLR request was issued. 1764 + * @gt: the &xe_gt 1765 + * @vfid: the VF identifier 1766 + * 1767 + * This is an optional early notification path used to mark pending FLR before 1768 + * the GuC notifies the PF with a FLR event. 1769 + * 1770 + * This function is for PF only. 1771 + * 1772 + * Return: 0 on success or a negative error code on failure. 1773 + */ 1774 + int xe_gt_sriov_pf_control_prepare_flr(struct xe_gt *gt, unsigned int vfid) 1775 + { 1776 + if (!pf_enter_vf_flr_wip(gt, vfid)) 1777 + return -EALREADY; 1778 + 1779 + pf_enter_vf_state(gt, vfid, XE_GT_SRIOV_STATE_FLR_PREPARE); 1780 + return 0; 1781 + } 1782 + 1783 + static int pf_begin_vf_flr(struct xe_gt *gt, unsigned int vfid) 1784 + { 1785 + if (pf_enter_vf_flr_wip(gt, vfid)) { 1786 + pf_enter_vf_flr_send_start(gt, vfid); 1787 + return 0; 1788 + } 1789 + 1790 + if (pf_exit_vf_flr_prepare(gt, vfid)) 1791 + return 0; 1792 + 1793 + xe_gt_sriov_dbg(gt, "VF%u FLR is already in progress\n", vfid); 1794 + return -EALREADY; 1795 + } 1796 + 1797 + /** 1776 1798 * xe_gt_sriov_pf_control_trigger_flr - Start a VF FLR sequence. 1777 1799 * @gt: the &xe_gt 1778 1800 * @vfid: the VF identifier ··· 1818 1770 */ 1819 1771 int xe_gt_sriov_pf_control_trigger_flr(struct xe_gt *gt, unsigned int vfid) 1820 1772 { 1821 - pf_enter_vf_flr_wip(gt, vfid); 1822 - 1823 - return 0; 1773 + return pf_begin_vf_flr(gt, vfid); 1824 1774 } 1825 1775 1826 1776 /** ··· 1925 1879 1926 1880 if (needs_dispatch_flr(xe)) { 1927 1881 for_each_gt(gtit, xe, gtid) 1928 - pf_enter_vf_flr_wip(gtit, vfid); 1882 + pf_begin_vf_flr(gtit, vfid); 1929 1883 } else { 1930 - pf_enter_vf_flr_wip(gt, vfid); 1884 + pf_begin_vf_flr(gt, vfid); 1931 1885 } 1932 1886 } 1933 1887
+1
drivers/gpu/drm/xe/xe_gt_sriov_pf_control.h
··· 27 27 int xe_gt_sriov_pf_control_trigger_restore_vf(struct xe_gt *gt, unsigned int vfid); 28 28 int xe_gt_sriov_pf_control_finish_restore_vf(struct xe_gt *gt, unsigned int vfid); 29 29 int xe_gt_sriov_pf_control_stop_vf(struct xe_gt *gt, unsigned int vfid); 30 + int xe_gt_sriov_pf_control_prepare_flr(struct xe_gt *gt, unsigned int vfid); 30 31 int xe_gt_sriov_pf_control_trigger_flr(struct xe_gt *gt, unsigned int vfid); 31 32 int xe_gt_sriov_pf_control_sync_flr(struct xe_gt *gt, unsigned int vfid, bool sync); 32 33 int xe_gt_sriov_pf_control_wait_flr(struct xe_gt *gt, unsigned int vfid);
+2
drivers/gpu/drm/xe/xe_gt_sriov_pf_control_types.h
··· 15 15 * 16 16 * @XE_GT_SRIOV_STATE_WIP: indicates that some operations are in progress. 17 17 * @XE_GT_SRIOV_STATE_FLR_WIP: indicates that a VF FLR is in progress. 18 + * @XE_GT_SRIOV_STATE_FLR_PREPARE: indicates that the PF received early VF FLR prepare notification. 18 19 * @XE_GT_SRIOV_STATE_FLR_SEND_START: indicates that the PF wants to send a FLR START command. 19 20 * @XE_GT_SRIOV_STATE_FLR_WAIT_GUC: indicates that the PF awaits for a response from the GuC. 20 21 * @XE_GT_SRIOV_STATE_FLR_GUC_DONE: indicates that the PF has received a response from the GuC. ··· 57 56 XE_GT_SRIOV_STATE_WIP = 1, 58 57 59 58 XE_GT_SRIOV_STATE_FLR_WIP, 59 + XE_GT_SRIOV_STATE_FLR_PREPARE, 60 60 XE_GT_SRIOV_STATE_FLR_SEND_START, 61 61 XE_GT_SRIOV_STATE_FLR_WAIT_GUC, 62 62 XE_GT_SRIOV_STATE_FLR_GUC_DONE,
+24
drivers/gpu/drm/xe/xe_sriov_pf_control.c
··· 124 124 } 125 125 126 126 /** 127 + * xe_sriov_pf_control_prepare_flr() - Notify PF that VF FLR prepare has started. 128 + * @xe: the &xe_device 129 + * @vfid: the VF identifier 130 + * 131 + * This function is for PF only. 132 + * 133 + * Return: 0 on success or a negative error code on failure. 134 + */ 135 + int xe_sriov_pf_control_prepare_flr(struct xe_device *xe, unsigned int vfid) 136 + { 137 + struct xe_gt *gt; 138 + unsigned int id; 139 + int result = 0; 140 + int err; 141 + 142 + for_each_gt(gt, xe, id) { 143 + err = xe_gt_sriov_pf_control_prepare_flr(gt, vfid); 144 + result = result ? -EUCLEAN : err; 145 + } 146 + 147 + return result; 148 + } 149 + 150 + /** 127 151 * xe_sriov_pf_control_wait_flr() - Wait for a VF reset (FLR) to complete. 128 152 * @xe: the &xe_device 129 153 * @vfid: the VF identifier
+1
drivers/gpu/drm/xe/xe_sriov_pf_control.h
··· 12 12 int xe_sriov_pf_control_resume_vf(struct xe_device *xe, unsigned int vfid); 13 13 int xe_sriov_pf_control_stop_vf(struct xe_device *xe, unsigned int vfid); 14 14 int xe_sriov_pf_control_reset_vf(struct xe_device *xe, unsigned int vfid); 15 + int xe_sriov_pf_control_prepare_flr(struct xe_device *xe, unsigned int vfid); 15 16 int xe_sriov_pf_control_wait_flr(struct xe_device *xe, unsigned int vfid); 16 17 int xe_sriov_pf_control_sync_flr(struct xe_device *xe, unsigned int vfid); 17 18 int xe_sriov_pf_control_trigger_save_vf(struct xe_device *xe, unsigned int vfid);
+1
drivers/gpu/drm/xe/xe_sriov_vfio.c
··· 42 42 EXPORT_SYMBOL_FOR_MODULES(xe_sriov_vfio_##_func, "xe-vfio-pci") 43 43 44 44 DEFINE_XE_SRIOV_VFIO_FUNCTION(int, wait_flr_done, control_wait_flr); 45 + DEFINE_XE_SRIOV_VFIO_FUNCTION(int, flr_prepare, control_prepare_flr); 45 46 DEFINE_XE_SRIOV_VFIO_FUNCTION(int, suspend_device, control_pause_vf); 46 47 DEFINE_XE_SRIOV_VFIO_FUNCTION(int, resume_device, control_resume_vf); 47 48 DEFINE_XE_SRIOV_VFIO_FUNCTION(int, stop_copy_enter, control_trigger_save_vf);
+11
include/drm/intel/xe_sriov_vfio.h
··· 28 28 bool xe_sriov_vfio_migration_supported(struct xe_device *xe); 29 29 30 30 /** 31 + * xe_sriov_vfio_flr_prepare() - Notify PF that VF FLR prepare has started. 32 + * @xe: the PF &xe_device obtained by calling xe_sriov_vfio_get_pf() 33 + * @vfid: the VF identifier (can't be 0) 34 + * 35 + * This function marks VF FLR as pending before PF receives GuC FLR event. 36 + * 37 + * Return: 0 on success or a negative error code on failure. 38 + */ 39 + int xe_sriov_vfio_flr_prepare(struct xe_device *xe, unsigned int vfid); 40 + 41 + /** 31 42 * xe_sriov_vfio_wait_flr_done() - Wait for VF FLR completion. 32 43 * @xe: the PF &xe_device obtained by calling xe_sriov_vfio_get_pf() 33 44 * @vfid: the VF identifier (can't be 0)