1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2023 Intel Corporation 4 */ 5 6 #include <drm/drm_managed.h> 7 8 #include "xe_assert.h" 9 #include "xe_sriov.h" 10 11 /** 12 * xe_sriov_mode_to_string - Convert enum value to string. 13 * @mode: the &xe_sriov_mode to convert 14 * 15 * Returns: SR-IOV mode as a user friendly string. 16 */ 17 const char *xe_sriov_mode_to_string(enum xe_sriov_mode mode) 18 { 19 switch (mode) { 20 case XE_SRIOV_MODE_NONE: 21 return "none"; 22 case XE_SRIOV_MODE_PF: 23 return "SR-IOV PF"; 24 case XE_SRIOV_MODE_VF: 25 return "SR-IOV VF"; 26 default: 27 return "<invalid>"; 28 } 29 } 30 31 /** 32 * xe_sriov_probe_early - Probe a SR-IOV mode. 33 * @xe: the &xe_device to probe mode on 34 * @has_sriov: flag indicating hardware support for SR-IOV 35 * 36 * This function should be called only once and as soon as possible during 37 * driver probe to detect whether we are running a SR-IOV Physical Function 38 * (PF) or a Virtual Function (VF) device. 39 * 40 * SR-IOV PF mode detection is based on PCI @dev_is_pf() function. 41 * SR-IOV VF mode detection is based on dedicated MMIO register read. 42 */ 43 void xe_sriov_probe_early(struct xe_device *xe, bool has_sriov) 44 { 45 enum xe_sriov_mode mode = XE_SRIOV_MODE_NONE; 46 47 /* TODO: replace with proper mode detection */ 48 xe_assert(xe, !has_sriov); 49 50 xe_assert(xe, !xe->sriov.__mode); 51 xe->sriov.__mode = mode; 52 xe_assert(xe, xe->sriov.__mode); 53 54 if (has_sriov) 55 drm_info(&xe->drm, "Running in %s mode\n", 56 xe_sriov_mode_to_string(xe_device_sriov_mode(xe))); 57 } 58 59 static void fini_sriov(struct drm_device *drm, void *arg) 60 { 61 struct xe_device *xe = arg; 62 63 destroy_workqueue(xe->sriov.wq); 64 xe->sriov.wq = NULL; 65 } 66 67 /** 68 * xe_sriov_init - Initialize SR-IOV specific data. 69 * @xe: the &xe_device to initialize 70 * 71 * In this function we create dedicated workqueue that will be used 72 * by the SR-IOV specific workers. 73 * 74 * Return: 0 on success or a negative error code on failure. 75 */ 76 int xe_sriov_init(struct xe_device *xe) 77 { 78 if (!IS_SRIOV(xe)) 79 return 0; 80 81 xe_assert(xe, !xe->sriov.wq); 82 xe->sriov.wq = alloc_workqueue("xe-sriov-wq", 0, 0); 83 if (!xe->sriov.wq) 84 return -ENOMEM; 85 86 return drmm_add_action_or_reset(&xe->drm, fini_sriov, xe); 87 } 88