1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Tegra host1x Syncpoints 4 * 5 * Copyright (c) 2010-2015, NVIDIA Corporation. 6 */ 7 8 #include <linux/module.h> 9 #include <linux/device.h> 10 #include <linux/dma-fence.h> 11 #include <linux/slab.h> 12 13 #include <trace/events/host1x.h> 14 15 #include "syncpt.h" 16 #include "dev.h" 17 #include "intr.h" 18 #include "debug.h" 19 20 #define SYNCPT_CHECK_PERIOD (2 * HZ) 21 #define MAX_STUCK_CHECK_COUNT 15 22 23 static struct host1x_syncpt_base * 24 host1x_syncpt_base_request(struct host1x *host) 25 { 26 struct host1x_syncpt_base *bases = host->bases; 27 unsigned int i; 28 29 for (i = 0; i < host->info->nb_bases; i++) 30 if (!bases[i].requested) 31 break; 32 33 if (i >= host->info->nb_bases) 34 return NULL; 35 36 bases[i].requested = true; 37 return &bases[i]; 38 } 39 40 static void host1x_syncpt_base_free(struct host1x_syncpt_base *base) 41 { 42 if (base) 43 base->requested = false; 44 } 45 46 /** 47 * host1x_syncpt_alloc() - allocate a syncpoint 48 * @host: host1x device data 49 * @flags: bitfield of HOST1X_SYNCPT_* flags 50 * @name: name for the syncpoint for use in debug prints 51 * 52 * Allocates a hardware syncpoint for the caller's use. The caller then has 53 * the sole authority to mutate the syncpoint's value until it is freed again. 54 * 55 * If no free syncpoints are available, or a NULL name was specified, returns 56 * NULL. 57 */ 58 struct host1x_syncpt *host1x_syncpt_alloc(struct host1x *host, 59 unsigned long flags, 60 const char *name) 61 { 62 struct host1x_syncpt *sp = host->syncpt; 63 char *full_name; 64 unsigned int i; 65 66 if (!name) 67 return NULL; 68 69 mutex_lock(&host->syncpt_mutex); 70 71 for (i = 0; i < host->info->nb_pts && kref_read(&sp->ref); i++, sp++) 72 ; 73 74 if (i >= host->info->nb_pts) 75 goto unlock; 76 77 if (flags & HOST1X_SYNCPT_HAS_BASE) { 78 sp->base = host1x_syncpt_base_request(host); 79 if (!sp->base) 80 goto unlock; 81 } 82 83 full_name = kasprintf(GFP_KERNEL, "%u-%s", sp->id, name); 84 if (!full_name) 85 goto free_base; 86 87 sp->name = full_name; 88 89 if (flags & HOST1X_SYNCPT_CLIENT_MANAGED) 90 sp->client_managed = true; 91 else 92 sp->client_managed = false; 93 94 kref_init(&sp->ref); 95 96 mutex_unlock(&host->syncpt_mutex); 97 return sp; 98 99 free_base: 100 host1x_syncpt_base_free(sp->base); 101 sp->base = NULL; 102 unlock: 103 mutex_unlock(&host->syncpt_mutex); 104 return NULL; 105 } 106 EXPORT_SYMBOL(host1x_syncpt_alloc); 107 108 /** 109 * host1x_syncpt_id() - retrieve syncpoint ID 110 * @sp: host1x syncpoint 111 * 112 * Given a pointer to a struct host1x_syncpt, retrieves its ID. This ID is 113 * often used as a value to program into registers that control how hardware 114 * blocks interact with syncpoints. 115 */ 116 u32 host1x_syncpt_id(struct host1x_syncpt *sp) 117 { 118 return sp->id; 119 } 120 EXPORT_SYMBOL(host1x_syncpt_id); 121 122 /** 123 * host1x_syncpt_incr_max() - update the value sent to hardware 124 * @sp: host1x syncpoint 125 * @incrs: number of increments 126 */ 127 u32 host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs) 128 { 129 return (u32)atomic_add_return(incrs, &sp->max_val); 130 } 131 EXPORT_SYMBOL(host1x_syncpt_incr_max); 132 133 /* 134 * Write cached syncpoint and waitbase values to hardware. 135 */ 136 void host1x_syncpt_restore(struct host1x *host) 137 { 138 struct host1x_syncpt *sp_base = host->syncpt; 139 unsigned int i; 140 141 for (i = 0; i < host1x_syncpt_nb_pts(host); i++) { 142 /* 143 * Unassign syncpt from channels for purposes of Tegra186 144 * syncpoint protection. This prevents any channel from 145 * accessing it until it is reassigned. 146 */ 147 host1x_hw_syncpt_assign_to_channel(host, sp_base + i, NULL); 148 host1x_hw_syncpt_restore(host, sp_base + i); 149 } 150 151 for (i = 0; i < host1x_syncpt_nb_bases(host); i++) 152 host1x_hw_syncpt_restore_wait_base(host, sp_base + i); 153 154 host1x_hw_syncpt_enable_protection(host); 155 156 wmb(); 157 } 158 159 /* 160 * Update the cached syncpoint and waitbase values by reading them 161 * from the registers. 162 */ 163 void host1x_syncpt_save(struct host1x *host) 164 { 165 struct host1x_syncpt *sp_base = host->syncpt; 166 unsigned int i; 167 168 for (i = 0; i < host1x_syncpt_nb_pts(host); i++) { 169 if (host1x_syncpt_client_managed(sp_base + i)) 170 host1x_hw_syncpt_load(host, sp_base + i); 171 else 172 WARN_ON(!host1x_syncpt_idle(sp_base + i)); 173 } 174 175 for (i = 0; i < host1x_syncpt_nb_bases(host); i++) 176 host1x_hw_syncpt_load_wait_base(host, sp_base + i); 177 } 178 179 /* 180 * Updates the cached syncpoint value by reading a new value from the hardware 181 * register 182 */ 183 u32 host1x_syncpt_load(struct host1x_syncpt *sp) 184 { 185 u32 val; 186 187 val = host1x_hw_syncpt_load(sp->host, sp); 188 trace_host1x_syncpt_load_min(sp->id, val); 189 190 return val; 191 } 192 193 /* 194 * Get the current syncpoint base 195 */ 196 u32 host1x_syncpt_load_wait_base(struct host1x_syncpt *sp) 197 { 198 host1x_hw_syncpt_load_wait_base(sp->host, sp); 199 200 return sp->base_val; 201 } 202 203 /** 204 * host1x_syncpt_incr() - increment syncpoint value from CPU, updating cache 205 * @sp: host1x syncpoint 206 */ 207 int host1x_syncpt_incr(struct host1x_syncpt *sp) 208 { 209 return host1x_hw_syncpt_cpu_incr(sp->host, sp); 210 } 211 EXPORT_SYMBOL(host1x_syncpt_incr); 212 213 /** 214 * host1x_syncpt_wait() - wait for a syncpoint to reach a given value 215 * @sp: host1x syncpoint 216 * @thresh: threshold 217 * @timeout: maximum time to wait for the syncpoint to reach the given value 218 * @value: return location for the syncpoint value 219 */ 220 int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout, 221 u32 *value) 222 { 223 struct dma_fence *fence; 224 long wait_err; 225 u32 curr; 226 227 curr = host1x_syncpt_load(sp); 228 229 if (value) 230 *value = curr; 231 232 if (host1x_syncpt_is_expired(sp, thresh)) 233 return 0; 234 235 if (timeout < 0) 236 timeout = LONG_MAX; 237 else if (timeout == 0) 238 return -EAGAIN; 239 240 fence = host1x_fence_create(sp, thresh, false); 241 if (IS_ERR(fence)) 242 return PTR_ERR(fence); 243 244 wait_err = dma_fence_wait_timeout(fence, true, timeout); 245 if (wait_err == 0) 246 host1x_fence_cancel(fence); 247 dma_fence_put(fence); 248 249 /* 250 * Don't rely on dma_fence_wait_timeout return value, 251 * since it returns zero both on timeout and if the 252 * wait completed with 0 jiffies left. 253 */ 254 if (wait_err == 0 && !host1x_syncpt_is_expired(sp, thresh)) { 255 if (value) 256 *value = host1x_syncpt_load(sp); 257 258 return -EAGAIN; 259 } else if (wait_err < 0) { 260 return wait_err; 261 } else { 262 /* Success, read the value cached by ISR */ 263 if (value) 264 *value = host1x_syncpt_read_min(sp); 265 266 return 0; 267 } 268 } 269 EXPORT_SYMBOL(host1x_syncpt_wait); 270 271 /* 272 * Returns true if syncpoint is expired, false if we may need to wait 273 */ 274 bool host1x_syncpt_is_expired(struct host1x_syncpt *sp, u32 thresh) 275 { 276 u32 current_val; 277 278 smp_rmb(); 279 280 current_val = (u32)atomic_read(&sp->min_val); 281 282 return ((current_val - thresh) & 0x80000000U) == 0U; 283 } 284 285 int host1x_syncpt_init(struct host1x *host) 286 { 287 struct host1x_syncpt_base *bases; 288 struct host1x_syncpt *syncpt; 289 unsigned int i; 290 291 syncpt = devm_kcalloc(host->dev, host->info->nb_pts, sizeof(*syncpt), 292 GFP_KERNEL); 293 if (!syncpt) 294 return -ENOMEM; 295 296 bases = devm_kcalloc(host->dev, host->info->nb_bases, sizeof(*bases), 297 GFP_KERNEL); 298 if (!bases) 299 return -ENOMEM; 300 301 for (i = 0; i < host->info->nb_pts; i++) { 302 syncpt[i].id = i; 303 syncpt[i].host = host; 304 } 305 306 for (i = 0; i < host->info->nb_bases; i++) 307 bases[i].id = i; 308 309 mutex_init(&host->syncpt_mutex); 310 host->syncpt = syncpt; 311 host->bases = bases; 312 313 /* Allocate sync point to use for clearing waits for expired fences */ 314 host->nop_sp = host1x_syncpt_alloc(host, 0, "reserved-nop"); 315 if (!host->nop_sp) 316 return -ENOMEM; 317 318 if (host->info->reserve_vblank_syncpts) { 319 kref_init(&host->syncpt[26].ref); 320 kref_init(&host->syncpt[27].ref); 321 } 322 323 return 0; 324 } 325 326 /** 327 * host1x_syncpt_request() - request a syncpoint 328 * @client: client requesting the syncpoint 329 * @flags: flags 330 * 331 * host1x client drivers can use this function to allocate a syncpoint for 332 * subsequent use. A syncpoint returned by this function will be reserved for 333 * use by the client exclusively. When no longer using a syncpoint, a host1x 334 * client driver needs to release it using host1x_syncpt_put(). 335 */ 336 struct host1x_syncpt *host1x_syncpt_request(struct host1x_client *client, 337 unsigned long flags) 338 { 339 struct host1x *host = dev_get_drvdata(client->host->parent); 340 341 return host1x_syncpt_alloc(host, flags, dev_name(client->dev)); 342 } 343 EXPORT_SYMBOL(host1x_syncpt_request); 344 345 static void syncpt_release(struct kref *ref) 346 { 347 struct host1x_syncpt *sp = container_of(ref, struct host1x_syncpt, ref); 348 349 atomic_set(&sp->max_val, host1x_syncpt_read(sp)); 350 351 sp->locked = false; 352 353 host1x_syncpt_base_free(sp->base); 354 kfree(sp->name); 355 sp->base = NULL; 356 sp->name = NULL; 357 sp->client_managed = false; 358 359 mutex_unlock(&sp->host->syncpt_mutex); 360 } 361 362 /** 363 * host1x_syncpt_put() - free a requested syncpoint 364 * @sp: host1x syncpoint 365 * 366 * Release a syncpoint previously allocated using host1x_syncpt_request(). A 367 * host1x client driver should call this when the syncpoint is no longer in 368 * use. 369 */ 370 void host1x_syncpt_put(struct host1x_syncpt *sp) 371 { 372 if (!sp) 373 return; 374 375 kref_put_mutex(&sp->ref, syncpt_release, &sp->host->syncpt_mutex); 376 } 377 EXPORT_SYMBOL(host1x_syncpt_put); 378 379 void host1x_syncpt_deinit(struct host1x *host) 380 { 381 struct host1x_syncpt *sp = host->syncpt; 382 unsigned int i; 383 384 for (i = 0; i < host->info->nb_pts; i++, sp++) 385 kfree(sp->name); 386 } 387 388 /** 389 * host1x_syncpt_read_max() - read maximum syncpoint value 390 * @sp: host1x syncpoint 391 * 392 * The maximum syncpoint value indicates how many operations there are in 393 * queue, either in channel or in a software thread. 394 */ 395 u32 host1x_syncpt_read_max(struct host1x_syncpt *sp) 396 { 397 smp_rmb(); 398 399 return (u32)atomic_read(&sp->max_val); 400 } 401 EXPORT_SYMBOL(host1x_syncpt_read_max); 402 403 /** 404 * host1x_syncpt_read_min() - read minimum syncpoint value 405 * @sp: host1x syncpoint 406 * 407 * The minimum syncpoint value is a shadow of the current sync point value in 408 * hardware. 409 */ 410 u32 host1x_syncpt_read_min(struct host1x_syncpt *sp) 411 { 412 smp_rmb(); 413 414 return (u32)atomic_read(&sp->min_val); 415 } 416 EXPORT_SYMBOL(host1x_syncpt_read_min); 417 418 /** 419 * host1x_syncpt_read() - read the current syncpoint value 420 * @sp: host1x syncpoint 421 */ 422 u32 host1x_syncpt_read(struct host1x_syncpt *sp) 423 { 424 return host1x_syncpt_load(sp); 425 } 426 EXPORT_SYMBOL(host1x_syncpt_read); 427 428 unsigned int host1x_syncpt_nb_pts(struct host1x *host) 429 { 430 return host->info->nb_pts; 431 } 432 433 unsigned int host1x_syncpt_nb_bases(struct host1x *host) 434 { 435 return host->info->nb_bases; 436 } 437 438 unsigned int host1x_syncpt_nb_mlocks(struct host1x *host) 439 { 440 return host->info->nb_mlocks; 441 } 442 443 /** 444 * host1x_syncpt_get_by_id() - obtain a syncpoint by ID 445 * @host: host1x controller 446 * @id: syncpoint ID 447 */ 448 struct host1x_syncpt *host1x_syncpt_get_by_id(struct host1x *host, 449 unsigned int id) 450 { 451 if (id >= host->info->nb_pts) 452 return NULL; 453 454 if (kref_get_unless_zero(&host->syncpt[id].ref)) 455 return &host->syncpt[id]; 456 else 457 return NULL; 458 } 459 EXPORT_SYMBOL(host1x_syncpt_get_by_id); 460 461 /** 462 * host1x_syncpt_get_by_id_noref() - obtain a syncpoint by ID but don't 463 * increase the refcount. 464 * @host: host1x controller 465 * @id: syncpoint ID 466 */ 467 struct host1x_syncpt *host1x_syncpt_get_by_id_noref(struct host1x *host, 468 unsigned int id) 469 { 470 if (id >= host->info->nb_pts) 471 return NULL; 472 473 return &host->syncpt[id]; 474 } 475 EXPORT_SYMBOL(host1x_syncpt_get_by_id_noref); 476 477 /** 478 * host1x_syncpt_get() - increment syncpoint refcount 479 * @sp: syncpoint 480 */ 481 struct host1x_syncpt *host1x_syncpt_get(struct host1x_syncpt *sp) 482 { 483 kref_get(&sp->ref); 484 485 return sp; 486 } 487 EXPORT_SYMBOL(host1x_syncpt_get); 488 489 /** 490 * host1x_syncpt_get_base() - obtain the wait base associated with a syncpoint 491 * @sp: host1x syncpoint 492 */ 493 struct host1x_syncpt_base *host1x_syncpt_get_base(struct host1x_syncpt *sp) 494 { 495 return sp ? sp->base : NULL; 496 } 497 EXPORT_SYMBOL(host1x_syncpt_get_base); 498 499 /** 500 * host1x_syncpt_base_id() - retrieve the ID of a syncpoint wait base 501 * @base: host1x syncpoint wait base 502 */ 503 u32 host1x_syncpt_base_id(struct host1x_syncpt_base *base) 504 { 505 return base->id; 506 } 507 EXPORT_SYMBOL(host1x_syncpt_base_id); 508 509 static void do_nothing(struct kref *ref) 510 { 511 } 512 513 /** 514 * host1x_syncpt_release_vblank_reservation() - Make VBLANK syncpoint 515 * available for allocation 516 * 517 * @client: host1x bus client 518 * @syncpt_id: syncpoint ID to make available 519 * 520 * Makes VBLANK<i> syncpoint available for allocatation if it was 521 * reserved at initialization time. This should be called by the display 522 * driver after it has ensured that any VBLANK increment programming configured 523 * by the boot chain has been disabled. 524 */ 525 void host1x_syncpt_release_vblank_reservation(struct host1x_client *client, 526 u32 syncpt_id) 527 { 528 struct host1x *host = dev_get_drvdata(client->host->parent); 529 530 if (!host->info->reserve_vblank_syncpts) 531 return; 532 533 kref_put(&host->syncpt[syncpt_id].ref, do_nothing); 534 } 535 EXPORT_SYMBOL(host1x_syncpt_release_vblank_reservation); 536