summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2026-07-17 10:40:39 +1000
committerDave Airlie <airlied@redhat.com>2026-07-17 10:41:02 +1000
commit2e33bfe53cba8558eb83f3fd327d0a5e21172baa (patch)
tree3db3d70d73a6f39d4fbef9482989954a8e4bd696 /include
parent295a8c0b0e44760ef7e06c55beacbe0caafe1ce7 (diff)
parentec6444a00c49e6c2b5e9a507272a28126677f9ee (diff)
downloadlinux-stable-2e33bfe53cba8558eb83f3fd327d0a5e21172baa.tar.gz
linux-stable-2e33bfe53cba8558eb83f3fd327d0a5e21172baa.zip
Merge tag 'drm-misc-next-2026-07-16' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-next
drm-misc-next for 7.3: UAPI Changes: Cross-subsystem Changes: Core Changes: - blend: allow blend mode property without PREMULTI - bridges: - Rename drm_for_each_bridge_in_chain_scoped to drm_for_each_bridge_in_chain - Drop legacy bridges support - gpusvm: Code reorganization to give drivers more flexibility Driver Changes: - etnaviv: Check if a reset has been successful - nouveau: Create instmem iomapping at first use - panthor: Remove redundant cleanup - qxl: Convert to a simple encoder to a regular one - bridges: - Convert all remaining legacy bridges to atomic - tc358767: clamp the reported AUX read size to the request - panels: - novatek-nt37801: Use mipi_dsi_*_multi() functions - samsung-s6d16d0: Fix prepare error handling Signed-off-by: Dave Airlie <airlied@redhat.com> From: Maxime Ripard <mripard@redhat.com> Link: https://patch.msgid.link/20260716-famous-pastel-ostrich-a1aaef@houat
Diffstat (limited to 'include')
-rw-r--r--include/drm/drm_bridge.h114
-rw-r--r--include/drm/drm_gpusvm.h67
2 files changed, 52 insertions, 129 deletions
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 18f3db367dc1..3ac84ed57ab2 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -173,52 +173,6 @@ struct drm_bridge_funcs {
bool (*mode_fixup)(struct drm_bridge *bridge,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode);
- /**
- * @disable:
- *
- * This callback should disable the bridge. It is called right before
- * the preceding element in the display pipe is disabled. If the
- * preceding element is a bridge this means it's called before that
- * bridge's @disable vfunc. If the preceding element is a &drm_encoder
- * it's called right before the &drm_encoder_helper_funcs.disable,
- * &drm_encoder_helper_funcs.prepare or &drm_encoder_helper_funcs.dpms
- * hook.
- *
- * The bridge can assume that the display pipe (i.e. clocks and timing
- * signals) feeding it is still running when this callback is called.
- *
- * The @disable callback is optional.
- *
- * NOTE:
- *
- * This is deprecated, do not use!
- * New drivers shall use &drm_bridge_funcs.atomic_disable.
- */
- void (*disable)(struct drm_bridge *bridge);
-
- /**
- * @post_disable:
- *
- * This callback should disable the bridge. It is called right after the
- * preceding element in the display pipe is disabled. If the preceding
- * element is a bridge this means it's called after that bridge's
- * @post_disable function. If the preceding element is a &drm_encoder
- * it's called right after the encoder's
- * &drm_encoder_helper_funcs.disable, &drm_encoder_helper_funcs.prepare
- * or &drm_encoder_helper_funcs.dpms hook.
- *
- * The bridge must assume that the display pipe (i.e. clocks and timing
- * signals) feeding it is no longer running when this callback is
- * called.
- *
- * The @post_disable callback is optional.
- *
- * NOTE:
- *
- * This is deprecated, do not use!
- * New drivers shall use &drm_bridge_funcs.atomic_post_disable.
- */
- void (*post_disable)(struct drm_bridge *bridge);
/**
* @mode_set:
@@ -249,55 +203,6 @@ struct drm_bridge_funcs {
void (*mode_set)(struct drm_bridge *bridge,
const struct drm_display_mode *mode,
const struct drm_display_mode *adjusted_mode);
- /**
- * @pre_enable:
- *
- * This callback should enable the bridge. It is called right before
- * the preceding element in the display pipe is enabled. If the
- * preceding element is a bridge this means it's called before that
- * bridge's @pre_enable function. If the preceding element is a
- * &drm_encoder it's called right before the encoder's
- * &drm_encoder_helper_funcs.enable, &drm_encoder_helper_funcs.commit or
- * &drm_encoder_helper_funcs.dpms hook.
- *
- * The display pipe (i.e. clocks and timing signals) feeding this bridge
- * will not yet be running when this callback is called. The bridge must
- * not enable the display link feeding the next bridge in the chain (if
- * there is one) when this callback is called.
- *
- * The @pre_enable callback is optional.
- *
- * NOTE:
- *
- * This is deprecated, do not use!
- * New drivers shall use &drm_bridge_funcs.atomic_pre_enable.
- */
- void (*pre_enable)(struct drm_bridge *bridge);
-
- /**
- * @enable:
- *
- * This callback should enable the bridge. It is called right after
- * the preceding element in the display pipe is enabled. If the
- * preceding element is a bridge this means it's called after that
- * bridge's @enable function. If the preceding element is a
- * &drm_encoder it's called right after the encoder's
- * &drm_encoder_helper_funcs.enable, &drm_encoder_helper_funcs.commit or
- * &drm_encoder_helper_funcs.dpms hook.
- *
- * The bridge can assume that the display pipe (i.e. clocks and timing
- * signals) feeding it is running when this callback is called. This
- * callback must enable the display link feeding the next bridge in the
- * chain if there is one.
- *
- * The @enable callback is optional.
- *
- * NOTE:
- *
- * This is deprecated, do not use!
- * New drivers shall use &drm_bridge_funcs.atomic_enable.
- */
- void (*enable)(struct drm_bridge *bridge);
/**
* @atomic_pre_enable:
@@ -1359,14 +1264,6 @@ drm_bridge_get_current_state(struct drm_bridge *bridge)
if (!bridge)
return NULL;
- /*
- * Only atomic bridges will have bridge->base initialized by
- * drm_atomic_private_obj_init(), so we need to make sure we're
- * working with one before we try to use the lock.
- */
- if (!bridge->funcs || !bridge->funcs->atomic_create_state)
- return NULL;
-
drm_modeset_lock_assert_held(&bridge->base.lock);
if (!bridge->base.state)
@@ -1474,9 +1371,9 @@ static inline struct drm_bridge *__drm_for_each_bridge_in_chain_next(struct drm_
DEFINE_FREE(__drm_for_each_bridge_in_chain_cleanup, struct drm_bridge *,
if (_T) { mutex_unlock(&_T->encoder->bridge_chain_mutex); drm_bridge_put(_T); })
-/* Internal to drm_for_each_bridge_in_chain_scoped() */
+/* Internal to drm_for_each_bridge_in_chain() */
static inline struct drm_bridge *
-__drm_for_each_bridge_in_chain_scoped_start(struct drm_encoder *encoder)
+__drm_for_each_bridge_in_chain_start(struct drm_encoder *encoder)
{
mutex_lock(&encoder->bridge_chain_mutex);
@@ -1489,8 +1386,7 @@ __drm_for_each_bridge_in_chain_scoped_start(struct drm_encoder *encoder)
}
/**
- * drm_for_each_bridge_in_chain_scoped - iterate over all bridges attached
- * to an encoder
+ * drm_for_each_bridge_in_chain - iterate over all bridges attached to an encoder
* @encoder: the encoder to iterate bridges on
* @bridge: a bridge pointer updated to point to the current bridge at each
* iteration
@@ -1500,9 +1396,9 @@ __drm_for_each_bridge_in_chain_scoped_start(struct drm_encoder *encoder)
* Automatically gets/puts the bridge reference while iterating and locks
* the encoder chain mutex to prevent chain modifications while iterating.
*/
-#define drm_for_each_bridge_in_chain_scoped(encoder, bridge) \
+#define drm_for_each_bridge_in_chain(encoder, bridge) \
for (struct drm_bridge *bridge __free(__drm_for_each_bridge_in_chain_cleanup) = \
- __drm_for_each_bridge_in_chain_scoped_start((encoder)); \
+ __drm_for_each_bridge_in_chain_start((encoder)); \
bridge; \
bridge = __drm_for_each_bridge_in_chain_next(bridge)) \
diff --git a/include/drm/drm_gpusvm.h b/include/drm/drm_gpusvm.h
index 8a4d7134a9a7..b7d987bf76aa 100644
--- a/include/drm/drm_gpusvm.h
+++ b/include/drm/drm_gpusvm.h
@@ -109,9 +109,7 @@ struct drm_gpusvm_notifier {
/**
* struct drm_gpusvm_pages_flags - Structure representing a GPU SVM pages flags
*
- * @migrate_devmem: Flag indicating whether the pages can be migrated to device memory
* @unmapped: Flag indicating if the pages has been unmapped
- * @partial_unmap: Flag indicating if the pages has been partially unmapped
* @has_devmem_pages: Flag indicating if the pages has devmem pages
* @has_dma_mapping: Flag indicating if the pages has a DMA mapping
* @__flags: Flags for pages in u16 form (used for READ_ONCE)
@@ -119,11 +117,8 @@ struct drm_gpusvm_notifier {
struct drm_gpusvm_pages_flags {
union {
struct {
- /* All flags below must be set upon creation */
- u16 migrate_devmem : 1;
/* All flags below must be set / cleared under notifier lock */
u16 unmapped : 1;
- u16 partial_unmap : 1;
u16 has_devmem_pages : 1;
u16 has_dma_mapping : 1;
};
@@ -134,6 +129,7 @@ struct drm_gpusvm_pages_flags {
/**
* struct drm_gpusvm_pages - Structure representing a GPU SVM mapped pages
*
+ * @drm: The DRM device that owns the dma mappings
* @dma_addr: Device address array
* @dpagemap: The struct drm_pagemap of the device pages we're dma-mapping.
* Note this is assuming only one drm_pagemap per range is allowed.
@@ -143,6 +139,7 @@ struct drm_gpusvm_pages_flags {
* @flags: Flags for the range; see &struct drm_gpusvm_pages_flags
*/
struct drm_gpusvm_pages {
+ struct drm_device *drm;
struct drm_pagemap_addr *dma_addr;
struct drm_pagemap *dpagemap;
struct dma_iova_state state;
@@ -152,6 +149,27 @@ struct drm_gpusvm_pages {
};
/**
+ * struct drm_gpusvm_range_flags - Range-level GPU SVM flags
+ *
+ * @migrate_devmem: Flag indicating whether the range can be migrated to device memory
+ * @unmapped: Flag indicating if the range has been unmapped
+ * @partial_unmap: Flag indicating if the range has been partially unmapped
+ * @__flags: All flags in u16 form (used for READ_ONCE)
+ */
+struct drm_gpusvm_range_flags {
+ union {
+ struct {
+ /* All flags below must be set upon creation */
+ u16 migrate_devmem : 1;
+ /* All flags below must be set / cleared under notifier lock */
+ u16 unmapped : 1;
+ u16 partial_unmap : 1;
+ };
+ u16 __flags;
+ };
+};
+
+/**
* struct drm_gpusvm_range - Structure representing a GPU SVM range
*
* @gpusvm: Pointer to the GPU SVM structure
@@ -159,7 +177,7 @@ struct drm_gpusvm_pages {
* @refcount: Reference count for the range
* @itree: Interval tree node for the range (inserted in GPU SVM notifier)
* @entry: List entry to fast interval tree traversal
- * @pages: The pages for this range.
+ * @flags: Flags for range see &struct drm_gpusvm_range_flags
*
* This structure represents a GPU SVM range used for tracking memory ranges
* mapped in a DRM device.
@@ -170,14 +188,13 @@ struct drm_gpusvm_range {
struct kref refcount;
struct interval_tree_node itree;
struct list_head entry;
- struct drm_gpusvm_pages pages;
+ struct drm_gpusvm_range_flags flags;
};
/**
* struct drm_gpusvm - GPU SVM structure
*
* @name: Name of the GPU SVM
- * @drm: Pointer to the DRM device structure
* @mm: Pointer to the mm_struct for the address space
* @mm_start: Start address of GPU SVM
* @mm_range: Range of the GPU SVM
@@ -201,7 +218,6 @@ struct drm_gpusvm_range {
*/
struct drm_gpusvm {
const char *name;
- struct drm_device *drm;
struct mm_struct *mm;
unsigned long mm_start;
unsigned long mm_range;
@@ -253,7 +269,7 @@ struct drm_gpusvm_ctx {
};
int drm_gpusvm_init(struct drm_gpusvm *gpusvm,
- const char *name, struct drm_device *drm,
+ const char *name,
struct mm_struct *mm,
unsigned long mm_start, unsigned long mm_range,
unsigned long notifier_size,
@@ -287,16 +303,8 @@ drm_gpusvm_range_get(struct drm_gpusvm_range *range);
void drm_gpusvm_range_put(struct drm_gpusvm_range *range);
-bool drm_gpusvm_range_pages_valid(struct drm_gpusvm *gpusvm,
- struct drm_gpusvm_range *range);
-
-int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
- struct drm_gpusvm_range *range,
- const struct drm_gpusvm_ctx *ctx);
-
-void drm_gpusvm_range_unmap_pages(struct drm_gpusvm *gpusvm,
- struct drm_gpusvm_range *range,
- const struct drm_gpusvm_ctx *ctx);
+bool drm_gpusvm_pages_valid(struct drm_gpusvm *gpusvm,
+ struct drm_gpusvm_pages *svm_pages);
bool drm_gpusvm_has_mapping(struct drm_gpusvm *gpusvm, unsigned long start,
unsigned long end);
@@ -310,6 +318,8 @@ drm_gpusvm_range_find(struct drm_gpusvm_notifier *notifier, unsigned long start,
unsigned long end);
void drm_gpusvm_range_set_unmapped(struct drm_gpusvm_range *range,
+ struct drm_gpusvm_pages *pages,
+ unsigned int pages_count,
const struct mmu_notifier_range *mmu_range);
int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
@@ -329,6 +339,23 @@ void drm_gpusvm_free_pages(struct drm_gpusvm *gpusvm,
unsigned long npages);
/**
+ * drm_gpusvm_init_pages() - Initialize a freshly allocated drm_gpusvm_pages
+ * @svm_pages: Pointer to the drm_gpusvm_pages to initialize.
+ * @drm: The DRM device that will own DMA mappings for this pages object.
+ *
+ * Drivers that embed one or more drm_gpusvm_pages in their own range
+ * structure must call this once on each pages instance after allocation,
+ * before the first drm_gpusvm_get_pages() / unmap / free.
+ */
+static inline void drm_gpusvm_init_pages(struct drm_gpusvm_pages *svm_pages,
+ struct drm_device *drm)
+{
+ memset(svm_pages, 0, sizeof(*svm_pages));
+ svm_pages->drm = drm;
+ svm_pages->notifier_seq = LONG_MAX;
+}
+
+/**
* enum drm_gpusvm_scan_result - Scan result from the drm_gpusvm_scan_mm() function.
* @DRM_GPUSVM_SCAN_UNPOPULATED: At least one page was not present or inaccessible.
* @DRM_GPUSVM_SCAN_EQUAL: All pages belong to the struct dev_pagemap indicated as