1 /* SPDX-License-Identifier: MIT */ 2 /* 3 * Copyright © 2022 Intel Corporation 4 */ 5 6 #ifndef _XE_FORCE_WAKE_H_ 7 #define _XE_FORCE_WAKE_H_ 8 9 #include "xe_assert.h" 10 #include "xe_force_wake_types.h" 11 12 struct xe_gt; 13 14 void xe_force_wake_init_gt(struct xe_gt *gt, 15 struct xe_force_wake *fw); 16 void xe_force_wake_init_engines(struct xe_gt *gt, 17 struct xe_force_wake *fw); 18 unsigned int __must_check xe_force_wake_get(struct xe_force_wake *fw, 19 enum xe_force_wake_domains domains); 20 void xe_force_wake_put(struct xe_force_wake *fw, unsigned int fw_ref); 21 22 const char *xe_force_wake_domain_to_str(enum xe_force_wake_domain_id id); 23 24 #define for_each_fw_domain_masked(domain__, mask__, fw__, tmp__) \ 25 for (tmp__ = (mask__); tmp__; tmp__ &= ~BIT(ffs(tmp__) - 1)) \ 26 for_each_if(((domain__) = ((fw__)->domains + \ 27 (ffs(tmp__) - 1))) && \ 28 (domain__)->reg_ctl.addr) 29 30 #define for_each_fw_domain(domain__, fw__, tmp__) \ 31 for_each_fw_domain_masked((domain__), (fw__)->initialized_domains, (fw__), (tmp__)) 32 33 static inline int 34 xe_force_wake_ref(struct xe_force_wake *fw, 35 enum xe_force_wake_domains domain) 36 { 37 xe_gt_assert(fw->gt, domain != XE_FORCEWAKE_ALL); 38 return fw->domains[ffs(domain) - 1].ref; 39 } 40 41 /** 42 * xe_force_wake_assert_held - asserts domain is awake 43 * @fw : xe_force_wake structure 44 * @domain: xe_force_wake_domains apart from XE_FORCEWAKE_ALL 45 * 46 * xe_force_wake_assert_held() is designed to confirm a particular 47 * forcewake domain's wakefulness; it doesn't verify the wakefulness of 48 * multiple domains. Make sure the caller doesn't input multiple 49 * domains(XE_FORCEWAKE_ALL) as a parameter. 50 */ 51 static inline void 52 xe_force_wake_assert_held(struct xe_force_wake *fw, 53 enum xe_force_wake_domains domain) 54 { 55 xe_gt_assert(fw->gt, domain != XE_FORCEWAKE_ALL); 56 xe_gt_assert(fw->gt, fw->awake_domains & domain); 57 } 58 59 /** 60 * xe_force_wake_ref_has_domain - verifies if the domains are in fw_ref 61 * @fw_ref : the force_wake reference 62 * @domain : forcewake domain to verify 63 * 64 * This function confirms whether the @fw_ref includes a reference to the 65 * specified @domain. 66 * 67 * Return: true if domain is refcounted. 68 */ 69 static inline bool 70 xe_force_wake_ref_has_domain(unsigned int fw_ref, enum xe_force_wake_domains domain) 71 { 72 return fw_ref & domain; 73 } 74 75 struct xe_force_wake_ref { 76 struct xe_force_wake *fw; 77 unsigned int domains; 78 }; 79 80 static struct xe_force_wake_ref 81 xe_force_wake_constructor(struct xe_force_wake *fw, unsigned int domains) 82 { 83 struct xe_force_wake_ref fw_ref = { .fw = fw }; 84 85 fw_ref.domains = xe_force_wake_get(fw, domains); 86 87 return fw_ref; 88 } 89 90 DEFINE_CLASS(xe_force_wake, struct xe_force_wake_ref, 91 xe_force_wake_put(_T.fw, _T.domains), 92 xe_force_wake_constructor(fw, domains), 93 struct xe_force_wake *fw, unsigned int domains); 94 95 /* 96 * Scoped helper for the forcewake class, using the same trick as scoped_guard() 97 * to bind the lifetime to the next statement/block. 98 */ 99 #define __xe_with_force_wake(ref, fw, domains, done) \ 100 for (CLASS(xe_force_wake, ref)(fw, domains), *(done) = NULL; \ 101 !(done); (done) = (void *)1) 102 103 #define xe_with_force_wake(ref, fw, domains) \ 104 __xe_with_force_wake(ref, fw, domains, __UNIQUE_ID(done)) 105 106 /* 107 * Used when xe_force_wake_constructor() has already been called by another 108 * function and the current function is responsible for releasing the forcewake 109 * reference in all possible cases and error paths. 110 */ 111 DEFINE_CLASS(xe_force_wake_release_only, struct xe_force_wake_ref, 112 if (_T.fw) xe_force_wake_put(_T.fw, _T.domains), fw_ref, 113 struct xe_force_wake_ref fw_ref); 114 115 #endif 116