| File: | dev/pci/drm/i915/intel_pcode.c |
| Warning: | line 231, column 2 Undefined or garbage value returned to caller |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | // SPDX-License-Identifier: MIT | |||
| 2 | /* | |||
| 3 | * Copyright © 2013-2021 Intel Corporation | |||
| 4 | */ | |||
| 5 | ||||
| 6 | #include "i915_drv.h" | |||
| 7 | #include "i915_reg.h" | |||
| 8 | #include "intel_pcode.h" | |||
| 9 | ||||
| 10 | static int gen6_check_mailbox_status(u32 mbox) | |||
| 11 | { | |||
| 12 | switch (mbox & GEN6_PCODE_ERROR_MASK0xFF) { | |||
| 13 | case GEN6_PCODE_SUCCESS0x0: | |||
| 14 | return 0; | |||
| 15 | case GEN6_PCODE_UNIMPLEMENTED_CMD0xFF: | |||
| 16 | return -ENODEV19; | |||
| 17 | case GEN6_PCODE_ILLEGAL_CMD0x1: | |||
| 18 | return -ENXIO6; | |||
| 19 | case GEN6_PCODE_MIN_FREQ_TABLE_GT_RATIO_OUT_OF_RANGE0x2: | |||
| 20 | case GEN7_PCODE_MIN_FREQ_TABLE_GT_RATIO_OUT_OF_RANGE0x10: | |||
| 21 | return -EOVERFLOW87; | |||
| 22 | case GEN6_PCODE_TIMEOUT0x3: | |||
| 23 | return -ETIMEDOUT60; | |||
| 24 | default: | |||
| 25 | MISSING_CASE(mbox & GEN6_PCODE_ERROR_MASK)({ int __ret = !!(1); if (__ret) printf("Missing case (%s == %ld)\n" , "mbox & 0xFF", (long)(mbox & 0xFF)); __builtin_expect (!!(__ret), 0); }); | |||
| 26 | return 0; | |||
| 27 | } | |||
| 28 | } | |||
| 29 | ||||
| 30 | static int gen7_check_mailbox_status(u32 mbox) | |||
| 31 | { | |||
| 32 | switch (mbox & GEN6_PCODE_ERROR_MASK0xFF) { | |||
| 33 | case GEN6_PCODE_SUCCESS0x0: | |||
| 34 | return 0; | |||
| 35 | case GEN6_PCODE_ILLEGAL_CMD0x1: | |||
| 36 | return -ENXIO6; | |||
| 37 | case GEN7_PCODE_TIMEOUT0x2: | |||
| 38 | return -ETIMEDOUT60; | |||
| 39 | case GEN7_PCODE_ILLEGAL_DATA0x3: | |||
| 40 | return -EINVAL22; | |||
| 41 | case GEN11_PCODE_ILLEGAL_SUBCOMMAND0x4: | |||
| 42 | return -ENXIO6; | |||
| 43 | case GEN11_PCODE_LOCKED0x6: | |||
| 44 | return -EBUSY16; | |||
| 45 | case GEN11_PCODE_REJECTED0x11: | |||
| 46 | return -EACCES13; | |||
| 47 | case GEN7_PCODE_MIN_FREQ_TABLE_GT_RATIO_OUT_OF_RANGE0x10: | |||
| 48 | return -EOVERFLOW87; | |||
| 49 | default: | |||
| 50 | MISSING_CASE(mbox & GEN6_PCODE_ERROR_MASK)({ int __ret = !!(1); if (__ret) printf("Missing case (%s == %ld)\n" , "mbox & 0xFF", (long)(mbox & 0xFF)); __builtin_expect (!!(__ret), 0); }); | |||
| 51 | return 0; | |||
| 52 | } | |||
| 53 | } | |||
| 54 | ||||
| 55 | static int __snb_pcode_rw(struct intel_uncore *uncore, u32 mbox, | |||
| 56 | u32 *val, u32 *val1, | |||
| 57 | int fast_timeout_us, int slow_timeout_ms, | |||
| 58 | bool_Bool is_read) | |||
| 59 | { | |||
| 60 | lockdep_assert_held(&uncore->i915->sb_lock)do { (void)(&uncore->i915->sb_lock); } while(0); | |||
| 61 | ||||
| 62 | /* | |||
| 63 | * GEN6_PCODE_* are outside of the forcewake domain, we can use | |||
| 64 | * intel_uncore_read/write_fw variants to reduce the amount of work | |||
| 65 | * required when reading/writing. | |||
| 66 | */ | |||
| 67 | ||||
| 68 | if (intel_uncore_read_fw(uncore, GEN6_PCODE_MAILBOX)__raw_uncore_read32(uncore, ((const i915_reg_t){ .reg = (0x138124 ) })) & GEN6_PCODE_READY(1 << 31)) | |||
| 69 | return -EAGAIN35; | |||
| 70 | ||||
| 71 | intel_uncore_write_fw(uncore, GEN6_PCODE_DATA, *val)__raw_uncore_write32(uncore, ((const i915_reg_t){ .reg = (0x138128 ) }), *val); | |||
| 72 | intel_uncore_write_fw(uncore, GEN6_PCODE_DATA1, val1 ? *val1 : 0)__raw_uncore_write32(uncore, ((const i915_reg_t){ .reg = (0x13812C ) }), val1 ? *val1 : 0); | |||
| 73 | intel_uncore_write_fw(uncore,__raw_uncore_write32(uncore, ((const i915_reg_t){ .reg = (0x138124 ) }), (1 << 31) | mbox) | |||
| 74 | GEN6_PCODE_MAILBOX, GEN6_PCODE_READY | mbox)__raw_uncore_write32(uncore, ((const i915_reg_t){ .reg = (0x138124 ) }), (1 << 31) | mbox); | |||
| 75 | ||||
| 76 | if (__intel_wait_for_register_fw(uncore, | |||
| 77 | GEN6_PCODE_MAILBOX((const i915_reg_t){ .reg = (0x138124) }), | |||
| 78 | GEN6_PCODE_READY(1 << 31), 0, | |||
| 79 | fast_timeout_us, | |||
| 80 | slow_timeout_ms, | |||
| 81 | &mbox)) | |||
| 82 | return -ETIMEDOUT60; | |||
| 83 | ||||
| 84 | if (is_read) | |||
| 85 | *val = intel_uncore_read_fw(uncore, GEN6_PCODE_DATA)__raw_uncore_read32(uncore, ((const i915_reg_t){ .reg = (0x138128 ) })); | |||
| 86 | if (is_read && val1) | |||
| 87 | *val1 = intel_uncore_read_fw(uncore, GEN6_PCODE_DATA1)__raw_uncore_read32(uncore, ((const i915_reg_t){ .reg = (0x13812C ) })); | |||
| 88 | ||||
| 89 | if (GRAPHICS_VER(uncore->i915)((&(uncore->i915)->__runtime)->graphics.ip.ver) > 6) | |||
| 90 | return gen7_check_mailbox_status(mbox); | |||
| 91 | else | |||
| 92 | return gen6_check_mailbox_status(mbox); | |||
| 93 | } | |||
| 94 | ||||
| 95 | int snb_pcode_read(struct intel_uncore *uncore, u32 mbox, u32 *val, u32 *val1) | |||
| 96 | { | |||
| 97 | int err; | |||
| 98 | ||||
| 99 | mutex_lock(&uncore->i915->sb_lock)rw_enter_write(&uncore->i915->sb_lock); | |||
| 100 | err = __snb_pcode_rw(uncore, mbox, val, val1, 500, 20, true1); | |||
| 101 | mutex_unlock(&uncore->i915->sb_lock)rw_exit_write(&uncore->i915->sb_lock); | |||
| 102 | ||||
| 103 | if (err) { | |||
| 104 | drm_dbg(&uncore->i915->drm,__drm_dev_dbg(((void *)0), (&uncore->i915->drm) ? ( &uncore->i915->drm)->dev : ((void *)0), DRM_UT_DRIVER , "warning: pcode (read from mbox %x) mailbox access failed for %ps: %d\n" , mbox, __builtin_return_address(0), err) | |||
| 105 | "warning: pcode (read from mbox %x) mailbox access failed for %ps: %d\n",__drm_dev_dbg(((void *)0), (&uncore->i915->drm) ? ( &uncore->i915->drm)->dev : ((void *)0), DRM_UT_DRIVER , "warning: pcode (read from mbox %x) mailbox access failed for %ps: %d\n" , mbox, __builtin_return_address(0), err) | |||
| 106 | mbox, __builtin_return_address(0), err)__drm_dev_dbg(((void *)0), (&uncore->i915->drm) ? ( &uncore->i915->drm)->dev : ((void *)0), DRM_UT_DRIVER , "warning: pcode (read from mbox %x) mailbox access failed for %ps: %d\n" , mbox, __builtin_return_address(0), err); | |||
| 107 | } | |||
| 108 | ||||
| 109 | return err; | |||
| 110 | } | |||
| 111 | ||||
| 112 | int snb_pcode_write_timeout(struct intel_uncore *uncore, u32 mbox, u32 val, | |||
| 113 | int fast_timeout_us, int slow_timeout_ms) | |||
| 114 | { | |||
| 115 | int err; | |||
| 116 | ||||
| 117 | mutex_lock(&uncore->i915->sb_lock)rw_enter_write(&uncore->i915->sb_lock); | |||
| 118 | err = __snb_pcode_rw(uncore, mbox, &val, NULL((void *)0), | |||
| 119 | fast_timeout_us, slow_timeout_ms, false0); | |||
| 120 | mutex_unlock(&uncore->i915->sb_lock)rw_exit_write(&uncore->i915->sb_lock); | |||
| 121 | ||||
| 122 | if (err) { | |||
| 123 | drm_dbg(&uncore->i915->drm,__drm_dev_dbg(((void *)0), (&uncore->i915->drm) ? ( &uncore->i915->drm)->dev : ((void *)0), DRM_UT_DRIVER , "warning: pcode (write of 0x%08x to mbox %x) mailbox access failed for %ps: %d\n" , val, mbox, __builtin_return_address(0), err) | |||
| 124 | "warning: pcode (write of 0x%08x to mbox %x) mailbox access failed for %ps: %d\n",__drm_dev_dbg(((void *)0), (&uncore->i915->drm) ? ( &uncore->i915->drm)->dev : ((void *)0), DRM_UT_DRIVER , "warning: pcode (write of 0x%08x to mbox %x) mailbox access failed for %ps: %d\n" , val, mbox, __builtin_return_address(0), err) | |||
| 125 | val, mbox, __builtin_return_address(0), err)__drm_dev_dbg(((void *)0), (&uncore->i915->drm) ? ( &uncore->i915->drm)->dev : ((void *)0), DRM_UT_DRIVER , "warning: pcode (write of 0x%08x to mbox %x) mailbox access failed for %ps: %d\n" , val, mbox, __builtin_return_address(0), err); | |||
| 126 | } | |||
| 127 | ||||
| 128 | return err; | |||
| 129 | } | |||
| 130 | ||||
| 131 | static bool_Bool skl_pcode_try_request(struct intel_uncore *uncore, u32 mbox, | |||
| 132 | u32 request, u32 reply_mask, u32 reply, | |||
| 133 | u32 *status) | |||
| 134 | { | |||
| 135 | *status = __snb_pcode_rw(uncore, mbox, &request, NULL((void *)0), 500, 0, true1); | |||
| 136 | ||||
| 137 | return (*status == 0) && ((request & reply_mask) == reply); | |||
| 138 | } | |||
| 139 | ||||
| 140 | /** | |||
| 141 | * skl_pcode_request - send PCODE request until acknowledgment | |||
| 142 | * @uncore: uncore | |||
| 143 | * @mbox: PCODE mailbox ID the request is targeted for | |||
| 144 | * @request: request ID | |||
| 145 | * @reply_mask: mask used to check for request acknowledgment | |||
| 146 | * @reply: value used to check for request acknowledgment | |||
| 147 | * @timeout_base_ms: timeout for polling with preemption enabled | |||
| 148 | * | |||
| 149 | * Keep resending the @request to @mbox until PCODE acknowledges it, PCODE | |||
| 150 | * reports an error or an overall timeout of @timeout_base_ms+50 ms expires. | |||
| 151 | * The request is acknowledged once the PCODE reply dword equals @reply after | |||
| 152 | * applying @reply_mask. Polling is first attempted with preemption enabled | |||
| 153 | * for @timeout_base_ms and if this times out for another 50 ms with | |||
| 154 | * preemption disabled. | |||
| 155 | * | |||
| 156 | * Returns 0 on success, %-ETIMEDOUT in case of a timeout, <0 in case of some | |||
| 157 | * other error as reported by PCODE. | |||
| 158 | */ | |||
| 159 | int skl_pcode_request(struct intel_uncore *uncore, u32 mbox, u32 request, | |||
| 160 | u32 reply_mask, u32 reply, int timeout_base_ms) | |||
| 161 | { | |||
| 162 | u32 status; | |||
| 163 | int ret; | |||
| 164 | ||||
| 165 | mutex_lock(&uncore->i915->sb_lock)rw_enter_write(&uncore->i915->sb_lock); | |||
| 166 | ||||
| 167 | #define COND \ | |||
| 168 | skl_pcode_try_request(uncore, mbox, request, reply_mask, reply, &status) | |||
| 169 | ||||
| 170 | /* | |||
| 171 | * Prime the PCODE by doing a request first. Normally it guarantees | |||
| 172 | * that a subsequent request, at most @timeout_base_ms later, succeeds. | |||
| 173 | * _wait_for() doesn't guarantee when its passed condition is evaluated | |||
| 174 | * first, so send the first request explicitly. | |||
| 175 | */ | |||
| 176 | if (COND) { | |||
| 177 | ret = 0; | |||
| 178 | goto out; | |||
| 179 | } | |||
| 180 | ret = _wait_for(COND, timeout_base_ms * 1000, 10, 10)({ const ktime_t end__ = ktime_add_ns(ktime_get_raw(), 1000ll * ((timeout_base_ms * 1000))); long wait__ = ((10)); int ret__ ; assertwaitok(); for (;;) { const _Bool expired__ = ktime_after (ktime_get_raw(), end__); ; __asm volatile("" : : : "memory") ; if ((COND)) { ret__ = 0; break; } if (expired__) { ret__ = - 60; break; } usleep_range(wait__, wait__ * 2); if (wait__ < ((10))) wait__ <<= 1; } ret__; }); | |||
| 181 | if (!ret) | |||
| 182 | goto out; | |||
| 183 | ||||
| 184 | /* | |||
| 185 | * The above can time out if the number of requests was low (2 in the | |||
| 186 | * worst case) _and_ PCODE was busy for some reason even after a | |||
| 187 | * (queued) request and @timeout_base_ms delay. As a workaround retry | |||
| 188 | * the poll with preemption disabled to maximize the number of | |||
| 189 | * requests. Increase the timeout from @timeout_base_ms to 50ms to | |||
| 190 | * account for interrupts that could reduce the number of these | |||
| 191 | * requests, and for any quirks of the PCODE firmware that delays | |||
| 192 | * the request completion. | |||
| 193 | */ | |||
| 194 | drm_dbg_kms(&uncore->i915->drm,__drm_dev_dbg(((void *)0), (&uncore->i915->drm) ? ( &uncore->i915->drm)->dev : ((void *)0), DRM_UT_KMS , "PCODE timeout, retrying with preemption disabled\n") | |||
| 195 | "PCODE timeout, retrying with preemption disabled\n")__drm_dev_dbg(((void *)0), (&uncore->i915->drm) ? ( &uncore->i915->drm)->dev : ((void *)0), DRM_UT_KMS , "PCODE timeout, retrying with preemption disabled\n"); | |||
| 196 | drm_WARN_ON_ONCE(&uncore->i915->drm, timeout_base_ms > 3)({ static int __warned; int __ret = !!((timeout_base_ms > 3 )); if (__ret && !__warned) { printf("%s %s: " "%s", dev_driver_string (((&uncore->i915->drm))->dev), "", "drm_WARN_ON_ONCE(" "timeout_base_ms > 3" ")"); __warned = 1; } __builtin_expect (!!(__ret), 0); }); | |||
| 197 | preempt_disable(); | |||
| 198 | ret = wait_for_atomic(COND, 50)({ extern char _ctassert[(!(!__builtin_constant_p((50) * 1000 ))) ? 1 : -1 ] __attribute__((__unused__)); extern char _ctassert [(!(((50) * 1000) > 50000)) ? 1 : -1 ] __attribute__((__unused__ )); ({ int cpu, ret, timeout = (((50) * 1000)) * 1000; u64 base ; do { } while (0); if (!(1)) { preempt_disable(); cpu = (({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci ) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci; })->ci_cpuid); } base = local_clock(); for (;;) { u64 now = local_clock(); if (!(1)) preempt_enable(); __asm volatile("" : : : "memory"); if (((COND))) { ret = 0; break; } if (now - base >= timeout) { ret = -60; break; } cpu_relax(); if (! (1)) { preempt_disable(); if (__builtin_expect(!!(cpu != (({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci ) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci; })->ci_cpuid)), 0)) { timeout -= now - base; cpu = (({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci ) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci; })->ci_cpuid); base = local_clock(); } } } ret; }); }); | |||
| 199 | preempt_enable(); | |||
| 200 | ||||
| 201 | out: | |||
| 202 | mutex_unlock(&uncore->i915->sb_lock)rw_exit_write(&uncore->i915->sb_lock); | |||
| 203 | return status ? status : ret; | |||
| 204 | #undef COND | |||
| 205 | } | |||
| 206 | ||||
| 207 | int intel_pcode_init(struct intel_uncore *uncore) | |||
| 208 | { | |||
| 209 | if (!IS_DGFX(uncore->i915)((&(uncore->i915)->__info)->is_dgfx)) | |||
| 210 | return 0; | |||
| 211 | ||||
| 212 | return skl_pcode_request(uncore, DG1_PCODE_STATUS0x7E, | |||
| 213 | DG1_UNCORE_GET_INIT_STATUS0x0, | |||
| 214 | DG1_UNCORE_INIT_STATUS_COMPLETE0x1, | |||
| 215 | DG1_UNCORE_INIT_STATUS_COMPLETE0x1, 180000); | |||
| 216 | } | |||
| 217 | ||||
| 218 | int snb_pcode_read_p(struct intel_uncore *uncore, u32 mbcmd, u32 p1, u32 p2, u32 *val) | |||
| 219 | { | |||
| 220 | intel_wakeref_t wakeref; | |||
| 221 | u32 mbox; | |||
| 222 | int err; | |||
| ||||
| 223 | ||||
| 224 | mbox = REG_FIELD_PREP(GEN6_PCODE_MB_COMMAND, mbcmd)((u32)((((typeof(((u32)((((~0UL) >> (64 - (7) - 1)) & ((~0UL) << (0))) + 0))))(mbcmd) << (__builtin_ffsll (((u32)((((~0UL) >> (64 - (7) - 1)) & ((~0UL) << (0))) + 0))) - 1)) & (((u32)((((~0UL) >> (64 - (7) - 1)) & ((~0UL) << (0))) + 0)))) + 0 + 0 + 0 + 0)) | |||
| 225 | | REG_FIELD_PREP(GEN6_PCODE_MB_PARAM1, p1)((u32)((((typeof(((u32)((((~0UL) >> (64 - (15) - 1)) & ((~0UL) << (8))) + 0))))(p1) << (__builtin_ffsll (((u32)((((~0UL) >> (64 - (15) - 1)) & ((~0UL) << (8))) + 0))) - 1)) & (((u32)((((~0UL) >> (64 - (15 ) - 1)) & ((~0UL) << (8))) + 0)))) + 0 + 0 + 0 + 0) ) | |||
| 226 | | REG_FIELD_PREP(GEN6_PCODE_MB_PARAM2, p2)((u32)((((typeof(((u32)((((~0UL) >> (64 - (23) - 1)) & ((~0UL) << (16))) + 0))))(p2) << (__builtin_ffsll (((u32)((((~0UL) >> (64 - (23) - 1)) & ((~0UL) << (16))) + 0))) - 1)) & (((u32)((((~0UL) >> (64 - (23 ) - 1)) & ((~0UL) << (16))) + 0)))) + 0 + 0 + 0 + 0 )); | |||
| 227 | ||||
| 228 | with_intel_runtime_pm(uncore->rpm, wakeref)for ((wakeref) = intel_runtime_pm_get(uncore->rpm); (wakeref ); intel_runtime_pm_put((uncore->rpm), (wakeref)), (wakeref ) = 0) | |||
| 229 | err = snb_pcode_read(uncore, mbox, val, NULL((void *)0)); | |||
| 230 | ||||
| 231 | return err; | |||
| ||||
| 232 | } | |||
| 233 | ||||
| 234 | int snb_pcode_write_p(struct intel_uncore *uncore, u32 mbcmd, u32 p1, u32 p2, u32 val) | |||
| 235 | { | |||
| 236 | intel_wakeref_t wakeref; | |||
| 237 | u32 mbox; | |||
| 238 | int err; | |||
| 239 | ||||
| 240 | mbox = REG_FIELD_PREP(GEN6_PCODE_MB_COMMAND, mbcmd)((u32)((((typeof(((u32)((((~0UL) >> (64 - (7) - 1)) & ((~0UL) << (0))) + 0))))(mbcmd) << (__builtin_ffsll (((u32)((((~0UL) >> (64 - (7) - 1)) & ((~0UL) << (0))) + 0))) - 1)) & (((u32)((((~0UL) >> (64 - (7) - 1)) & ((~0UL) << (0))) + 0)))) + 0 + 0 + 0 + 0)) | |||
| 241 | | REG_FIELD_PREP(GEN6_PCODE_MB_PARAM1, p1)((u32)((((typeof(((u32)((((~0UL) >> (64 - (15) - 1)) & ((~0UL) << (8))) + 0))))(p1) << (__builtin_ffsll (((u32)((((~0UL) >> (64 - (15) - 1)) & ((~0UL) << (8))) + 0))) - 1)) & (((u32)((((~0UL) >> (64 - (15 ) - 1)) & ((~0UL) << (8))) + 0)))) + 0 + 0 + 0 + 0) ) | |||
| 242 | | REG_FIELD_PREP(GEN6_PCODE_MB_PARAM2, p2)((u32)((((typeof(((u32)((((~0UL) >> (64 - (23) - 1)) & ((~0UL) << (16))) + 0))))(p2) << (__builtin_ffsll (((u32)((((~0UL) >> (64 - (23) - 1)) & ((~0UL) << (16))) + 0))) - 1)) & (((u32)((((~0UL) >> (64 - (23 ) - 1)) & ((~0UL) << (16))) + 0)))) + 0 + 0 + 0 + 0 )); | |||
| 243 | ||||
| 244 | with_intel_runtime_pm(uncore->rpm, wakeref)for ((wakeref) = intel_runtime_pm_get(uncore->rpm); (wakeref ); intel_runtime_pm_put((uncore->rpm), (wakeref)), (wakeref ) = 0) | |||
| 245 | err = snb_pcode_write(uncore, mbox, val)snb_pcode_write_timeout(uncore, mbox, val, 500, 0); | |||
| 246 | ||||
| 247 | return err; | |||
| 248 | } |