1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2022 Intel Corporation 4 */ 5 6 #include "xe_pcode.h" 7 8 #include <linux/delay.h> 9 #include <linux/errno.h> 10 #include <linux/error-injection.h> 11 12 #include <drm/drm_managed.h> 13 14 #include "regs/xe_pmt.h" 15 #include "xe_assert.h" 16 #include "xe_device.h" 17 #include "xe_mmio.h" 18 #include "xe_pcode_api.h" 19 #include "xe_pm.h" 20 #include "xe_printk.h" 21 #include "xe_vsec.h" 22 23 /** 24 * DOC: PCODE 25 * 26 * Xe PCODE is the component responsible for interfacing with the PCODE 27 * firmware. 28 * It shall provide a very simple ABI to other Xe components, but be the 29 * single and consolidated place that will communicate with PCODE. All read 30 * and write operations to PCODE will be internal and private to this component. 31 * 32 * What's next: 33 * - PCODE hw metrics 34 * - PCODE for display operations 35 */ 36 37 static int pcode_mailbox_status(struct xe_tile *tile) 38 { 39 const char *err_str; 40 int err_decode; 41 u32 err; 42 43 #define CASE_ERR(_err, _err_decode, _err_str) \ 44 case _err: \ 45 err_decode = _err_decode; \ 46 err_str = _err_str; \ 47 break 48 49 err = xe_mmio_read32(&tile->mmio, PCODE_MAILBOX) & PCODE_ERROR_MASK; 50 switch (err) { 51 CASE_ERR(PCODE_ILLEGAL_CMD, -ENXIO, "Illegal Command"); 52 CASE_ERR(PCODE_TIMEOUT, -ETIMEDOUT, "Timed out"); 53 CASE_ERR(PCODE_ILLEGAL_DATA, -EINVAL, "Illegal Data"); 54 CASE_ERR(PCODE_ILLEGAL_SUBCOMMAND, -ENXIO, "Illegal Subcommand"); 55 CASE_ERR(PCODE_LOCKED, -EBUSY, "PCODE Locked"); 56 CASE_ERR(PCODE_GT_RATIO_OUT_OF_RANGE, -EOVERFLOW, "GT ratio out of range"); 57 CASE_ERR(PCODE_REJECTED, -EACCES, "PCODE Rejected"); 58 default: 59 err_decode = -EPROTO; 60 err_str = "Unknown"; 61 } 62 63 if (err) { 64 drm_err(&tile_to_xe(tile)->drm, "PCODE Mailbox failed: %d %s", 65 err_decode, err_str); 66 67 return err_decode; 68 } 69 70 return 0; 71 #undef CASE_ERR 72 } 73 74 static int __pcode_mailbox_rw(struct xe_tile *tile, u32 mbox, u32 *data0, u32 *data1, 75 unsigned int timeout_ms, bool return_data, 76 bool atomic) 77 { 78 struct xe_mmio *mmio = &tile->mmio; 79 int err; 80 81 if (tile_to_xe(tile)->info.skip_pcode) 82 return 0; 83 84 if ((xe_mmio_read32(mmio, PCODE_MAILBOX) & PCODE_READY) != 0) 85 return -EAGAIN; 86 87 xe_mmio_write32(mmio, PCODE_DATA0, *data0); 88 xe_mmio_write32(mmio, PCODE_DATA1, data1 ? *data1 : 0); 89 xe_mmio_write32(mmio, PCODE_MAILBOX, PCODE_READY | mbox); 90 91 err = xe_mmio_wait32(mmio, PCODE_MAILBOX, PCODE_READY, 0, 92 timeout_ms * USEC_PER_MSEC, NULL, atomic); 93 if (err) 94 return err; 95 96 if (return_data) { 97 *data0 = xe_mmio_read32(mmio, PCODE_DATA0); 98 if (data1) 99 *data1 = xe_mmio_read32(mmio, PCODE_DATA1); 100 } 101 102 return pcode_mailbox_status(tile); 103 } 104 105 static int pcode_mailbox_rw(struct xe_tile *tile, u32 mbox, u32 *data0, u32 *data1, 106 unsigned int timeout_ms, bool return_data, 107 bool atomic) 108 { 109 if (tile_to_xe(tile)->info.skip_pcode) 110 return 0; 111 112 lockdep_assert_held(&tile->pcode.lock); 113 114 return __pcode_mailbox_rw(tile, mbox, data0, data1, timeout_ms, return_data, atomic); 115 } 116 117 int xe_pcode_write_timeout(struct xe_tile *tile, u32 mbox, u32 data, int timeout) 118 { 119 int err; 120 121 mutex_lock(&tile->pcode.lock); 122 err = pcode_mailbox_rw(tile, mbox, &data, NULL, timeout, false, false); 123 mutex_unlock(&tile->pcode.lock); 124 125 return err; 126 } 127 128 int xe_pcode_write64_timeout(struct xe_tile *tile, u32 mbox, u32 data0, u32 data1, int timeout) 129 { 130 int err; 131 132 mutex_lock(&tile->pcode.lock); 133 err = pcode_mailbox_rw(tile, mbox, &data0, &data1, timeout, false, false); 134 mutex_unlock(&tile->pcode.lock); 135 136 return err; 137 } 138 139 int xe_pcode_read(struct xe_tile *tile, u32 mbox, u32 *val, u32 *val1) 140 { 141 int err; 142 143 mutex_lock(&tile->pcode.lock); 144 err = pcode_mailbox_rw(tile, mbox, val, val1, 1, true, false); 145 mutex_unlock(&tile->pcode.lock); 146 147 return err; 148 } 149 150 static int pcode_try_request(struct xe_tile *tile, u32 mbox, 151 u32 request, u32 reply_mask, u32 reply, 152 u32 *status, bool atomic, int timeout_us, bool locked) 153 { 154 int slept, wait = 10; 155 156 xe_tile_assert(tile, timeout_us > 0); 157 158 for (slept = 0; slept < timeout_us; slept += wait) { 159 if (locked) 160 *status = pcode_mailbox_rw(tile, mbox, &request, NULL, 1, true, 161 atomic); 162 else 163 *status = __pcode_mailbox_rw(tile, mbox, &request, NULL, 1, true, 164 atomic); 165 if ((*status == 0) && ((request & reply_mask) == reply)) 166 return 0; 167 168 if (atomic) 169 udelay(wait); 170 else 171 usleep_range(wait, wait << 1); 172 wait <<= 1; 173 } 174 175 return -ETIMEDOUT; 176 } 177 178 /** 179 * xe_pcode_request - send PCODE request until acknowledgment 180 * @tile: tile 181 * @mbox: PCODE mailbox ID the request is targeted for 182 * @request: request ID 183 * @reply_mask: mask used to check for request acknowledgment 184 * @reply: value used to check for request acknowledgment 185 * @timeout_base_ms: timeout for polling with preemption enabled 186 * 187 * Keep resending the @request to @mbox until PCODE acknowledges it, PCODE 188 * reports an error or an overall timeout of @timeout_base_ms+50 ms expires. 189 * The request is acknowledged once the PCODE reply dword equals @reply after 190 * applying @reply_mask. Polling is first attempted with preemption enabled 191 * for @timeout_base_ms and if this times out for another 50 ms with 192 * preemption disabled. 193 * 194 * Returns 0 on success, %-ETIMEDOUT in case of a timeout, <0 in case of some 195 * other error as reported by PCODE. 196 */ 197 int xe_pcode_request(struct xe_tile *tile, u32 mbox, u32 request, 198 u32 reply_mask, u32 reply, int timeout_base_ms) 199 { 200 u32 status; 201 int ret; 202 203 xe_tile_assert(tile, timeout_base_ms <= 3); 204 205 mutex_lock(&tile->pcode.lock); 206 207 ret = pcode_try_request(tile, mbox, request, reply_mask, reply, &status, 208 false, timeout_base_ms * 1000, true); 209 if (!ret) 210 goto out; 211 212 /* 213 * The above can time out if the number of requests was low (2 in the 214 * worst case) _and_ PCODE was busy for some reason even after a 215 * (queued) request and @timeout_base_ms delay. As a workaround retry 216 * the poll with preemption disabled to maximize the number of 217 * requests. Increase the timeout from @timeout_base_ms to 50ms to 218 * account for interrupts that could reduce the number of these 219 * requests, and for any quirks of the PCODE firmware that delays 220 * the request completion. 221 */ 222 drm_err(&tile_to_xe(tile)->drm, 223 "PCODE timeout, retrying with preemption disabled\n"); 224 preempt_disable(); 225 ret = pcode_try_request(tile, mbox, request, reply_mask, reply, &status, 226 true, 50 * 1000, true); 227 preempt_enable(); 228 229 out: 230 mutex_unlock(&tile->pcode.lock); 231 return status ? status : ret; 232 } 233 /** 234 * xe_pcode_init_min_freq_table - Initialize PCODE's QOS frequency table 235 * @tile: tile instance 236 * @min_gt_freq: Minimal (RPn) GT frequency in units of 50MHz. 237 * @max_gt_freq: Maximal (RP0) GT frequency in units of 50MHz. 238 * 239 * This function initialize PCODE's QOS frequency table for a proper minimal 240 * frequency/power steering decision, depending on the current requested GT 241 * frequency. For older platforms this was a more complete table including 242 * the IA freq. However for the latest platforms this table become a simple 243 * 1-1 Ring vs GT frequency. Even though, without setting it, PCODE might 244 * not take the right decisions for some memory frequencies and affect latency. 245 * 246 * It returns 0 on success, and -ERROR number on failure, -EINVAL if max 247 * frequency is higher then the minimal, and other errors directly translated 248 * from the PCODE Error returns: 249 * - -ENXIO: "Illegal Command" 250 * - -ETIMEDOUT: "Timed out" 251 * - -EINVAL: "Illegal Data" 252 * - -ENXIO, "Illegal Subcommand" 253 * - -EBUSY: "PCODE Locked" 254 * - -EOVERFLOW, "GT ratio out of range" 255 * - -EACCES, "PCODE Rejected" 256 * - -EPROTO, "Unknown" 257 */ 258 int xe_pcode_init_min_freq_table(struct xe_tile *tile, u32 min_gt_freq, 259 u32 max_gt_freq) 260 { 261 int ret; 262 u32 freq; 263 264 if (!tile_to_xe(tile)->info.has_llc) 265 return 0; 266 267 if (max_gt_freq <= min_gt_freq) 268 return -EINVAL; 269 270 mutex_lock(&tile->pcode.lock); 271 for (freq = min_gt_freq; freq <= max_gt_freq; freq++) { 272 u32 data = freq << PCODE_FREQ_RING_RATIO_SHIFT | freq; 273 274 ret = pcode_mailbox_rw(tile, PCODE_WRITE_MIN_FREQ_TABLE, 275 &data, NULL, 1, false, false); 276 if (ret) 277 goto unlock; 278 } 279 280 unlock: 281 mutex_unlock(&tile->pcode.lock); 282 return ret; 283 } 284 285 /** 286 * xe_pcode_ready - Ensure PCODE is initialized 287 * @xe: xe instance 288 * @locked: true if lock held, false otherwise 289 * 290 * PCODE init mailbox is polled only on root gt of root tile 291 * as the root tile provides the initialization is complete only 292 * after all the tiles have completed the initialization. 293 * Called only on early probe without locks and with locks in 294 * resume path. 295 * 296 * Returns 0 on success, and -error number on failure. 297 */ 298 int xe_pcode_ready(struct xe_device *xe, bool locked) 299 { 300 u32 status, request = DGFX_GET_INIT_STATUS; 301 struct xe_tile *tile = xe_device_get_root_tile(xe); 302 int timeout_us = 180000000; /* 3 min */ 303 int ret; 304 305 if (xe->info.skip_pcode) 306 return 0; 307 308 if (!IS_DGFX(xe)) 309 return 0; 310 311 if (locked) 312 mutex_lock(&tile->pcode.lock); 313 314 ret = pcode_try_request(tile, DGFX_PCODE_STATUS, request, 315 DGFX_INIT_STATUS_COMPLETE, 316 DGFX_INIT_STATUS_COMPLETE, 317 &status, false, timeout_us, locked); 318 319 if (locked) 320 mutex_unlock(&tile->pcode.lock); 321 322 if (ret) 323 drm_err(&xe->drm, 324 "PCODE initialization timedout after: 3 min\n"); 325 326 return ret; 327 } 328 329 /** 330 * xe_pcode_init_early() - Initialize components of PCODE 331 * @tile: tile instance 332 * 333 * This function initializes the xe_pcode component. 334 * To be called once only during probe. 335 * 336 * Return: 0 on success or a negative error code on failure. 337 */ 338 int xe_pcode_init_early(struct xe_tile *tile) 339 { 340 return drmm_mutex_init(&tile_to_xe(tile)->drm, &tile->pcode.lock); 341 } 342 343 /** 344 * xe_pcode_probe_early: initializes PCODE 345 * @xe: xe instance 346 * 347 * This function checks the initialization status of PCODE 348 * To be called once only during early probe without locks. 349 * 350 * Returns 0 on success, error code otherwise 351 */ 352 int xe_pcode_probe_early(struct xe_device *xe) 353 { 354 return xe_pcode_ready(xe, false); 355 } 356 ALLOW_ERROR_INJECTION(xe_pcode_probe_early, ERRNO); /* See xe_pci_probe */ 357 358 /** 359 * xe_get_pcode_version - Read pcode version via PMT telemetry 360 * @xe: xe instance 361 * @version: pointer to struct xe_pcode_version to store version info 362 * 363 * Reads the pcode version from PMT telemetry and fills the 364 * provided @version structure. 365 * 366 * Return: 0 on success, negative error code on failure. 367 */ 368 int xe_get_pcode_version(struct xe_device *xe, struct xe_pcode_version *version) 369 { 370 int ret = 0; 371 372 guard(xe_pm_runtime)(xe); 373 374 ret = xe_pmt_telem_read(xe->drm.dev, 375 xe_mmio_read32(xe_root_tile_mmio(xe), PUNIT_TELEMETRY_GUID), 376 (u64 *)version, PUNIT_VERSION_OFFSET, sizeof(*version)); 377 if (ret != sizeof(*version)) { 378 xe_warn(xe, "pcode version read from PMT failed, ret %pe\n", ERR_PTR(ret)); 379 return ret; 380 } 381 xe_dbg(xe, "pcode version major %u minor %u engg %u\n", version->major, 382 version->minor, version->engg); 383 return 0; 384 } 385