drm_gpusvm.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571
  1. /* SPDX-License-Identifier: GPL-2.0-only OR MIT */
  2. /*
  3. * Copyright © 2024 Intel Corporation
  4. */
  5. #ifndef __DRM_GPUSVM_H__
  6. #define __DRM_GPUSVM_H__
  7. #include <linux/kref.h>
  8. #include <linux/interval_tree.h>
  9. #include <linux/mmu_notifier.h>
  10. struct dev_pagemap_ops;
  11. struct drm_device;
  12. struct drm_gpusvm;
  13. struct drm_gpusvm_notifier;
  14. struct drm_gpusvm_ops;
  15. struct drm_gpusvm_range;
  16. struct drm_pagemap;
  17. struct drm_pagemap_addr;
  18. /**
  19. * struct drm_gpusvm_ops - Operations structure for GPU SVM
  20. *
  21. * This structure defines the operations for GPU Shared Virtual Memory (SVM).
  22. * These operations are provided by the GPU driver to manage SVM ranges and
  23. * notifiers.
  24. */
  25. struct drm_gpusvm_ops {
  26. /**
  27. * @notifier_alloc: Allocate a GPU SVM notifier (optional)
  28. *
  29. * Allocate a GPU SVM notifier.
  30. *
  31. * Return: Pointer to the allocated GPU SVM notifier on success, NULL on failure.
  32. */
  33. struct drm_gpusvm_notifier *(*notifier_alloc)(void);
  34. /**
  35. * @notifier_free: Free a GPU SVM notifier (optional)
  36. * @notifier: Pointer to the GPU SVM notifier to be freed
  37. *
  38. * Free a GPU SVM notifier.
  39. */
  40. void (*notifier_free)(struct drm_gpusvm_notifier *notifier);
  41. /**
  42. * @range_alloc: Allocate a GPU SVM range (optional)
  43. * @gpusvm: Pointer to the GPU SVM
  44. *
  45. * Allocate a GPU SVM range.
  46. *
  47. * Return: Pointer to the allocated GPU SVM range on success, NULL on failure.
  48. */
  49. struct drm_gpusvm_range *(*range_alloc)(struct drm_gpusvm *gpusvm);
  50. /**
  51. * @range_free: Free a GPU SVM range (optional)
  52. * @range: Pointer to the GPU SVM range to be freed
  53. *
  54. * Free a GPU SVM range.
  55. */
  56. void (*range_free)(struct drm_gpusvm_range *range);
  57. /**
  58. * @invalidate: Invalidate GPU SVM notifier (required)
  59. * @gpusvm: Pointer to the GPU SVM
  60. * @notifier: Pointer to the GPU SVM notifier
  61. * @mmu_range: Pointer to the mmu_notifier_range structure
  62. *
  63. * Invalidate the GPU page tables. It can safely walk the notifier range
  64. * RB tree/list in this function. Called while holding the notifier lock.
  65. */
  66. void (*invalidate)(struct drm_gpusvm *gpusvm,
  67. struct drm_gpusvm_notifier *notifier,
  68. const struct mmu_notifier_range *mmu_range);
  69. };
  70. /**
  71. * struct drm_gpusvm_notifier - Structure representing a GPU SVM notifier
  72. *
  73. * @gpusvm: Pointer to the GPU SVM structure
  74. * @notifier: MMU interval notifier
  75. * @itree: Interval tree node for the notifier (inserted in GPU SVM)
  76. * @entry: List entry to fast interval tree traversal
  77. * @root: Cached root node of the RB tree containing ranges
  78. * @range_list: List head containing of ranges in the same order they appear in
  79. * interval tree. This is useful to keep iterating ranges while
  80. * doing modifications to RB tree.
  81. * @flags: Flags for notifier
  82. * @flags.removed: Flag indicating whether the MMU interval notifier has been
  83. * removed
  84. *
  85. * This structure represents a GPU SVM notifier.
  86. */
  87. struct drm_gpusvm_notifier {
  88. struct drm_gpusvm *gpusvm;
  89. struct mmu_interval_notifier notifier;
  90. struct interval_tree_node itree;
  91. struct list_head entry;
  92. struct rb_root_cached root;
  93. struct list_head range_list;
  94. struct {
  95. u32 removed : 1;
  96. } flags;
  97. };
  98. /**
  99. * struct drm_gpusvm_pages_flags - Structure representing a GPU SVM pages flags
  100. *
  101. * @migrate_devmem: Flag indicating whether the pages can be migrated to device memory
  102. * @unmapped: Flag indicating if the pages has been unmapped
  103. * @partial_unmap: Flag indicating if the pages has been partially unmapped
  104. * @has_devmem_pages: Flag indicating if the pages has devmem pages
  105. * @has_dma_mapping: Flag indicating if the pages has a DMA mapping
  106. * @__flags: Flags for pages in u16 form (used for READ_ONCE)
  107. */
  108. struct drm_gpusvm_pages_flags {
  109. union {
  110. struct {
  111. /* All flags below must be set upon creation */
  112. u16 migrate_devmem : 1;
  113. /* All flags below must be set / cleared under notifier lock */
  114. u16 unmapped : 1;
  115. u16 partial_unmap : 1;
  116. u16 has_devmem_pages : 1;
  117. u16 has_dma_mapping : 1;
  118. };
  119. u16 __flags;
  120. };
  121. };
  122. /**
  123. * struct drm_gpusvm_pages - Structure representing a GPU SVM mapped pages
  124. *
  125. * @dma_addr: Device address array
  126. * @dpagemap: The struct drm_pagemap of the device pages we're dma-mapping.
  127. * Note this is assuming only one drm_pagemap per range is allowed.
  128. * @notifier_seq: Notifier sequence number of the range's pages
  129. * @flags: Flags for range
  130. * @flags.migrate_devmem: Flag indicating whether the range can be migrated to device memory
  131. * @flags.unmapped: Flag indicating if the range has been unmapped
  132. * @flags.partial_unmap: Flag indicating if the range has been partially unmapped
  133. * @flags.has_devmem_pages: Flag indicating if the range has devmem pages
  134. * @flags.has_dma_mapping: Flag indicating if the range has a DMA mapping
  135. */
  136. struct drm_gpusvm_pages {
  137. struct drm_pagemap_addr *dma_addr;
  138. struct drm_pagemap *dpagemap;
  139. unsigned long notifier_seq;
  140. struct drm_gpusvm_pages_flags flags;
  141. };
  142. /**
  143. * struct drm_gpusvm_range - Structure representing a GPU SVM range
  144. *
  145. * @gpusvm: Pointer to the GPU SVM structure
  146. * @notifier: Pointer to the GPU SVM notifier
  147. * @refcount: Reference count for the range
  148. * @itree: Interval tree node for the range (inserted in GPU SVM notifier)
  149. * @entry: List entry to fast interval tree traversal
  150. * @pages: The pages for this range.
  151. *
  152. * This structure represents a GPU SVM range used for tracking memory ranges
  153. * mapped in a DRM device.
  154. */
  155. struct drm_gpusvm_range {
  156. struct drm_gpusvm *gpusvm;
  157. struct drm_gpusvm_notifier *notifier;
  158. struct kref refcount;
  159. struct interval_tree_node itree;
  160. struct list_head entry;
  161. struct drm_gpusvm_pages pages;
  162. };
  163. /**
  164. * struct drm_gpusvm - GPU SVM structure
  165. *
  166. * @name: Name of the GPU SVM
  167. * @drm: Pointer to the DRM device structure
  168. * @mm: Pointer to the mm_struct for the address space
  169. * @mm_start: Start address of GPU SVM
  170. * @mm_range: Range of the GPU SVM
  171. * @notifier_size: Size of individual notifiers
  172. * @ops: Pointer to the operations structure for GPU SVM
  173. * @chunk_sizes: Pointer to the array of chunk sizes used in range allocation.
  174. * Entries should be powers of 2 in descending order.
  175. * @num_chunks: Number of chunks
  176. * @notifier_lock: Read-write semaphore for protecting notifier operations
  177. * @root: Cached root node of the Red-Black tree containing GPU SVM notifiers
  178. * @notifier_list: list head containing of notifiers in the same order they
  179. * appear in interval tree. This is useful to keep iterating
  180. * notifiers while doing modifications to RB tree.
  181. *
  182. * This structure represents a GPU SVM (Shared Virtual Memory) used for tracking
  183. * memory ranges mapped in a DRM (Direct Rendering Manager) device.
  184. *
  185. * No reference counting is provided, as this is expected to be embedded in the
  186. * driver VM structure along with the struct drm_gpuvm, which handles reference
  187. * counting.
  188. */
  189. struct drm_gpusvm {
  190. const char *name;
  191. struct drm_device *drm;
  192. struct mm_struct *mm;
  193. unsigned long mm_start;
  194. unsigned long mm_range;
  195. unsigned long notifier_size;
  196. const struct drm_gpusvm_ops *ops;
  197. const unsigned long *chunk_sizes;
  198. int num_chunks;
  199. struct rw_semaphore notifier_lock;
  200. struct rb_root_cached root;
  201. struct list_head notifier_list;
  202. #ifdef CONFIG_LOCKDEP
  203. /**
  204. * @lock_dep_map: Annotates drm_gpusvm_range_find_or_insert and
  205. * drm_gpusvm_range_remove with a driver provided lock.
  206. */
  207. struct lockdep_map *lock_dep_map;
  208. #endif
  209. };
  210. /**
  211. * struct drm_gpusvm_ctx - DRM GPU SVM context
  212. *
  213. * @device_private_page_owner: The device-private page owner to use for
  214. * this operation
  215. * @check_pages_threshold: Check CPU pages for present if chunk is less than or
  216. * equal to threshold. If not present, reduce chunk
  217. * size.
  218. * @timeslice_ms: The timeslice MS which in minimum time a piece of memory
  219. * remains with either exclusive GPU or CPU access.
  220. * @in_notifier: entering from a MMU notifier
  221. * @read_only: operating on read-only memory
  222. * @devmem_possible: possible to use device memory
  223. * @devmem_only: use only device memory
  224. * @allow_mixed: Allow mixed mappings in get pages. Mixing between system and
  225. * single dpagemap is supported, mixing between multiple dpagemap
  226. * is unsupported.
  227. *
  228. * Context that is DRM GPUSVM is operating in (i.e. user arguments).
  229. */
  230. struct drm_gpusvm_ctx {
  231. void *device_private_page_owner;
  232. unsigned long check_pages_threshold;
  233. unsigned long timeslice_ms;
  234. unsigned int in_notifier :1;
  235. unsigned int read_only :1;
  236. unsigned int devmem_possible :1;
  237. unsigned int devmem_only :1;
  238. unsigned int allow_mixed :1;
  239. };
  240. int drm_gpusvm_init(struct drm_gpusvm *gpusvm,
  241. const char *name, struct drm_device *drm,
  242. struct mm_struct *mm,
  243. unsigned long mm_start, unsigned long mm_range,
  244. unsigned long notifier_size,
  245. const struct drm_gpusvm_ops *ops,
  246. const unsigned long *chunk_sizes, int num_chunks);
  247. void drm_gpusvm_fini(struct drm_gpusvm *gpusvm);
  248. void drm_gpusvm_free(struct drm_gpusvm *gpusvm);
  249. unsigned long
  250. drm_gpusvm_find_vma_start(struct drm_gpusvm *gpusvm,
  251. unsigned long start,
  252. unsigned long end);
  253. struct drm_gpusvm_range *
  254. drm_gpusvm_range_find_or_insert(struct drm_gpusvm *gpusvm,
  255. unsigned long fault_addr,
  256. unsigned long gpuva_start,
  257. unsigned long gpuva_end,
  258. const struct drm_gpusvm_ctx *ctx);
  259. void drm_gpusvm_range_remove(struct drm_gpusvm *gpusvm,
  260. struct drm_gpusvm_range *range);
  261. int drm_gpusvm_range_evict(struct drm_gpusvm *gpusvm,
  262. struct drm_gpusvm_range *range);
  263. struct drm_gpusvm_range *
  264. drm_gpusvm_range_get(struct drm_gpusvm_range *range);
  265. void drm_gpusvm_range_put(struct drm_gpusvm_range *range);
  266. bool drm_gpusvm_range_pages_valid(struct drm_gpusvm *gpusvm,
  267. struct drm_gpusvm_range *range);
  268. int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
  269. struct drm_gpusvm_range *range,
  270. const struct drm_gpusvm_ctx *ctx);
  271. void drm_gpusvm_range_unmap_pages(struct drm_gpusvm *gpusvm,
  272. struct drm_gpusvm_range *range,
  273. const struct drm_gpusvm_ctx *ctx);
  274. bool drm_gpusvm_has_mapping(struct drm_gpusvm *gpusvm, unsigned long start,
  275. unsigned long end);
  276. struct drm_gpusvm_notifier *
  277. drm_gpusvm_notifier_find(struct drm_gpusvm *gpusvm, unsigned long start,
  278. unsigned long end);
  279. struct drm_gpusvm_range *
  280. drm_gpusvm_range_find(struct drm_gpusvm_notifier *notifier, unsigned long start,
  281. unsigned long end);
  282. void drm_gpusvm_range_set_unmapped(struct drm_gpusvm_range *range,
  283. const struct mmu_notifier_range *mmu_range);
  284. int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
  285. struct drm_gpusvm_pages *svm_pages,
  286. struct mm_struct *mm,
  287. struct mmu_interval_notifier *notifier,
  288. unsigned long pages_start, unsigned long pages_end,
  289. const struct drm_gpusvm_ctx *ctx);
  290. void drm_gpusvm_unmap_pages(struct drm_gpusvm *gpusvm,
  291. struct drm_gpusvm_pages *svm_pages,
  292. unsigned long npages,
  293. const struct drm_gpusvm_ctx *ctx);
  294. void drm_gpusvm_free_pages(struct drm_gpusvm *gpusvm,
  295. struct drm_gpusvm_pages *svm_pages,
  296. unsigned long npages);
  297. /**
  298. * enum drm_gpusvm_scan_result - Scan result from the drm_gpusvm_scan_mm() function.
  299. * @DRM_GPUSVM_SCAN_UNPOPULATED: At least one page was not present or inaccessible.
  300. * @DRM_GPUSVM_SCAN_EQUAL: All pages belong to the struct dev_pagemap indicated as
  301. * the @pagemap argument to the drm_gpusvm_scan_mm() function.
  302. * @DRM_GPUSVM_SCAN_OTHER: All pages belong to exactly one dev_pagemap, which is
  303. * *NOT* the @pagemap argument to the drm_gpusvm_scan_mm(). All pages belong to
  304. * the same device private owner.
  305. * @DRM_GPUSVM_SCAN_SYSTEM: All pages are present and system pages.
  306. * @DRM_GPUSVM_SCAN_MIXED_DEVICE: All pages are device pages and belong to at least
  307. * two different struct dev_pagemaps. All pages belong to the same device private
  308. * owner.
  309. * @DRM_GPUSVM_SCAN_MIXED: Pages are present and are a mix of system pages
  310. * and device-private pages. All device-private pages belong to the same device
  311. * private owner.
  312. */
  313. enum drm_gpusvm_scan_result {
  314. DRM_GPUSVM_SCAN_UNPOPULATED,
  315. DRM_GPUSVM_SCAN_EQUAL,
  316. DRM_GPUSVM_SCAN_OTHER,
  317. DRM_GPUSVM_SCAN_SYSTEM,
  318. DRM_GPUSVM_SCAN_MIXED_DEVICE,
  319. DRM_GPUSVM_SCAN_MIXED,
  320. };
  321. enum drm_gpusvm_scan_result drm_gpusvm_scan_mm(struct drm_gpusvm_range *range,
  322. void *dev_private_owner,
  323. const struct dev_pagemap *pagemap);
  324. #ifdef CONFIG_LOCKDEP
  325. /**
  326. * drm_gpusvm_driver_set_lock() - Set the lock protecting accesses to GPU SVM
  327. * @gpusvm: Pointer to the GPU SVM structure.
  328. * @lock: the lock used to protect the gpuva list. The locking primitive
  329. * must contain a dep_map field.
  330. *
  331. * Call this to annotate drm_gpusvm_range_find_or_insert and
  332. * drm_gpusvm_range_remove.
  333. */
  334. #define drm_gpusvm_driver_set_lock(gpusvm, lock) \
  335. do { \
  336. if (!WARN((gpusvm)->lock_dep_map, \
  337. "GPUSVM range lock should be set only once."))\
  338. (gpusvm)->lock_dep_map = &(lock)->dep_map; \
  339. } while (0)
  340. #else
  341. #define drm_gpusvm_driver_set_lock(gpusvm, lock) do {} while (0)
  342. #endif
  343. /**
  344. * drm_gpusvm_notifier_lock() - Lock GPU SVM notifier
  345. * @gpusvm__: Pointer to the GPU SVM structure.
  346. *
  347. * Abstract client usage GPU SVM notifier lock, take lock
  348. */
  349. #define drm_gpusvm_notifier_lock(gpusvm__) \
  350. down_read(&(gpusvm__)->notifier_lock)
  351. /**
  352. * drm_gpusvm_notifier_unlock() - Unlock GPU SVM notifier
  353. * @gpusvm__: Pointer to the GPU SVM structure.
  354. *
  355. * Abstract client usage GPU SVM notifier lock, drop lock
  356. */
  357. #define drm_gpusvm_notifier_unlock(gpusvm__) \
  358. up_read(&(gpusvm__)->notifier_lock)
  359. /**
  360. * drm_gpusvm_range_start() - GPU SVM range start address
  361. * @range: Pointer to the GPU SVM range
  362. *
  363. * Return: GPU SVM range start address
  364. */
  365. static inline unsigned long
  366. drm_gpusvm_range_start(struct drm_gpusvm_range *range)
  367. {
  368. return range->itree.start;
  369. }
  370. /**
  371. * drm_gpusvm_range_end() - GPU SVM range end address
  372. * @range: Pointer to the GPU SVM range
  373. *
  374. * Return: GPU SVM range end address
  375. */
  376. static inline unsigned long
  377. drm_gpusvm_range_end(struct drm_gpusvm_range *range)
  378. {
  379. return range->itree.last + 1;
  380. }
  381. /**
  382. * drm_gpusvm_range_size() - GPU SVM range size
  383. * @range: Pointer to the GPU SVM range
  384. *
  385. * Return: GPU SVM range size
  386. */
  387. static inline unsigned long
  388. drm_gpusvm_range_size(struct drm_gpusvm_range *range)
  389. {
  390. return drm_gpusvm_range_end(range) - drm_gpusvm_range_start(range);
  391. }
  392. /**
  393. * drm_gpusvm_notifier_start() - GPU SVM notifier start address
  394. * @notifier: Pointer to the GPU SVM notifier
  395. *
  396. * Return: GPU SVM notifier start address
  397. */
  398. static inline unsigned long
  399. drm_gpusvm_notifier_start(struct drm_gpusvm_notifier *notifier)
  400. {
  401. return notifier->itree.start;
  402. }
  403. /**
  404. * drm_gpusvm_notifier_end() - GPU SVM notifier end address
  405. * @notifier: Pointer to the GPU SVM notifier
  406. *
  407. * Return: GPU SVM notifier end address
  408. */
  409. static inline unsigned long
  410. drm_gpusvm_notifier_end(struct drm_gpusvm_notifier *notifier)
  411. {
  412. return notifier->itree.last + 1;
  413. }
  414. /**
  415. * drm_gpusvm_notifier_size() - GPU SVM notifier size
  416. * @notifier: Pointer to the GPU SVM notifier
  417. *
  418. * Return: GPU SVM notifier size
  419. */
  420. static inline unsigned long
  421. drm_gpusvm_notifier_size(struct drm_gpusvm_notifier *notifier)
  422. {
  423. return drm_gpusvm_notifier_end(notifier) -
  424. drm_gpusvm_notifier_start(notifier);
  425. }
  426. /**
  427. * __drm_gpusvm_range_next() - Get the next GPU SVM range in the list
  428. * @range: a pointer to the current GPU SVM range
  429. *
  430. * Return: A pointer to the next drm_gpusvm_range if available, or NULL if the
  431. * current range is the last one or if the input range is NULL.
  432. */
  433. static inline struct drm_gpusvm_range *
  434. __drm_gpusvm_range_next(struct drm_gpusvm_range *range)
  435. {
  436. if (range && !list_is_last(&range->entry,
  437. &range->notifier->range_list))
  438. return list_next_entry(range, entry);
  439. return NULL;
  440. }
  441. /**
  442. * drm_gpusvm_for_each_range() - Iterate over GPU SVM ranges in a notifier
  443. * @range__: Iterator variable for the ranges. If set, it indicates the start of
  444. * the iterator. If NULL, call drm_gpusvm_range_find() to get the range.
  445. * @notifier__: Pointer to the GPU SVM notifier
  446. * @start__: Start address of the range
  447. * @end__: End address of the range
  448. *
  449. * This macro is used to iterate over GPU SVM ranges in a notifier. It is safe
  450. * to use while holding the driver SVM lock or the notifier lock.
  451. */
  452. #define drm_gpusvm_for_each_range(range__, notifier__, start__, end__) \
  453. for ((range__) = (range__) ?: \
  454. drm_gpusvm_range_find((notifier__), (start__), (end__)); \
  455. (range__) && (drm_gpusvm_range_start(range__) < (end__)); \
  456. (range__) = __drm_gpusvm_range_next(range__))
  457. /**
  458. * drm_gpusvm_for_each_range_safe() - Safely iterate over GPU SVM ranges in a notifier
  459. * @range__: Iterator variable for the ranges
  460. * @next__: Iterator variable for the ranges temporay storage
  461. * @notifier__: Pointer to the GPU SVM notifier
  462. * @start__: Start address of the range
  463. * @end__: End address of the range
  464. *
  465. * This macro is used to iterate over GPU SVM ranges in a notifier while
  466. * removing ranges from it.
  467. */
  468. #define drm_gpusvm_for_each_range_safe(range__, next__, notifier__, start__, end__) \
  469. for ((range__) = drm_gpusvm_range_find((notifier__), (start__), (end__)), \
  470. (next__) = __drm_gpusvm_range_next(range__); \
  471. (range__) && (drm_gpusvm_range_start(range__) < (end__)); \
  472. (range__) = (next__), (next__) = __drm_gpusvm_range_next(range__))
  473. /**
  474. * __drm_gpusvm_notifier_next() - get the next drm_gpusvm_notifier in the list
  475. * @notifier: a pointer to the current drm_gpusvm_notifier
  476. *
  477. * Return: A pointer to the next drm_gpusvm_notifier if available, or NULL if
  478. * the current notifier is the last one or if the input notifier is
  479. * NULL.
  480. */
  481. static inline struct drm_gpusvm_notifier *
  482. __drm_gpusvm_notifier_next(struct drm_gpusvm_notifier *notifier)
  483. {
  484. if (notifier && !list_is_last(&notifier->entry,
  485. &notifier->gpusvm->notifier_list))
  486. return list_next_entry(notifier, entry);
  487. return NULL;
  488. }
  489. /**
  490. * drm_gpusvm_for_each_notifier() - Iterate over GPU SVM notifiers in a gpusvm
  491. * @notifier__: Iterator variable for the notifiers
  492. * @gpusvm__: Pointer to the GPU SVM notifier
  493. * @start__: Start address of the notifier
  494. * @end__: End address of the notifier
  495. *
  496. * This macro is used to iterate over GPU SVM notifiers in a gpusvm.
  497. */
  498. #define drm_gpusvm_for_each_notifier(notifier__, gpusvm__, start__, end__) \
  499. for ((notifier__) = drm_gpusvm_notifier_find((gpusvm__), (start__), (end__)); \
  500. (notifier__) && (drm_gpusvm_notifier_start(notifier__) < (end__)); \
  501. (notifier__) = __drm_gpusvm_notifier_next(notifier__))
  502. /**
  503. * drm_gpusvm_for_each_notifier_safe() - Safely iterate over GPU SVM notifiers in a gpusvm
  504. * @notifier__: Iterator variable for the notifiers
  505. * @next__: Iterator variable for the notifiers temporay storage
  506. * @gpusvm__: Pointer to the GPU SVM notifier
  507. * @start__: Start address of the notifier
  508. * @end__: End address of the notifier
  509. *
  510. * This macro is used to iterate over GPU SVM notifiers in a gpusvm while
  511. * removing notifiers from it.
  512. */
  513. #define drm_gpusvm_for_each_notifier_safe(notifier__, next__, gpusvm__, start__, end__) \
  514. for ((notifier__) = drm_gpusvm_notifier_find((gpusvm__), (start__), (end__)), \
  515. (next__) = __drm_gpusvm_notifier_next(notifier__); \
  516. (notifier__) && (drm_gpusvm_notifier_start(notifier__) < (end__)); \
  517. (notifier__) = (next__), (next__) = __drm_gpusvm_notifier_next(notifier__))
  518. #endif /* __DRM_GPUSVM_H__ */