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