Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/xe: Switch MMIO interface to take xe_mmio instead of xe_gt

Since much of the MMIO register access done by the driver is to non-GT
registers, use of 'xe_gt' in these interfaces has been a long-standing
design flaw that's been hard to disentangle.

To avoid a flag day across the whole driver, munge the function names
and add temporary compatibility macros with the original function names
that can accept either the new xe_mmio or the old xe_gt structure as a
parameter. This will allow us to slowly convert parts of the driver
over to the new interface independently.

Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240910234719.3335472-54-matthew.d.roper@intel.com

+124 -86
+63 -68
drivers/gpu/drm/xe/xe_mmio.c
··· 67 67 68 68 /* Possibly override number of tile based on configuration register */ 69 69 if (!xe->info.skip_mtcfg) { 70 - struct xe_gt *gt = xe_root_mmio_gt(xe); 70 + struct xe_mmio *mmio = xe_root_tile_mmio(xe); 71 71 u8 tile_count; 72 72 u32 mtcfg; 73 73 74 74 /* 75 75 * Although the per-tile mmio regs are not yet initialized, this 76 - * is fine as it's going to the root gt, that's guaranteed to be 77 - * initialized earlier in xe_mmio_init() 76 + * is fine as it's going to the root tile's mmio, that's 77 + * guaranteed to be initialized earlier in xe_mmio_init() 78 78 */ 79 - mtcfg = xe_mmio_read64_2x32(gt, XEHP_MTCFG_ADDR); 79 + mtcfg = xe_mmio_read64_2x32(mmio, XEHP_MTCFG_ADDR); 80 80 tile_count = REG_FIELD_GET(TILE_COUNT, mtcfg) + 1; 81 81 82 82 if (tile_count < xe->info.tile_count) { ··· 186 186 return devm_add_action_or_reset(xe->drm.dev, mmio_fini, xe); 187 187 } 188 188 189 - static void mmio_flush_pending_writes(struct xe_gt *gt) 189 + static void mmio_flush_pending_writes(struct xe_mmio *mmio) 190 190 { 191 191 #define DUMMY_REG_OFFSET 0x130030 192 - struct xe_tile *tile = gt_to_tile(gt); 193 192 int i; 194 193 195 - if (tile->xe->info.platform != XE_LUNARLAKE) 194 + if (mmio->tile->xe->info.platform != XE_LUNARLAKE) 196 195 return; 197 196 198 197 /* 4 dummy writes */ 199 198 for (i = 0; i < 4; i++) 200 - writel(0, tile->mmio.regs + DUMMY_REG_OFFSET); 199 + writel(0, mmio->regs + DUMMY_REG_OFFSET); 201 200 } 202 201 203 - u8 xe_mmio_read8(struct xe_gt *gt, struct xe_reg reg) 202 + u8 __xe_mmio_read8(struct xe_mmio *mmio, struct xe_reg reg) 204 203 { 205 - struct xe_tile *tile = gt_to_tile(gt); 206 - u32 addr = xe_mmio_adjusted_addr(gt, reg.addr); 204 + u32 addr = xe_mmio_adjusted_addr(mmio, reg.addr); 207 205 u8 val; 208 206 209 207 /* Wa_15015404425 */ 210 - mmio_flush_pending_writes(gt); 208 + mmio_flush_pending_writes(mmio); 211 209 212 - val = readb((reg.ext ? tile->mmio_ext.regs : tile->mmio.regs) + addr); 213 - trace_xe_reg_rw(gt, false, addr, val, sizeof(val)); 210 + val = readb(mmio->regs + addr); 211 + trace_xe_reg_rw(mmio, false, addr, val, sizeof(val)); 214 212 215 213 return val; 216 214 } 217 215 218 - u16 xe_mmio_read16(struct xe_gt *gt, struct xe_reg reg) 216 + u16 __xe_mmio_read16(struct xe_mmio *mmio, struct xe_reg reg) 219 217 { 220 - struct xe_tile *tile = gt_to_tile(gt); 221 - u32 addr = xe_mmio_adjusted_addr(gt, reg.addr); 218 + u32 addr = xe_mmio_adjusted_addr(mmio, reg.addr); 222 219 u16 val; 223 220 224 221 /* Wa_15015404425 */ 225 - mmio_flush_pending_writes(gt); 222 + mmio_flush_pending_writes(mmio); 226 223 227 - val = readw((reg.ext ? tile->mmio_ext.regs : tile->mmio.regs) + addr); 228 - trace_xe_reg_rw(gt, false, addr, val, sizeof(val)); 224 + val = readw(mmio->regs + addr); 225 + trace_xe_reg_rw(mmio, false, addr, val, sizeof(val)); 229 226 230 227 return val; 231 228 } 232 229 233 - void xe_mmio_write32(struct xe_gt *gt, struct xe_reg reg, u32 val) 230 + void __xe_mmio_write32(struct xe_mmio *mmio, struct xe_reg reg, u32 val) 234 231 { 235 - struct xe_tile *tile = gt_to_tile(gt); 236 - u32 addr = xe_mmio_adjusted_addr(gt, reg.addr); 232 + u32 addr = xe_mmio_adjusted_addr(mmio, reg.addr); 237 233 238 - trace_xe_reg_rw(gt, true, addr, val, sizeof(val)); 234 + trace_xe_reg_rw(mmio, true, addr, val, sizeof(val)); 239 235 240 - if (!reg.vf && IS_SRIOV_VF(gt_to_xe(gt))) 241 - xe_gt_sriov_vf_write32(gt, reg, val); 236 + if (!reg.vf && mmio->sriov_vf_gt) 237 + xe_gt_sriov_vf_write32(mmio->sriov_vf_gt, reg, val); 242 238 else 243 - writel(val, (reg.ext ? tile->mmio_ext.regs : tile->mmio.regs) + addr); 239 + writel(val, mmio->regs + addr); 244 240 } 245 241 246 - u32 xe_mmio_read32(struct xe_gt *gt, struct xe_reg reg) 242 + u32 __xe_mmio_read32(struct xe_mmio *mmio, struct xe_reg reg) 247 243 { 248 - struct xe_tile *tile = gt_to_tile(gt); 249 - u32 addr = xe_mmio_adjusted_addr(gt, reg.addr); 244 + u32 addr = xe_mmio_adjusted_addr(mmio, reg.addr); 250 245 u32 val; 251 246 252 247 /* Wa_15015404425 */ 253 - mmio_flush_pending_writes(gt); 248 + mmio_flush_pending_writes(mmio); 254 249 255 - if (!reg.vf && IS_SRIOV_VF(gt_to_xe(gt))) 256 - val = xe_gt_sriov_vf_read32(gt, reg); 250 + if (!reg.vf && mmio->sriov_vf_gt) 251 + val = xe_gt_sriov_vf_read32(mmio->sriov_vf_gt, reg); 257 252 else 258 - val = readl((reg.ext ? tile->mmio_ext.regs : tile->mmio.regs) + addr); 253 + val = readl(mmio->regs + addr); 259 254 260 - trace_xe_reg_rw(gt, false, addr, val, sizeof(val)); 255 + trace_xe_reg_rw(mmio, false, addr, val, sizeof(val)); 261 256 262 257 return val; 263 258 } 264 259 265 - u32 xe_mmio_rmw32(struct xe_gt *gt, struct xe_reg reg, u32 clr, u32 set) 260 + u32 __xe_mmio_rmw32(struct xe_mmio *mmio, struct xe_reg reg, u32 clr, u32 set) 266 261 { 267 262 u32 old, reg_val; 268 263 269 - old = xe_mmio_read32(gt, reg); 264 + old = xe_mmio_read32(mmio, reg); 270 265 reg_val = (old & ~clr) | set; 271 - xe_mmio_write32(gt, reg, reg_val); 266 + xe_mmio_write32(mmio, reg, reg_val); 272 267 273 268 return old; 274 269 } 275 270 276 - int xe_mmio_write32_and_verify(struct xe_gt *gt, 277 - struct xe_reg reg, u32 val, u32 mask, u32 eval) 271 + int __xe_mmio_write32_and_verify(struct xe_mmio *mmio, 272 + struct xe_reg reg, u32 val, u32 mask, u32 eval) 278 273 { 279 274 u32 reg_val; 280 275 281 - xe_mmio_write32(gt, reg, val); 282 - reg_val = xe_mmio_read32(gt, reg); 276 + xe_mmio_write32(mmio, reg, val); 277 + reg_val = xe_mmio_read32(mmio, reg); 283 278 284 279 return (reg_val & mask) != eval ? -EINVAL : 0; 285 280 } 286 281 287 - bool xe_mmio_in_range(const struct xe_gt *gt, 288 - const struct xe_mmio_range *range, 289 - struct xe_reg reg) 282 + bool __xe_mmio_in_range(const struct xe_mmio *mmio, 283 + const struct xe_mmio_range *range, 284 + struct xe_reg reg) 290 285 { 291 - u32 addr = xe_mmio_adjusted_addr(gt, reg.addr); 286 + u32 addr = xe_mmio_adjusted_addr(mmio, reg.addr); 292 287 293 288 return range && addr >= range->start && addr <= range->end; 294 289 } 295 290 296 291 /** 297 292 * xe_mmio_read64_2x32() - Read a 64-bit register as two 32-bit reads 298 - * @gt: MMIO target GT 293 + * @mmio: MMIO target 299 294 * @reg: register to read value from 300 295 * 301 296 * Although Intel GPUs have some 64-bit registers, the hardware officially ··· 310 315 * 311 316 * Returns the value of the 64-bit register. 312 317 */ 313 - u64 xe_mmio_read64_2x32(struct xe_gt *gt, struct xe_reg reg) 318 + u64 __xe_mmio_read64_2x32(struct xe_mmio *mmio, struct xe_reg reg) 314 319 { 315 320 struct xe_reg reg_udw = { .addr = reg.addr + 0x4 }; 316 321 u32 ldw, udw, oldudw, retries; 317 322 318 - reg.addr = xe_mmio_adjusted_addr(gt, reg.addr); 319 - reg_udw.addr = xe_mmio_adjusted_addr(gt, reg_udw.addr); 323 + reg.addr = xe_mmio_adjusted_addr(mmio, reg.addr); 324 + reg_udw.addr = xe_mmio_adjusted_addr(mmio, reg_udw.addr); 320 325 321 326 /* we shouldn't adjust just one register address */ 322 - xe_gt_assert(gt, reg_udw.addr == reg.addr + 0x4); 327 + xe_tile_assert(mmio->tile, reg_udw.addr == reg.addr + 0x4); 323 328 324 - oldudw = xe_mmio_read32(gt, reg_udw); 329 + oldudw = xe_mmio_read32(mmio, reg_udw); 325 330 for (retries = 5; retries; --retries) { 326 - ldw = xe_mmio_read32(gt, reg); 327 - udw = xe_mmio_read32(gt, reg_udw); 331 + ldw = xe_mmio_read32(mmio, reg); 332 + udw = xe_mmio_read32(mmio, reg_udw); 328 333 329 334 if (udw == oldudw) 330 335 break; ··· 332 337 oldudw = udw; 333 338 } 334 339 335 - xe_gt_WARN(gt, retries == 0, 336 - "64-bit read of %#x did not stabilize\n", reg.addr); 340 + drm_WARN(&mmio->tile->xe->drm, retries == 0, 341 + "64-bit read of %#x did not stabilize\n", reg.addr); 337 342 338 343 return (u64)udw << 32 | ldw; 339 344 } 340 345 341 - static int __xe_mmio_wait32(struct xe_gt *gt, struct xe_reg reg, u32 mask, u32 val, u32 timeout_us, 342 - u32 *out_val, bool atomic, bool expect_match) 346 + static int ____xe_mmio_wait32(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, u32 val, u32 timeout_us, 347 + u32 *out_val, bool atomic, bool expect_match) 343 348 { 344 349 ktime_t cur = ktime_get_raw(); 345 350 const ktime_t end = ktime_add_us(cur, timeout_us); ··· 349 354 bool check; 350 355 351 356 for (;;) { 352 - read = xe_mmio_read32(gt, reg); 357 + read = xe_mmio_read32(mmio, reg); 353 358 354 359 check = (read & mask) == val; 355 360 if (!expect_match) ··· 375 380 } 376 381 377 382 if (ret != 0) { 378 - read = xe_mmio_read32(gt, reg); 383 + read = xe_mmio_read32(mmio, reg); 379 384 380 385 check = (read & mask) == val; 381 386 if (!expect_match) ··· 393 398 394 399 /** 395 400 * xe_mmio_wait32() - Wait for a register to match the desired masked value 396 - * @gt: MMIO target GT 401 + * @mmio: MMIO target 397 402 * @reg: register to read value from 398 403 * @mask: mask to be applied to the value read from the register 399 404 * @val: desired value after applying the mask ··· 410 415 * @timeout_us for different reasons, specially in non-atomic contexts. Thus, 411 416 * it is possible that this function succeeds even after @timeout_us has passed. 412 417 */ 413 - int xe_mmio_wait32(struct xe_gt *gt, struct xe_reg reg, u32 mask, u32 val, u32 timeout_us, 414 - u32 *out_val, bool atomic) 418 + int __xe_mmio_wait32(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, u32 val, u32 timeout_us, 419 + u32 *out_val, bool atomic) 415 420 { 416 - return __xe_mmio_wait32(gt, reg, mask, val, timeout_us, out_val, atomic, true); 421 + return ____xe_mmio_wait32(mmio, reg, mask, val, timeout_us, out_val, atomic, true); 417 422 } 418 423 419 424 /** 420 425 * xe_mmio_wait32_not() - Wait for a register to return anything other than the given masked value 421 - * @gt: MMIO target GT 426 + * @mmio: MMIO target 422 427 * @reg: register to read value from 423 428 * @mask: mask to be applied to the value read from the register 424 429 * @val: value not to be matched after applying the mask ··· 429 434 * This function works exactly like xe_mmio_wait32() with the exception that 430 435 * @val is expected not to be matched. 431 436 */ 432 - int xe_mmio_wait32_not(struct xe_gt *gt, struct xe_reg reg, u32 mask, u32 val, u32 timeout_us, 433 - u32 *out_val, bool atomic) 437 + int __xe_mmio_wait32_not(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, u32 val, u32 timeout_us, 438 + u32 *out_val, bool atomic) 434 439 { 435 - return __xe_mmio_wait32(gt, reg, mask, val, timeout_us, out_val, atomic, false); 440 + return ____xe_mmio_wait32(mmio, reg, mask, val, timeout_us, out_val, atomic, false); 436 441 }
+57 -15
drivers/gpu/drm/xe/xe_mmio.h
··· 14 14 int xe_mmio_init(struct xe_device *xe); 15 15 int xe_mmio_probe_tiles(struct xe_device *xe); 16 16 17 - u8 xe_mmio_read8(struct xe_gt *gt, struct xe_reg reg); 18 - u16 xe_mmio_read16(struct xe_gt *gt, struct xe_reg reg); 19 - void xe_mmio_write32(struct xe_gt *gt, struct xe_reg reg, u32 val); 20 - u32 xe_mmio_read32(struct xe_gt *gt, struct xe_reg reg); 21 - u32 xe_mmio_rmw32(struct xe_gt *gt, struct xe_reg reg, u32 clr, u32 set); 22 - int xe_mmio_write32_and_verify(struct xe_gt *gt, struct xe_reg reg, u32 val, u32 mask, u32 eval); 23 - bool xe_mmio_in_range(const struct xe_gt *gt, const struct xe_mmio_range *range, struct xe_reg reg); 17 + /* 18 + * Temporary transition helper for xe_gt -> xe_mmio conversion. Allows 19 + * continued usage of xe_gt as a parameter to MMIO operations which now 20 + * take an xe_mmio structure instead. Will be removed once the driver-wide 21 + * conversion is complete. 22 + */ 23 + #define __to_xe_mmio(ptr) \ 24 + _Generic(ptr, \ 25 + const struct xe_gt *: (&((const struct xe_gt *)(ptr))->mmio), \ 26 + struct xe_gt *: (&((struct xe_gt *)(ptr))->mmio), \ 27 + const struct xe_mmio *: (ptr), \ 28 + struct xe_mmio *: (ptr)) 24 29 25 - u64 xe_mmio_read64_2x32(struct xe_gt *gt, struct xe_reg reg); 26 - int xe_mmio_wait32(struct xe_gt *gt, struct xe_reg reg, u32 mask, u32 val, u32 timeout_us, 27 - u32 *out_val, bool atomic); 28 - int xe_mmio_wait32_not(struct xe_gt *gt, struct xe_reg reg, u32 mask, u32 val, u32 timeout_us, 29 - u32 *out_val, bool atomic); 30 + u8 __xe_mmio_read8(struct xe_mmio *mmio, struct xe_reg reg); 31 + #define xe_mmio_read8(p, reg) __xe_mmio_read8(__to_xe_mmio(p), reg) 30 32 31 - static inline u32 xe_mmio_adjusted_addr(const struct xe_gt *gt, u32 addr) 33 + u16 __xe_mmio_read16(struct xe_mmio *mmio, struct xe_reg reg); 34 + #define xe_mmio_read16(p, reg) __xe_mmio_read16(__to_xe_mmio(p), reg) 35 + 36 + void __xe_mmio_write32(struct xe_mmio *mmio, struct xe_reg reg, u32 val); 37 + #define xe_mmio_write32(p, reg, val) __xe_mmio_write32(__to_xe_mmio(p), reg, val) 38 + 39 + u32 __xe_mmio_read32(struct xe_mmio *mmio, struct xe_reg reg); 40 + #define xe_mmio_read32(p, reg) __xe_mmio_read32(__to_xe_mmio(p), reg) 41 + 42 + u32 __xe_mmio_rmw32(struct xe_mmio *mmio, struct xe_reg reg, u32 clr, u32 set); 43 + #define xe_mmio_rmw32(p, reg, clr, set) __xe_mmio_rmw32(__to_xe_mmio(p), reg, clr, set) 44 + 45 + int __xe_mmio_write32_and_verify(struct xe_mmio *mmio, struct xe_reg reg, 46 + u32 val, u32 mask, u32 eval); 47 + #define xe_mmio_write32_and_verify(p, reg, val, mask, eval) \ 48 + __xe_mmio_write32_and_verify(__to_xe_mmio(p), reg, val, mask, eval) 49 + 50 + bool __xe_mmio_in_range(const struct xe_mmio *mmio, 51 + const struct xe_mmio_range *range, struct xe_reg reg); 52 + #define xe_mmio_in_range(p, range, reg) __xe_mmio_in_range(__to_xe_mmio(p), range, reg) 53 + 54 + u64 __xe_mmio_read64_2x32(struct xe_mmio *mmio, struct xe_reg reg); 55 + #define xe_mmio_read64_2x32(p, reg) __xe_mmio_read64_2x32(__to_xe_mmio(p), reg) 56 + 57 + int __xe_mmio_wait32(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, u32 val, 58 + u32 timeout_us, u32 *out_val, bool atomic); 59 + #define xe_mmio_wait32(p, reg, mask, val, timeout_us, out_val, atomic) \ 60 + __xe_mmio_wait32(__to_xe_mmio(p), reg, mask, val, timeout_us, out_val, atomic) 61 + 62 + int __xe_mmio_wait32_not(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, 63 + u32 val, u32 timeout_us, u32 *out_val, bool atomic); 64 + #define xe_mmio_wait32_not(p, reg, mask, val, timeout_us, out_val, atomic) \ 65 + __xe_mmio_wait32_not(__to_xe_mmio(p), reg, mask, val, timeout_us, out_val, atomic) 66 + 67 + static inline u32 __xe_mmio_adjusted_addr(const struct xe_mmio *mmio, u32 addr) 32 68 { 33 - if (addr < gt->mmio.adj_limit) 34 - addr += gt->mmio.adj_offset; 69 + if (addr < mmio->adj_limit) 70 + addr += mmio->adj_offset; 35 71 return addr; 72 + } 73 + #define xe_mmio_adjusted_addr(p, addr) __xe_mmio_adjusted_addr(__to_xe_mmio(p), addr) 74 + 75 + static inline struct xe_mmio *xe_root_tile_mmio(struct xe_device *xe) 76 + { 77 + return &xe->tiles[0].mmio; 36 78 } 37 79 38 80 #endif
+4 -3
drivers/gpu/drm/xe/xe_trace.h
··· 21 21 #include "xe_vm.h" 22 22 23 23 #define __dev_name_xe(xe) dev_name((xe)->drm.dev) 24 + #define __dev_name_tile(tile) __dev_name_xe(tile_to_xe((tile))) 24 25 #define __dev_name_gt(gt) __dev_name_xe(gt_to_xe((gt))) 25 26 #define __dev_name_eq(q) __dev_name_gt((q)->gt) 26 27 ··· 343 342 ); 344 343 345 344 TRACE_EVENT(xe_reg_rw, 346 - TP_PROTO(struct xe_gt *gt, bool write, u32 reg, u64 val, int len), 345 + TP_PROTO(struct xe_mmio *mmio, bool write, u32 reg, u64 val, int len), 347 346 348 - TP_ARGS(gt, write, reg, val, len), 347 + TP_ARGS(mmio, write, reg, val, len), 349 348 350 349 TP_STRUCT__entry( 351 - __string(dev, __dev_name_gt(gt)) 350 + __string(dev, __dev_name_tile(mmio->tile)) 352 351 __field(u64, val) 353 352 __field(u32, reg) 354 353 __field(u16, write)