summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/drm/drmP.h14
-rw-r--r--include/drm/drm_atomic.h31
-rw-r--r--include/drm/drm_atomic_helper.h3
-rw-r--r--include/drm/drm_auth.h17
-rw-r--r--include/drm/drm_bridge.h46
-rw-r--r--include/drm/drm_connector.h91
-rw-r--r--include/drm/drm_crtc.h31
-rw-r--r--include/drm/drm_drv.h34
-rw-r--r--include/drm/drm_encoder.h7
-rw-r--r--include/drm/drm_encoder_slave.h1
-rw-r--r--include/drm/drm_fb_cma_helper.h5
-rw-r--r--include/drm/drm_fb_helper.h5
-rw-r--r--include/drm/drm_framebuffer.h33
-rw-r--r--include/drm/drm_gem_cma_helper.h17
-rw-r--r--include/drm/drm_irq.h4
-rw-r--r--include/drm/drm_mm.h373
-rw-r--r--include/drm/drm_mode_config.h20
-rw-r--r--include/drm/drm_modeset_helper.h3
-rw-r--r--include/drm/drm_modeset_helper_vtables.h3
-rw-r--r--include/drm/drm_plane.h4
-rw-r--r--include/drm/drm_print.h24
-rw-r--r--include/drm/drm_simple_kms_helper.h10
-rw-r--r--include/drm/i915_pciids.h21
-rw-r--r--include/drm/intel-gtt.h6
-rw-r--r--include/linux/dma-buf.h224
-rw-r--r--include/linux/dma-fence.h52
-rw-r--r--include/linux/kref.h2
-rw-r--r--include/linux/prime_numbers.h37
-rw-r--r--include/linux/reservation.h34
-rw-r--r--include/uapi/drm/Kbuild1
-rw-r--r--include/uapi/drm/drm_fourcc.h11
-rw-r--r--include/uapi/drm/i915_drm.h135
32 files changed, 1016 insertions, 283 deletions
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 192016e2b518..9af3bb14641f 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -360,6 +360,7 @@ struct drm_ioctl_desc {
/* Event queued up for userspace to read */
struct drm_pending_event {
struct completion *completion;
+ void (*completion_release)(struct completion *completion);
struct drm_event *event;
struct dma_fence *fence;
struct list_head link;
@@ -634,6 +635,19 @@ struct drm_device {
int switch_power_state;
};
+/**
+ * drm_drv_uses_atomic_modeset - check if the driver implements
+ * atomic_commit()
+ * @dev: DRM device
+ *
+ * This check is useful if drivers do not have DRIVER_ATOMIC set but
+ * have atomic modesetting internally implemented.
+ */
+static inline bool drm_drv_uses_atomic_modeset(struct drm_device *dev)
+{
+ return dev->mode_config.funcs->atomic_commit != NULL;
+}
+
#include <drm/drm_irq.h>
#define DRM_SWITCH_POWER_ON 0
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index d6d241f63b9f..f96220ed4004 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -145,6 +145,7 @@ struct __drm_crtcs_state {
struct drm_crtc_state *state;
struct drm_crtc_commit *commit;
s64 __user *out_fence_ptr;
+ unsigned last_vblank_count;
};
struct __drm_connnectors_state {
@@ -188,12 +189,31 @@ struct drm_atomic_state {
struct work_struct commit_work;
};
-void drm_crtc_commit_put(struct drm_crtc_commit *commit);
+void __drm_crtc_commit_free(struct kref *kref);
+
+/**
+ * drm_crtc_commit_get - acquire a reference to the CRTC commit
+ * @commit: CRTC commit
+ *
+ * Increases the reference of @commit.
+ */
static inline void drm_crtc_commit_get(struct drm_crtc_commit *commit)
{
kref_get(&commit->ref);
}
+/**
+ * drm_crtc_commit_put - release a reference to the CRTC commmit
+ * @commit: CRTC commit
+ *
+ * This releases a reference to @commit which is freed after removing the
+ * final reference. No locking required and callable from any context.
+ */
+static inline void drm_crtc_commit_put(struct drm_crtc_commit *commit)
+{
+ kref_put(&commit->ref, __drm_crtc_commit_free);
+}
+
struct drm_atomic_state * __must_check
drm_atomic_state_alloc(struct drm_device *dev);
void drm_atomic_state_clear(struct drm_atomic_state *state);
@@ -369,12 +389,6 @@ int __must_check drm_atomic_nonblocking_commit(struct drm_atomic_state *state);
void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
-#ifdef CONFIG_DEBUG_FS
-struct drm_minor;
-int drm_atomic_debugfs_init(struct drm_minor *minor);
-int drm_atomic_debugfs_cleanup(struct drm_minor *minor);
-#endif
-
#define for_each_connector_in_state(__state, connector, connector_state, __i) \
for ((__i) = 0; \
(__i) < (__state)->num_connector && \
@@ -403,7 +417,7 @@ int drm_atomic_debugfs_cleanup(struct drm_minor *minor);
* drm_atomic_crtc_needs_modeset - compute combined modeset need
* @state: &drm_crtc_state for the CRTC
*
- * To give drivers flexibility struct &drm_crtc_state has 3 booleans to track
+ * To give drivers flexibility &struct drm_crtc_state has 3 booleans to track
* whether the state CRTC changed enough to need a full modeset cycle:
* connectors_changed, mode_changed and active_changed. This helper simply
* combines these three to compute the overall need for a modeset for @state.
@@ -424,5 +438,4 @@ drm_atomic_crtc_needs_modeset(const struct drm_crtc_state *state)
state->connectors_changed;
}
-
#endif /* DRM_ATOMIC_H_ */
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index 7ff92b09fd9c..4b2353dc34ba 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -48,9 +48,6 @@ int drm_atomic_helper_commit(struct drm_device *dev,
int drm_atomic_helper_wait_for_fences(struct drm_device *dev,
struct drm_atomic_state *state,
bool pre_swap);
-bool drm_atomic_helper_framebuffer_changed(struct drm_device *dev,
- struct drm_atomic_state *old_state,
- struct drm_crtc *crtc);
void drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
struct drm_atomic_state *old_state);
diff --git a/include/drm/drm_auth.h b/include/drm/drm_auth.h
index 610223b0481b..eecbc2f43f55 100644
--- a/include/drm/drm_auth.h
+++ b/include/drm/drm_auth.h
@@ -33,10 +33,7 @@
*
* @refcount: Refcount for this master object.
* @dev: Link back to the DRM device
- * @unique: Unique identifier: e.g. busid. Protected by drm_global_mutex.
- * @unique_len: Length of unique field. Protected by drm_global_mutex.
- * @magic_map: Map of used authentication tokens. Protected by struct_mutex.
- * @lock: DRI lock information.
+ * @lock: DRI1 lock information.
* @driver_priv: Pointer to driver-private information.
*
* Note that master structures are only relevant for the legacy/primary device
@@ -45,8 +42,20 @@
struct drm_master {
struct kref refcount;
struct drm_device *dev;
+ /**
+ * @unique: Unique identifier: e.g. busid. Protected by struct
+ * &drm_device master_mutex.
+ */
char *unique;
+ /**
+ * @unique_len: Length of unique field. Protected by &struct drm_device
+ * master_mutex.
+ */
int unique_len;
+ /**
+ * @magic_map: Map of used authentication tokens. Protected by struct
+ * &drm_device master_mutex.
+ */
struct idr magic_map;
struct drm_lock_data lock;
void *driver_priv;
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 530a1d6e8cde..fdd82fcbf168 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -96,9 +96,10 @@ struct drm_bridge_funcs {
* 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() function. If the preceding element is a
- * &drm_encoder it's called right before the encoder's ->disable(),
- * ->prepare() or ->dpms() hook from struct &drm_encoder_helper_funcs.
+ * 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.
@@ -110,12 +111,13 @@ struct drm_bridge_funcs {
/**
* @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 ->disable(),
- * ->prepare() or ->dpms() hook from struct &drm_encoder_helper_funcs.
+ * 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
* singals) feeding it is no longer running when this callback is
@@ -129,9 +131,11 @@ struct drm_bridge_funcs {
* @mode_set:
*
* This callback should set the given mode on the bridge. It is called
- * after the ->mode_set() callback for the preceding element in the
- * display pipeline has been called already. The display pipe (i.e.
- * clocks and timing signals) is off when this function is called.
+ * after the @mode_set callback for the preceding element in the display
+ * pipeline has been called already. If the bridge is the first element
+ * then this would be &drm_encoder_helper_funcs.mode_set. The display
+ * pipe (i.e. clocks and timing signals) is off when this function is
+ * called.
*/
void (*mode_set)(struct drm_bridge *bridge,
struct drm_display_mode *mode,
@@ -142,9 +146,10 @@ struct drm_bridge_funcs {
* 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 ->enable(),
- * ->commit() or ->dpms() hook from struct &drm_encoder_helper_funcs.
+ * 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
@@ -161,9 +166,10 @@ struct drm_bridge_funcs {
* 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 ->enable(),
- * ->commit() or ->dpms() hook from struct &drm_encoder_helper_funcs.
+ * 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
@@ -201,8 +207,8 @@ struct drm_bridge {
int drm_bridge_add(struct drm_bridge *bridge);
void drm_bridge_remove(struct drm_bridge *bridge);
struct drm_bridge *of_drm_find_bridge(struct device_node *np);
-int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge);
-void drm_bridge_detach(struct drm_bridge *bridge);
+int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
+ struct drm_bridge *previous);
bool drm_bridge_mode_fixup(struct drm_bridge *bridge,
const struct drm_display_mode *mode,
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index a9b95246e26e..d489cc003b7e 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -94,7 +94,7 @@ enum subpixel_order {
*
* Describes a given display (e.g. CRT or flat panel) and its limitations. For
* fixed display sinks like built-in panels there's not much difference between
- * this and struct &drm_connector. But for sinks with a real cable this
+ * this and &struct drm_connector. But for sinks with a real cable this
* structure is meant to describe all the things at the other end of the cable.
*
* For sinks which provide an EDID this can be filled out by calling
@@ -117,7 +117,7 @@ struct drm_display_info {
/**
* @pixel_clock: Maximum pixel clock supported by the sink, in units of
- * 100Hz. This mismatches the clok in &drm_display_mode (which is in
+ * 100Hz. This mismatches the clock in &drm_display_mode (which is in
* kHZ), because that's what the EDID uses as base unit.
*/
unsigned int pixel_clock;
@@ -381,6 +381,8 @@ struct drm_connector_funcs {
* core drm connector interfaces. Everything added from this callback
* should be unregistered in the early_unregister callback.
*
+ * This is called while holding drm_connector->mutex.
+ *
* Returns:
*
* 0 on success, or a negative error code on failure.
@@ -395,6 +397,8 @@ struct drm_connector_funcs {
* late_register(). It is called from drm_connector_unregister(),
* early in the driver unload sequence to disable userspace access
* before data structures are torndown.
+ *
+ * This is called while holding drm_connector->mutex.
*/
void (*early_unregister)(struct drm_connector *connector);
@@ -418,7 +422,7 @@ struct drm_connector_funcs {
* &drm_mode_config_funcs) will be cleaned up by calling the
* @atomic_destroy_state hook in this structure.
*
- * Atomic drivers which don't subclass struct &drm_connector_state should use
+ * Atomic drivers which don't subclass &struct drm_connector_state should use
* drm_atomic_helper_connector_duplicate_state(). Drivers that subclass the
* state structure to extend it with driver-private state should use
* __drm_atomic_helper_connector_duplicate_state() to make sure shared state is
@@ -521,7 +525,7 @@ struct drm_connector_funcs {
/**
* @atomic_print_state:
*
- * If driver subclasses struct &drm_connector_state, it should implement
+ * If driver subclasses &struct drm_connector_state, it should implement
* this optional hook for printing additional driver specific state.
*
* Do not call this directly, use drm_atomic_connector_print_state()
@@ -559,10 +563,6 @@ struct drm_cmdline_mode {
* @interlace_allowed: can this connector handle interlaced modes?
* @doublescan_allowed: can this connector handle doublescan?
* @stereo_allowed: can this connector handle stereo modes?
- * @registered: is this connector exposed (registered) with userspace?
- * @modes: modes available on this connector (from fill_modes() + user)
- * @status: one of the drm_connector_status enums (connected, not, or unknown)
- * @probed_modes: list of modes derived directly from the display
* @funcs: connector control functions
* @edid_blob_ptr: DRM property containing EDID if present
* @properties: property tracking for this connector
@@ -608,6 +608,13 @@ struct drm_connector {
char *name;
/**
+ * @mutex: Lock for general connector state, but currently only protects
+ * @registered. Most of the connector state is still protected by the
+ * mutex in &drm_mode_config.
+ */
+ struct mutex mutex;
+
+ /**
* @index: Compacted connector index, which matches the position inside
* the mode_config.list for drivers not supporting hot-add/removing. Can
* be used as an array index. It is invariant over the lifetime of the
@@ -620,12 +627,32 @@ struct drm_connector {
bool interlace_allowed;
bool doublescan_allowed;
bool stereo_allowed;
+ /**
+ * @registered: Is this connector exposed (registered) with userspace?
+ * Protected by @mutex.
+ */
bool registered;
+
+ /**
+ * @modes:
+ * Modes available on this connector (from fill_modes() + user).
+ * Protected by dev->mode_config.mutex.
+ */
struct list_head modes; /* list of modes on this connector */
+ /**
+ * @status:
+ * One of the drm_connector_status enums (connected, not, or unknown).
+ * Protected by dev->mode_config.mutex.
+ */
enum drm_connector_status status;
- /* these are modes added by probing with DDC or the BIOS */
+ /**
+ * @probed_modes:
+ * These are modes added by probing with DDC or the BIOS, before
+ * filtering is applied. Used by the probe helpers.Protected by
+ * dev->mode_config.mutex.
+ */
struct list_head probed_modes;
/**
@@ -634,6 +661,8 @@ struct drm_connector {
* flat panels in embedded systems, the driver should initialize the
* display_info.width_mm and display_info.height_mm fields with the
* physical size of the display.
+ *
+ * Protected by dev->mode_config.mutex.
*/
struct drm_display_info display_info;
const struct drm_connector_funcs *funcs;
@@ -839,12 +868,46 @@ void drm_mode_put_tile_group(struct drm_device *dev,
* @dev: the DRM device
*
* Iterate over all connectors of @dev.
+ *
+ * WARNING:
+ *
+ * This iterator is not safe against hotadd/removal of connectors and is
+ * deprecated. Use drm_for_each_connector_iter() instead.
*/
#define drm_for_each_connector(connector, dev) \
- for (assert_drm_connector_list_read_locked(&(dev)->mode_config), \
- connector = list_first_entry(&(dev)->mode_config.connector_list, \
- struct drm_connector, head); \
- &connector->head != (&(dev)->mode_config.connector_list); \
- connector = list_next_entry(connector, head))
+ list_for_each_entry(connector, &(dev)->mode_config.connector_list, head)
+
+/**
+ * struct drm_connector_list_iter - connector_list iterator
+ *
+ * This iterator tracks state needed to be able to walk the connector_list
+ * within struct drm_mode_config. Only use together with
+ * drm_connector_list_iter_get(), drm_connector_list_iter_put() and
+ * drm_connector_list_iter_next() respectively the convenience macro
+ * drm_for_each_connector_iter().
+ */
+struct drm_connector_list_iter {
+/* private: */
+ struct drm_device *dev;
+ struct drm_connector *conn;
+};
+
+void drm_connector_list_iter_get(struct drm_device *dev,
+ struct drm_connector_list_iter *iter);
+struct drm_connector *
+drm_connector_list_iter_next(struct drm_connector_list_iter *iter);
+void drm_connector_list_iter_put(struct drm_connector_list_iter *iter);
+
+/**
+ * drm_for_each_connector_iter - connector_list iterator macro
+ * @connector: &struct drm_connector pointer used as cursor
+ * @iter: &struct drm_connector_list_iter
+ *
+ * Note that @connector is only valid within the list body, if you want to use
+ * @connector after calling drm_connector_list_iter_put() then you need to grab
+ * your own reference first using drm_connector_reference().
+ */
+#define drm_for_each_connector_iter(connector, iter) \
+ while ((connector = drm_connector_list_iter_next(iter)))
#endif
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 946672f97e1e..17c9f52d6ecb 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -39,7 +39,6 @@
#include <drm/drm_framebuffer.h>
#include <drm/drm_modes.h>
#include <drm/drm_connector.h>
-#include <drm/drm_encoder.h>
#include <drm/drm_property.h>
#include <drm/drm_bridge.h>
#include <drm/drm_edid.h>
@@ -68,14 +67,12 @@ static inline uint64_t I642U64(int64_t val)
}
struct drm_crtc;
-struct drm_encoder;
struct drm_pending_vblank_event;
struct drm_plane;
struct drm_bridge;
struct drm_atomic_state;
struct drm_crtc_helper_funcs;
-struct drm_encoder_helper_funcs;
struct drm_plane_helper_funcs;
/**
@@ -93,8 +90,6 @@ struct drm_plane_helper_funcs;
* @plane_mask: bitmask of (1 << drm_plane_index(plane)) of attached planes
* @connector_mask: bitmask of (1 << drm_connector_index(connector)) of attached connectors
* @encoder_mask: bitmask of (1 << drm_encoder_index(encoder)) of attached encoders
- * @last_vblank_count: for helpers and drivers to capture the vblank of the
- * update to ensure framebuffer cleanup isn't done too early
* @adjusted_mode: for use by helpers and drivers to compute adjusted mode timings
* @mode: current mode timings
* @mode_blob: &drm_property_blob for @mode
@@ -140,9 +135,6 @@ struct drm_crtc_state {
u32 connector_mask;
u32 encoder_mask;
- /* last_vblank_count: for vblank waits before cleanup */
- u32 last_vblank_count;
-
/* adjusted_mode: for use by helpers and drivers */
struct drm_display_mode adjusted_mode;
@@ -323,7 +315,7 @@ struct drm_crtc_funcs {
*
* This is the main legacy entry point to change the modeset state on a
* CRTC. All the details of the desired configuration are passed in a
- * struct &drm_mode_set - see there for details.
+ * &struct drm_mode_set - see there for details.
*
* Drivers implementing atomic modeset should use
* drm_atomic_helper_set_config() to implement this hook.
@@ -354,7 +346,7 @@ struct drm_crtc_funcs {
* shared dma-buf.
*
* An application can request to be notified when the page flip has
- * completed. The drm core will supply a struct &drm_event in the event
+ * completed. The drm core will supply a &struct drm_event in the event
* parameter in this case. This can be handled by the
* drm_crtc_send_vblank_event() function, which the driver should call on
* the provided event upon completion of the flip. Note that if
@@ -439,7 +431,7 @@ struct drm_crtc_funcs {
* &drm_mode_config_funcs) will be cleaned up by calling the
* @atomic_destroy_state hook in this structure.
*
- * Atomic drivers which don't subclass struct &drm_crtc should use
+ * Atomic drivers which don't subclass &struct drm_crtc should use
* drm_atomic_helper_crtc_duplicate_state(). Drivers that subclass the
* state structure to extend it with driver-private state should use
* __drm_atomic_helper_crtc_duplicate_state() to make sure shared state is
@@ -591,7 +583,7 @@ struct drm_crtc_funcs {
/**
* @atomic_print_state:
*
- * If driver subclasses struct &drm_crtc_state, it should implement
+ * If driver subclasses &struct drm_crtc_state, it should implement
* this optional hook for printing additional driver specific state.
*
* Do not call this directly, use drm_atomic_crtc_print_state()
@@ -830,6 +822,7 @@ int drm_crtc_force_disable(struct drm_crtc *crtc);
int drm_crtc_force_disable_all(struct drm_device *dev);
int drm_mode_set_config_internal(struct drm_mode_set *set);
+struct drm_crtc *drm_crtc_from_index(struct drm_device *dev, int idx);
/* Helpers */
static inline struct drm_crtc *drm_crtc_find(struct drm_device *dev,
@@ -843,18 +836,4 @@ static inline struct drm_crtc *drm_crtc_find(struct drm_device *dev,
#define drm_for_each_crtc(crtc, dev) \
list_for_each_entry(crtc, &(dev)->mode_config.crtc_list, head)
-static inline void
-assert_drm_connector_list_read_locked(struct drm_mode_config *mode_config)
-{
- /*
- * The connector hotadd/remove code currently grabs both locks when
- * updating lists. Hence readers need only hold either of them to be
- * safe and the check amounts to
- *
- * WARN_ON(not_holding(A) && not_holding(B)).
- */
- WARN_ON(!mutex_is_locked(&mode_config->mutex) &&
- !drm_modeset_is_locked(&mode_config->connection_mutex));
-}
-
#endif /* __DRM_CRTC_H__ */
diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h
index c4fc49583dc0..34ece393c639 100644
--- a/include/drm/drm_drv.h
+++ b/include/drm/drm_drv.h
@@ -64,13 +64,45 @@ struct drm_mode_create_dumb;
* structure for GEM drivers.
*/
struct drm_driver {
+
+ /**
+ * @load:
+ *
+ * Backward-compatible driver callback to complete
+ * initialization steps after the driver is registered. For
+ * this reason, may suffer from race conditions and its use is
+ * deprecated for new drivers. It is therefore only supported
+ * for existing drivers not yet converted to the new scheme.
+ * See drm_dev_init() and drm_dev_register() for proper and
+ * race-free way to set up a &struct drm_device.
+ *
+ * Returns:
+ *
+ * Zero on success, non-zero value on failure.
+ */
int (*load) (struct drm_device *, unsigned long flags);
int (*firstopen) (struct drm_device *);
int (*open) (struct drm_device *, struct drm_file *);
void (*preclose) (struct drm_device *, struct drm_file *file_priv);
void (*postclose) (struct drm_device *, struct drm_file *);
void (*lastclose) (struct drm_device *);
- int (*unload) (struct drm_device *);
+
+ /**
+ * @unload:
+ *
+ * Reverse the effects of the driver load callback. Ideally,
+ * the clean up performed by the driver should happen in the
+ * reverse order of the initialization. Similarly to the load
+ * hook, this handler is deprecated and its usage should be
+ * dropped in favor of an open-coded teardown function at the
+ * driver layer. See drm_dev_unregister() and drm_dev_unref()
+ * for the proper way to remove a &struct drm_device.
+ *
+ * The unload() hook is called right after unregistering
+ * the device.
+ *
+ */
+ void (*unload) (struct drm_device *);
int (*dma_ioctl) (struct drm_device *dev, void *data, struct drm_file *file_priv);
int (*dma_quiescent) (struct drm_device *);
int (*context_dtor) (struct drm_device *dev, int context);
diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h
index c7438ff0d609..5f58f65344e0 100644
--- a/include/drm/drm_encoder.h
+++ b/include/drm/drm_encoder.h
@@ -25,8 +25,12 @@
#include <linux/list.h>
#include <linux/ctype.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_mode.h>
#include <drm/drm_mode_object.h>
+struct drm_encoder;
+
/**
* struct drm_encoder_funcs - encoder controls
*
@@ -188,9 +192,6 @@ static inline unsigned int drm_encoder_index(struct drm_encoder *encoder)
return encoder->index;
}
-/* FIXME: We have an include file mess still, drm_crtc.h needs untangling. */
-static inline uint32_t drm_crtc_mask(const struct drm_crtc *crtc);
-
/**
* drm_encoder_crtc_ok - can a given crtc drive a given encoder?
* @encoder: encoder to test
diff --git a/include/drm/drm_encoder_slave.h b/include/drm/drm_encoder_slave.h
index 82cdf611393d..1107b4b1c599 100644
--- a/include/drm/drm_encoder_slave.h
+++ b/include/drm/drm_encoder_slave.h
@@ -29,6 +29,7 @@
#include <drm/drmP.h>
#include <drm/drm_crtc.h>
+#include <drm/drm_encoder.h>
/**
* struct drm_encoder_slave_funcs - Entry points exposed by a slave encoder driver
diff --git a/include/drm/drm_fb_cma_helper.h b/include/drm/drm_fb_cma_helper.h
index 3b00f6480b83..9f4e34ea99fd 100644
--- a/include/drm/drm_fb_cma_helper.h
+++ b/include/drm/drm_fb_cma_helper.h
@@ -17,7 +17,7 @@ struct drm_plane_state;
struct drm_fbdev_cma *drm_fbdev_cma_init_with_funcs(struct drm_device *dev,
unsigned int preferred_bpp, unsigned int num_crtc,
- unsigned int max_conn_count, const struct drm_fb_helper_funcs *funcs);
+ unsigned int max_conn_count, const struct drm_framebuffer_funcs *funcs);
struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev,
unsigned int preferred_bpp, unsigned int num_crtc,
unsigned int max_conn_count);
@@ -26,9 +26,6 @@ void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma);
void drm_fbdev_cma_restore_mode(struct drm_fbdev_cma *fbdev_cma);
void drm_fbdev_cma_hotplug_event(struct drm_fbdev_cma *fbdev_cma);
void drm_fbdev_cma_set_suspend(struct drm_fbdev_cma *fbdev_cma, int state);
-int drm_fbdev_cma_create_with_funcs(struct drm_fb_helper *helper,
- struct drm_fb_helper_surface_size *sizes,
- const struct drm_framebuffer_funcs *funcs);
void drm_fb_cma_destroy(struct drm_framebuffer *fb);
int drm_fb_cma_create_handle(struct drm_framebuffer *fb,
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index 975deedd593e..e62e1cf22678 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -181,7 +181,7 @@ struct drm_fb_helper_connector {
*
* This is the main structure used by the fbdev helpers. Drivers supporting
* fbdev emulation should embedded this into their overall driver structure.
- * Drivers must also fill out a struct &drm_fb_helper_funcs with a few
+ * Drivers must also fill out a &struct drm_fb_helper_funcs with a few
* operations.
*/
struct drm_fb_helper {
@@ -295,8 +295,7 @@ struct drm_display_mode *
drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector,
int width, int height);
struct drm_display_mode *
-drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
- int width, int height);
+drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn);
int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_connector *connector);
int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
diff --git a/include/drm/drm_framebuffer.h b/include/drm/drm_framebuffer.h
index 1ddfa2928802..046c35e54099 100644
--- a/include/drm/drm_framebuffer.h
+++ b/include/drm/drm_framebuffer.h
@@ -51,7 +51,7 @@ struct drm_framebuffer_funcs {
* @create_handle:
*
* Create a buffer handle in the driver-specific buffer manager (either
- * GEM or TTM) valid for the passed-in struct &drm_file. This is used by
+ * GEM or TTM) valid for the passed-in &struct drm_file. This is used by
* the core to implement the GETFB IOCTL, which returns (for
* sufficiently priviledged user) also a native buffer handle. This can
* be used for seamless transitions between modesetting clients by
@@ -122,6 +122,10 @@ struct drm_framebuffer {
*/
struct drm_mode_object base;
/**
+ * @format: framebuffer format information
+ */
+ const struct drm_format_info *format;
+ /**
* @funcs: framebuffer vfunc table
*/
const struct drm_framebuffer_funcs *funcs;
@@ -145,7 +149,7 @@ struct drm_framebuffer {
*
* This should not be used to specifiy x/y pixel offsets into the buffer
* data (even for linear buffers). Specifying an x/y pixel offset is
- * instead done through the source rectangle in struct &drm_plane_state.
+ * instead done through the source rectangle in &struct drm_plane_state.
*/
unsigned int offsets[4];
/**
@@ -166,28 +170,11 @@ struct drm_framebuffer {
*/
unsigned int height;
/**
- * @depth: Depth in bits per pixel for RGB formats. 0 for everything
- * else. Legacy information derived from @pixel_format, it's suggested to use
- * the DRM FOURCC codes and helper functions directly instead.
- */
- unsigned int depth;
- /**
- * @bits_per_pixel: Storage used bits per pixel for RGB formats. 0 for
- * everything else. Legacy information derived from @pixel_format, it's
- * suggested to use the DRM FOURCC codes and helper functions directly
- * instead.
- */
- int bits_per_pixel;
- /**
* @flags: Framebuffer flags like DRM_MODE_FB_INTERLACED or
* DRM_MODE_FB_MODIFIERS.
*/
int flags;
/**
- * @pixel_format: DRM FOURCC code describing the pixel format.
- */
- uint32_t pixel_format; /* fourcc format */
- /**
* @hot_x: X coordinate of the cursor hotspot. Used by the legacy cursor
* IOCTL when the driver supports cursor through a DRM_PLANE_TYPE_CURSOR
* universal plane.
@@ -200,7 +187,7 @@ struct drm_framebuffer {
*/
int hot_y;
/**
- * @filp_head: Placed on struct &drm_file fbs list_head, protected by
+ * @filp_head: Placed on &struct drm_file fbs list_head, protected by
* fbs_lock in the same structure.
*/
struct list_head filp_head;
@@ -282,4 +269,10 @@ static inline void drm_framebuffer_assign(struct drm_framebuffer **p,
struct drm_framebuffer, head); \
&fb->head != (&(dev)->mode_config.fb_list); \
fb = list_next_entry(fb, head))
+
+int drm_framebuffer_plane_width(int width,
+ const struct drm_framebuffer *fb, int plane);
+int drm_framebuffer_plane_height(int height,
+ const struct drm_framebuffer *fb, int plane);
+
#endif
diff --git a/include/drm/drm_gem_cma_helper.h b/include/drm/drm_gem_cma_helper.h
index acd6af8a8e67..2abcd5190cc1 100644
--- a/include/drm/drm_gem_cma_helper.h
+++ b/include/drm/drm_gem_cma_helper.h
@@ -53,6 +53,23 @@ struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm,
extern const struct vm_operations_struct drm_gem_cma_vm_ops;
+#ifndef CONFIG_MMU
+unsigned long drm_gem_cma_get_unmapped_area(struct file *filp,
+ unsigned long addr,
+ unsigned long len,
+ unsigned long pgoff,
+ unsigned long flags);
+#else
+static inline unsigned long drm_gem_cma_get_unmapped_area(struct file *filp,
+ unsigned long addr,
+ unsigned long len,
+ unsigned long pgoff,
+ unsigned long flags)
+{
+ return -EINVAL;
+}
+#endif
+
#ifdef CONFIG_DEBUG_FS
void drm_gem_cma_describe(struct drm_gem_cma_object *obj, struct seq_file *m);
#endif
diff --git a/include/drm/drm_irq.h b/include/drm/drm_irq.h
index 293d08caab60..18cfd11307e1 100644
--- a/include/drm/drm_irq.h
+++ b/include/drm/drm_irq.h
@@ -51,8 +51,8 @@ struct drm_pending_vblank_event {
*
* Note that for historical reasons - the vblank handling code is still shared
* with legacy/non-kms drivers - this is a free-standing structure not directly
- * connected to struct &drm_crtc. But all public interface functions are taking
- * a struct &drm_crtc to hide this implementation detail.
+ * connected to &struct drm_crtc. But all public interface functions are taking
+ * a &struct drm_crtc to hide this implementation detail.
*/
struct drm_vblank_crtc {
/**
diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h
index 0b8371795aeb..3bddca8fd2b5 100644
--- a/include/drm/drm_mm.h
+++ b/include/drm/drm_mm.h
@@ -1,6 +1,7 @@
/**************************************************************************
*
* Copyright 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX. USA.
+ * Copyright 2016 Intel Corporation
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -41,12 +42,16 @@
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/spinlock.h>
-#ifdef CONFIG_DEBUG_FS
-#include <linux/seq_file.h>
-#endif
#ifdef CONFIG_DRM_DEBUG_MM
#include <linux/stackdepot.h>
#endif
+#include <drm/drm_print.h>
+
+#ifdef CONFIG_DRM_DEBUG_MM
+#define DRM_MM_BUG_ON(expr) BUG_ON(expr)
+#else
+#define DRM_MM_BUG_ON(expr) BUILD_BUG_ON_INVALID(expr)
+#endif
enum drm_mm_search_flags {
DRM_MM_SEARCH_DEFAULT = 0,
@@ -62,19 +67,29 @@ enum drm_mm_allocator_flags {
#define DRM_MM_BOTTOMUP DRM_MM_SEARCH_DEFAULT, DRM_MM_CREATE_DEFAULT
#define DRM_MM_TOPDOWN DRM_MM_SEARCH_BELOW, DRM_MM_CREATE_TOP
+/**
+ * struct drm_mm_node - allocated block in the DRM allocator
+ *
+ * This represents an allocated block in a &drm_mm allocator. Except for
+ * pre-reserved nodes inserted using drm_mm_reserve_node() the structure is
+ * entirely opaque and should only be accessed through the provided funcions.
+ * Since allocation of these nodes is entirely handled by the driver they can be
+ * embedded.
+ */
struct drm_mm_node {
+ /** @color: Opaque driver-private tag. */
+ unsigned long color;
+ /** @start: Start address of the allocated block. */
+ u64 start;
+ /** @size: Size of the allocated block. */
+ u64 size;
+ /* private: */
struct list_head node_list;
struct list_head hole_stack;
struct rb_node rb;
unsigned hole_follows : 1;
- unsigned scanned_block : 1;
- unsigned scanned_prev_free : 1;
- unsigned scanned_next_free : 1;
- unsigned scanned_preceeds_hole : 1;
unsigned allocated : 1;
- unsigned long color;
- u64 start;
- u64 size;
+ bool scanned_block : 1;
u64 __subtree_last;
struct drm_mm *mm;
#ifdef CONFIG_DRM_DEBUG_MM
@@ -82,7 +97,29 @@ struct drm_mm_node {
#endif
};
+/**
+ * struct drm_mm - DRM allocator
+ *
+ * DRM range allocator with a few special functions and features geared towards
+ * managing GPU memory. Except for the @color_adjust callback the structure is
+ * entirely opaque and should only be accessed through the provided functions
+ * and macros. This structure can be embedded into larger driver structures.
+ */
struct drm_mm {
+ /**
+ * @color_adjust:
+ *
+ * Optional driver callback to further apply restrictions on a hole. The
+ * node argument points at the node containing the hole from which the
+ * block would be allocated (see drm_mm_hole_follows() and friends). The
+ * other arguments are the size of the block to be allocated. The driver
+ * can adjust the start and end as needed to e.g. insert guard pages.
+ */
+ void (*color_adjust)(const struct drm_mm_node *node,
+ unsigned long color,
+ u64 *start, u64 *end);
+
+ /* private: */
/* List of all memory nodes that immediately precede a free hole. */
struct list_head hole_stack;
/* head_node.node_list is the list of all memory nodes, ordered
@@ -91,32 +128,50 @@ struct drm_mm {
/* Keep an interval_tree for fast lookup of drm_mm_nodes by address. */
struct rb_root interval_tree;
- unsigned int scan_check_range : 1;
- unsigned scan_alignment;
- unsigned long scan_color;
- u64 scan_size;
- u64 scan_hit_start;
- u64 scan_hit_end;
- unsigned scanned_blocks;
- u64 scan_start;
- u64 scan_end;
- struct drm_mm_node *prev_scanned_node;
-
- void (*color_adjust)(struct drm_mm_node *node, unsigned long color,
- u64 *start, u64 *end);
+ unsigned long scan_active;
+};
+
+/**
+ * struct drm_mm_scan - DRM allocator eviction roaster data
+ *
+ * This structure tracks data needed for the eviction roaster set up using
+ * drm_mm_scan_init(), and used with drm_mm_scan_add_block() and
+ * drm_mm_scan_remove_block(). The structure is entirely opaque and should only
+ * be accessed through the provided functions and macros. It is meant to be
+ * allocated temporarily by the driver on the stack.
+ */
+struct drm_mm_scan {
+ /* private: */
+ struct drm_mm *mm;
+
+ u64 size;
+ u64 alignment;
+ u64 remainder_mask;
+
+ u64 range_start;
+ u64 range_end;
+
+ u64 hit_start;
+ u64 hit_end;
+
+ unsigned long color;
+ unsigned int flags;
};
/**
* drm_mm_node_allocated - checks whether a node is allocated
* @node: drm_mm_node to check
*
- * Drivers should use this helpers for proper encapusulation of drm_mm
+ * Drivers are required to clear a node prior to using it with the
+ * drm_mm range manager.
+ *
+ * Drivers should use this helper for proper encapsulation of drm_mm
* internals.
*
* Returns:
* True if the @node is allocated.
*/
-static inline bool drm_mm_node_allocated(struct drm_mm_node *node)
+static inline bool drm_mm_node_allocated(const struct drm_mm_node *node)
{
return node->allocated;
}
@@ -125,18 +180,38 @@ static inline bool drm_mm_node_allocated(struct drm_mm_node *node)
* drm_mm_initialized - checks whether an allocator is initialized
* @mm: drm_mm to check
*
- * Drivers should use this helpers for proper encapusulation of drm_mm
+ * Drivers should clear the struct drm_mm prior to initialisation if they
+ * want to use this function.
+ *
+ * Drivers should use this helper for proper encapsulation of drm_mm
* internals.
*
* Returns:
* True if the @mm is initialized.
*/
-static inline bool drm_mm_initialized(struct drm_mm *mm)
+static inline bool drm_mm_initialized(const struct drm_mm *mm)
{
return mm->hole_stack.next;
}
-static inline u64 __drm_mm_hole_node_start(struct drm_mm_node *hole_node)
+/**
+ * drm_mm_hole_follows - checks whether a hole follows this node
+ * @node: drm_mm_node to check
+ *
+ * Holes are embedded into the drm_mm using the tail of a drm_mm_node.
+ * If you wish to know whether a hole follows this particular node,
+ * query this function. See also drm_mm_hole_node_start() and
+ * drm_mm_hole_node_end().
+ *
+ * Returns:
+ * True if a hole follows the @node.
+ */
+static inline bool drm_mm_hole_follows(const struct drm_mm_node *node)
+{
+ return node->hole_follows;
+}
+
+static inline u64 __drm_mm_hole_node_start(const struct drm_mm_node *hole_node)
{
return hole_node->start + hole_node->size;
}
@@ -145,20 +220,20 @@ static inline u64 __drm_mm_hole_node_start(struct drm_mm_node *hole_node)
* drm_mm_hole_node_start - computes the start of the hole following @node
* @hole_node: drm_mm_node which implicitly tracks the following hole
*
- * This is useful for driver-sepific debug dumpers. Otherwise drivers should not
- * inspect holes themselves. Drivers must check first whether a hole indeed
- * follows by looking at node->hole_follows.
+ * This is useful for driver-specific debug dumpers. Otherwise drivers should
+ * not inspect holes themselves. Drivers must check first whether a hole indeed
+ * follows by looking at drm_mm_hole_follows()
*
* Returns:
* Start of the subsequent hole.
*/
-static inline u64 drm_mm_hole_node_start(struct drm_mm_node *hole_node)
+static inline u64 drm_mm_hole_node_start(const struct drm_mm_node *hole_node)
{
- BUG_ON(!hole_node->hole_follows);
+ DRM_MM_BUG_ON(!drm_mm_hole_follows(hole_node));
return __drm_mm_hole_node_start(hole_node);
}
-static inline u64 __drm_mm_hole_node_end(struct drm_mm_node *hole_node)
+static inline u64 __drm_mm_hole_node_end(const struct drm_mm_node *hole_node)
{
return list_next_entry(hole_node, node_list)->start;
}
@@ -167,29 +242,54 @@ static inline u64 __drm_mm_hole_node_end(struct drm_mm_node *hole_node)
* drm_mm_hole_node_end - computes the end of the hole following @node
* @hole_node: drm_mm_node which implicitly tracks the following hole
*
- * This is useful for driver-sepific debug dumpers. Otherwise drivers should not
- * inspect holes themselves. Drivers must check first whether a hole indeed
- * follows by looking at node->hole_follows.
+ * This is useful for driver-specific debug dumpers. Otherwise drivers should
+ * not inspect holes themselves. Drivers must check first whether a hole indeed
+ * follows by looking at drm_mm_hole_follows().
*
* Returns:
* End of the subsequent hole.
*/
-static inline u64 drm_mm_hole_node_end(struct drm_mm_node *hole_node)
+static inline u64 drm_mm_hole_node_end(const struct drm_mm_node *hole_node)
{
return __drm_mm_hole_node_end(hole_node);
}
/**
+ * drm_mm_nodes - list of nodes under the drm_mm range manager
+ * @mm: the struct drm_mm range manger
+ *
+ * As the drm_mm range manager hides its node_list deep with its
+ * structure, extracting it looks painful and repetitive. This is
+ * not expected to be used outside of the drm_mm_for_each_node()
+ * macros and similar internal functions.
+ *
+ * Returns:
+ * The node list, may be empty.
+ */
+#define drm_mm_nodes(mm) (&(mm)->head_node.node_list)
+
+/**
* drm_mm_for_each_node - iterator to walk over all allocated nodes
- * @entry: drm_mm_node structure to assign to in each iteration step
- * @mm: drm_mm allocator to walk
+ * @entry: &struct drm_mm_node to assign to in each iteration step
+ * @mm: &drm_mm allocator to walk
+ *
+ * This iterator walks over all nodes in the range allocator. It is implemented
+ * with list_for_each(), so not save against removal of elements.
+ */
+#define drm_mm_for_each_node(entry, mm) \
+ list_for_each_entry(entry, drm_mm_nodes(mm), node_list)
+
+/**
+ * drm_mm_for_each_node_safe - iterator to walk over all allocated nodes
+ * @entry: &struct drm_mm_node to assign to in each iteration step
+ * @next: &struct drm_mm_node to store the next step
+ * @mm: &drm_mm allocator to walk
*
* This iterator walks over all nodes in the range allocator. It is implemented
- * with list_for_each, so not save against removal of elements.
+ * with list_for_each_safe(), so save against removal of elements.
*/
-#define drm_mm_for_each_node(entry, mm) list_for_each_entry(entry, \
- &(mm)->head_node.node_list, \
- node_list)
+#define drm_mm_for_each_node_safe(entry, next, mm) \
+ list_for_each_entry_safe(entry, next, drm_mm_nodes(mm), node_list)
#define __drm_mm_for_each_hole(entry, mm, hole_start, hole_end, backwards) \
for (entry = list_entry((backwards) ? (mm)->hole_stack.prev : (mm)->hole_stack.next, struct drm_mm_node, hole_stack); \
@@ -201,13 +301,13 @@ static inline u64 drm_mm_hole_node_end(struct drm_mm_node *hole_node)
/**
* drm_mm_for_each_hole - iterator to walk over all holes
- * @entry: drm_mm_node used internally to track progress
- * @mm: drm_mm allocator to walk
+ * @entry: &drm_mm_node used internally to track progress
+ * @mm: &drm_mm allocator to walk
* @hole_start: ulong variable to assign the hole start to on each iteration
* @hole_end: ulong variable to assign the hole end to on each iteration
*
* This iterator walks over all holes in the range allocator. It is implemented
- * with list_for_each, so not save against removal of elements. @entry is used
+ * with list_for_each(), so not save against removal of elements. @entry is used
* internally and will not reflect a real drm_mm_node for the very first hole.
* Hence users of this iterator may not access it.
*
@@ -225,49 +325,16 @@ static inline u64 drm_mm_hole_node_end(struct drm_mm_node *hole_node)
* Basic range manager support (drm_mm.c)
*/
int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node);
-
-int drm_mm_insert_node_generic(struct drm_mm *mm,
- struct drm_mm_node *node,
- u64 size,
- unsigned alignment,
- unsigned long color,
- enum drm_mm_search_flags sflags,
- enum drm_mm_allocator_flags aflags);
-/**
- * drm_mm_insert_node - search for space and insert @node
- * @mm: drm_mm to allocate from
- * @node: preallocate node to insert
- * @size: size of the allocation
- * @alignment: alignment of the allocation
- * @flags: flags to fine-tune the allocation
- *
- * This is a simplified version of drm_mm_insert_node_generic() with @color set
- * to 0.
- *
- * The preallocated node must be cleared to 0.
- *
- * Returns:
- * 0 on success, -ENOSPC if there's no suitable hole.
- */
-static inline int drm_mm_insert_node(struct drm_mm *mm,
- struct drm_mm_node *node,
- u64 size,
- unsigned alignment,
- enum drm_mm_search_flags flags)
-{
- return drm_mm_insert_node_generic(mm, node, size, alignment, 0, flags,
- DRM_MM_CREATE_DEFAULT);
-}
-
int drm_mm_insert_node_in_range_generic(struct drm_mm *mm,
struct drm_mm_node *node,
u64 size,
- unsigned alignment,
+ u64 alignment,
unsigned long color,
u64 start,
u64 end,
enum drm_mm_search_flags sflags,
enum drm_mm_allocator_flags aflags);
+
/**
* drm_mm_insert_node_in_range - ranged search for space and insert @node
* @mm: drm_mm to allocate from
@@ -289,7 +356,7 @@ int drm_mm_insert_node_in_range_generic(struct drm_mm *mm,
static inline int drm_mm_insert_node_in_range(struct drm_mm *mm,
struct drm_mm_node *node,
u64 size,
- unsigned alignment,
+ u64 alignment,
u64 start,
u64 end,
enum drm_mm_search_flags flags)
@@ -299,16 +366,84 @@ static inline int drm_mm_insert_node_in_range(struct drm_mm *mm,
DRM_MM_CREATE_DEFAULT);
}
+/**
+ * drm_mm_insert_node_generic - search for space and insert @node
+ * @mm: drm_mm to allocate from
+ * @node: preallocate node to insert
+ * @size: size of the allocation
+ * @alignment: alignment of the allocation
+ * @color: opaque tag value to use for this node
+ * @sflags: flags to fine-tune the allocation search
+ * @aflags: flags to fine-tune the allocation behavior
+ *
+ * This is a simplified version of drm_mm_insert_node_in_range_generic() with no
+ * range restrictions applied.
+ *
+ * The preallocated node must be cleared to 0.
+ *
+ * Returns:
+ * 0 on success, -ENOSPC if there's no suitable hole.
+ */
+static inline int
+drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node,
+ u64 size, u64 alignment,
+ unsigned long color,
+ enum drm_mm_search_flags sflags,
+ enum drm_mm_allocator_flags aflags)
+{
+ return drm_mm_insert_node_in_range_generic(mm, node,
+ size, alignment, 0,
+ 0, U64_MAX,
+ sflags, aflags);
+}
+
+/**
+ * drm_mm_insert_node - search for space and insert @node
+ * @mm: drm_mm to allocate from
+ * @node: preallocate node to insert
+ * @size: size of the allocation
+ * @alignment: alignment of the allocation
+ * @flags: flags to fine-tune the allocation
+ *
+ * This is a simplified version of drm_mm_insert_node_generic() with @color set
+ * to 0.
+ *
+ * The preallocated node must be cleared to 0.
+ *
+ * Returns:
+ * 0 on success, -ENOSPC if there's no suitable hole.
+ */
+static inline int drm_mm_insert_node(struct drm_mm *mm,
+ struct drm_mm_node *node,
+ u64 size,
+ u64 alignment,
+ enum drm_mm_search_flags flags)
+{
+ return drm_mm_insert_node_generic(mm, node,
+ size, alignment, 0,
+ flags, DRM_MM_CREATE_DEFAULT);
+}
+
void drm_mm_remove_node(struct drm_mm_node *node);
void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new);
-void drm_mm_init(struct drm_mm *mm,
- u64 start,
- u64 size);
+void drm_mm_init(struct drm_mm *mm, u64 start, u64 size);
void drm_mm_takedown(struct drm_mm *mm);
-bool drm_mm_clean(struct drm_mm *mm);
+
+/**
+ * drm_mm_clean - checks whether an allocator is clean
+ * @mm: drm_mm allocator to check
+ *
+ * Returns:
+ * True if the allocator is completely free, false if there's still a node
+ * allocated in it.
+ */
+static inline bool drm_mm_clean(const struct drm_mm *mm)
+{
+ return list_empty(drm_mm_nodes(mm));
+}
struct drm_mm_node *
-__drm_mm_interval_first(struct drm_mm *mm, u64 start, u64 last);
+__drm_mm_interval_first(const struct drm_mm *mm, u64 start, u64 last);
/**
* drm_mm_for_each_node_in_range - iterator to walk over a range of
@@ -329,22 +464,50 @@ __drm_mm_interval_first(struct drm_mm *mm, u64 start, u64 last);
node__ && node__->start < (end__); \
node__ = list_next_entry(node__, node_list))
-void drm_mm_init_scan(struct drm_mm *mm,
- u64 size,
- unsigned alignment,
- unsigned long color);
-void drm_mm_init_scan_with_range(struct drm_mm *mm,
- u64 size,
- unsigned alignment,
- unsigned long color,
- u64 start,
- u64 end);
-bool drm_mm_scan_add_block(struct drm_mm_node *node);
-bool drm_mm_scan_remove_block(struct drm_mm_node *node);
-
-void drm_mm_debug_table(struct drm_mm *mm, const char *prefix);
-#ifdef CONFIG_DEBUG_FS
-int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm);
-#endif
+void drm_mm_scan_init_with_range(struct drm_mm_scan *scan,
+ struct drm_mm *mm,
+ u64 size, u64 alignment, unsigned long color,
+ u64 start, u64 end,
+ unsigned int flags);
+
+/**
+ * drm_mm_scan_init - initialize lru scanning
+ * @scan: scan state
+ * @mm: drm_mm to scan
+ * @size: size of the allocation
+ * @alignment: alignment of the allocation
+ * @color: opaque tag value to use for the allocation
+ * @flags: flags to specify how the allocation will be performed afterwards
+ *
+ * This is a simplified version of drm_mm_scan_init_with_range() with no range
+ * restrictions applied.
+ *
+ * This simply sets up the scanning routines with the parameters for the desired
+ * hole.
+ *
+ * Warning:
+ * As long as the scan list is non-empty, no other operations than
+ * adding/removing nodes to/from the scan list are allowed.
+ */
+static inline void drm_mm_scan_init(struct drm_mm_scan *scan,
+ struct drm_mm *mm,
+ u64 size,
+ u64 alignment,
+ unsigned long color,
+ unsigned int flags)
+{
+ drm_mm_scan_init_with_range(scan, mm,
+ size, alignment, color,
+ 0, U64_MAX,
+ flags);
+}
+
+bool drm_mm_scan_add_block(struct drm_mm_scan *scan,
+ struct drm_mm_node *node);
+bool drm_mm_scan_remove_block(struct drm_mm_scan *scan,
+ struct drm_mm_node *node);
+struct drm_mm_node *drm_mm_scan_color_evict(struct drm_mm_scan *scan);
+
+void drm_mm_print(const struct drm_mm *mm, struct drm_printer *p);
#endif
diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
index bf9991b20611..17942c0f32a8 100644
--- a/include/drm/drm_mode_config.h
+++ b/include/drm/drm_mode_config.h
@@ -47,7 +47,7 @@ struct drm_mode_config_funcs {
*
* Create a new framebuffer object. The core does basic checks on the
* requested metadata, but most of that is left to the driver. See
- * struct &drm_mode_fb_cmd2 for details.
+ * &struct drm_mode_fb_cmd2 for details.
*
* If the parameters are deemed valid and the backing storage objects in
* the underlying memory manager all exist, then the driver allocates
@@ -135,7 +135,7 @@ struct drm_mode_config_funcs {
* error conditions which don't have to be checked at the
* ->atomic_check() stage?
*
- * See the documentation for struct &drm_atomic_state for how exactly
+ * See the documentation for &struct drm_atomic_state for how exactly
* an atomic modeset update is described.
*
* Drivers using the atomic helpers can implement this hook using
@@ -171,7 +171,7 @@ struct drm_mode_config_funcs {
* calling this function, and that nothing has been changed in the
* interim.
*
- * See the documentation for struct &drm_atomic_state for how exactly
+ * See the documentation for &struct drm_atomic_state for how exactly
* an atomic modeset update is described.
*
* Drivers using the atomic helpers can implement this hook using
@@ -198,7 +198,7 @@ struct drm_mode_config_funcs {
* completed. These events are per-CRTC and can be distinguished by the
* CRTC index supplied in &drm_event to userspace.
*
- * The drm core will supply a struct &drm_event in the event
+ * The drm core will supply a &struct drm_event in the event
* member of each CRTC's &drm_crtc_state structure. See the
* documentation for &drm_crtc_state for more details about the precise
* semantics of this event.
@@ -365,7 +365,13 @@ struct drm_mode_config {
struct list_head fb_list;
/**
- * @num_connector: Number of connectors on this device.
+ * @connector_list_lock: Protects @num_connector and
+ * @connector_list.
+ */
+ spinlock_t connector_list_lock;
+ /**
+ * @num_connector: Number of connectors on this device. Protected by
+ * @connector_list_lock.
*/
int num_connector;
/**
@@ -373,7 +379,9 @@ struct drm_mode_config {
*/
struct ida connector_ida;
/**
- * @connector_list: List of connector objects.
+ * @connector_list: List of connector objects. Protected by
+ * @connector_list_lock. Only use drm_for_each_connector_iter() and
+ * &struct drm_connector_list_iter to walk this list.
*/
struct list_head connector_list;
int num_encoder;
diff --git a/include/drm/drm_modeset_helper.h b/include/drm/drm_modeset_helper.h
index b8051d5abe10..cb0ec92e11e6 100644
--- a/include/drm/drm_modeset_helper.h
+++ b/include/drm/drm_modeset_helper.h
@@ -27,7 +27,8 @@
void drm_helper_move_panel_connectors_to_head(struct drm_device *);
-void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
+void drm_helper_mode_fill_fb_struct(struct drm_device *dev,
+ struct drm_framebuffer *fb,
const struct drm_mode_fb_cmd2 *mode_cmd);
int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
index 69c3974bf133..46f5b349f059 100644
--- a/include/drm/drm_modeset_helper_vtables.h
+++ b/include/drm/drm_modeset_helper_vtables.h
@@ -30,6 +30,7 @@
#define __DRM_MODESET_HELPER_VTABLES_H__
#include <drm/drm_crtc.h>
+#include <drm/drm_encoder.h>
/**
* DOC: overview
@@ -725,7 +726,7 @@ struct drm_connector_helper_funcs {
* fixed panel can also manually add specific modes using
* drm_mode_probed_add(). Drivers which manually add modes should also
* make sure that the @display_info, @width_mm and @height_mm fields of the
- * struct &drm_connector are filled in.
+ * &struct drm_connector are filled in.
*
* Virtual drivers that just want some standard VESA mode with a given
* resolution can call drm_add_modes_noedid(), and mark the preferred
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index db3bbdeb36d5..e049bc52fb07 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -253,7 +253,7 @@ struct drm_plane_funcs {
* &drm_mode_config_funcs) will be cleaned up by calling the
* @atomic_destroy_state hook in this structure.
*
- * Atomic drivers which don't subclass struct &drm_plane_state should use
+ * Atomic drivers which don't subclass &struct drm_plane_state should use
* drm_atomic_helper_plane_duplicate_state(). Drivers that subclass the
* state structure to extend it with driver-private state should use
* __drm_atomic_helper_plane_duplicate_state() to make sure shared state is
@@ -381,7 +381,7 @@ struct drm_plane_funcs {
/**
* @atomic_print_state:
*
- * If driver subclasses struct &drm_plane_state, it should implement
+ * If driver subclasses &struct drm_plane_state, it should implement
* this optional hook for printing additional driver specific state.
*
* Do not call this directly, use drm_atomic_plane_print_state()
diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h
index 1adf84aea622..7d98763c0444 100644
--- a/include/drm/drm_print.h
+++ b/include/drm/drm_print.h
@@ -60,26 +60,27 @@
/**
* struct drm_printer - drm output "stream"
- * @printfn: actual output fxn
- * @arg: output fxn specific data
*
* Do not use struct members directly. Use drm_printer_seq_file(),
* drm_printer_info(), etc to initialize. And drm_printf() for output.
*/
struct drm_printer {
+ /* private: */
void (*printfn)(struct drm_printer *p, struct va_format *vaf);
void *arg;
+ const char *prefix;
};
void __drm_printfn_seq_file(struct drm_printer *p, struct va_format *vaf);
void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf);
+void __drm_printfn_debug(struct drm_printer *p, struct va_format *vaf);
void drm_printf(struct drm_printer *p, const char *f, ...);
/**
* drm_seq_file_printer - construct a &drm_printer that outputs to &seq_file
- * @f: the struct &seq_file to output to
+ * @f: the &struct seq_file to output to
*
* RETURNS:
* The &drm_printer object
@@ -95,7 +96,7 @@ static inline struct drm_printer drm_seq_file_printer(struct seq_file *f)
/**
* drm_info_printer - construct a &drm_printer that outputs to dev_printk()
- * @dev: the struct &device pointer
+ * @dev: the &struct device pointer
*
* RETURNS:
* The &drm_printer object
@@ -109,4 +110,19 @@ static inline struct drm_printer drm_info_printer(struct device *dev)
return p;
}
+/**
+ * drm_debug_printer - construct a &drm_printer that outputs to pr_debug()
+ * @prefix: debug output prefix
+ *
+ * RETURNS:
+ * The &drm_printer object
+ */
+static inline struct drm_printer drm_debug_printer(const char *prefix)
+{
+ struct drm_printer p = {
+ .printfn = __drm_printfn_debug,
+ .prefix = prefix
+ };
+ return p;
+}
#endif /* DRM_PRINT_H_ */
diff --git a/include/drm/drm_simple_kms_helper.h b/include/drm/drm_simple_kms_helper.h
index 01a8436ccb0a..fe8c4ba905ac 100644
--- a/include/drm/drm_simple_kms_helper.h
+++ b/include/drm/drm_simple_kms_helper.h
@@ -73,9 +73,9 @@ struct drm_simple_display_pipe_funcs {
/**
* @prepare_fb:
*
- * Optional, called by struct &drm_plane_helper_funcs ->prepare_fb .
+ * Optional, called by &struct drm_plane_helper_funcs ->prepare_fb .
* Please read the documentation for the ->prepare_fb hook in
- * struct &drm_plane_helper_funcs for more details.
+ * &struct drm_plane_helper_funcs for more details.
*/
int (*prepare_fb)(struct drm_simple_display_pipe *pipe,
struct drm_plane_state *plane_state);
@@ -83,9 +83,9 @@ struct drm_simple_display_pipe_funcs {
/**
* @cleanup_fb:
*
- * Optional, called by struct &drm_plane_helper_funcs ->cleanup_fb .
+ * Optional, called by &struct drm_plane_helper_funcs ->cleanup_fb .
* Please read the documentation for the ->cleanup_fb hook in
- * struct &drm_plane_helper_funcs for more details.
+ * &struct drm_plane_helper_funcs for more details.
*/
void (*cleanup_fb)(struct drm_simple_display_pipe *pipe,
struct drm_plane_state *plane_state);
@@ -114,8 +114,6 @@ struct drm_simple_display_pipe {
int drm_simple_display_pipe_attach_bridge(struct drm_simple_display_pipe *pipe,
struct drm_bridge *bridge);
-void drm_simple_display_pipe_detach_bridge(struct drm_simple_display_pipe *pipe);
-
int drm_simple_display_pipe_init(struct drm_device *dev,
struct drm_simple_display_pipe *pipe,
const struct drm_simple_display_pipe_funcs *funcs,
diff --git a/include/drm/i915_pciids.h b/include/drm/i915_pciids.h
index 0d5f4268d75f..a1dd21d6b723 100644
--- a/include/drm/i915_pciids.h
+++ b/include/drm/i915_pciids.h
@@ -226,23 +226,18 @@
INTEL_VGA_DEVICE(0x162A, info), /* Server */ \
INTEL_VGA_DEVICE(0x162D, info) /* Workstation */
-#define INTEL_BDW_RSVDM_IDS(info) \
+#define INTEL_BDW_RSVD_IDS(info) \
INTEL_VGA_DEVICE(0x1632, info), /* ULT */ \
INTEL_VGA_DEVICE(0x1636, info), /* ULT */ \
INTEL_VGA_DEVICE(0x163B, info), /* Iris */ \
- INTEL_VGA_DEVICE(0x163E, info) /* ULX */
-
-#define INTEL_BDW_RSVDD_IDS(info) \
+ INTEL_VGA_DEVICE(0x163E, info), /* ULX */ \
INTEL_VGA_DEVICE(0x163A, info), /* Server */ \
INTEL_VGA_DEVICE(0x163D, info) /* Workstation */
#define INTEL_BDW_IDS(info) \
INTEL_BDW_GT12_IDS(info), \
INTEL_BDW_GT3_IDS(info), \
- INTEL_BDW_RSVDM_IDS(info), \
- INTEL_BDW_GT12_IDS(info), \
- INTEL_BDW_GT3_IDS(info), \
- INTEL_BDW_RSVDD_IDS(info)
+ INTEL_BDW_RSVD_IDS(info)
#define INTEL_CHV_IDS(info) \
INTEL_VGA_DEVICE(0x22b0, info), \
@@ -270,14 +265,14 @@
INTEL_VGA_DEVICE(0x1923, info), /* ULT GT3 */ \
INTEL_VGA_DEVICE(0x1926, info), /* ULT GT3 */ \
INTEL_VGA_DEVICE(0x1927, info), /* ULT GT3 */ \
- INTEL_VGA_DEVICE(0x192B, info), /* Halo GT3 */ \
- INTEL_VGA_DEVICE(0x192A, info) /* SRV GT3 */
+ INTEL_VGA_DEVICE(0x192B, info) /* Halo GT3 */ \
#define INTEL_SKL_GT4_IDS(info) \
INTEL_VGA_DEVICE(0x1932, info), /* DT GT4 */ \
INTEL_VGA_DEVICE(0x193B, info), /* Halo GT4 */ \
INTEL_VGA_DEVICE(0x193D, info), /* WKS GT4 */ \
- INTEL_VGA_DEVICE(0x193A, info) /* SRV GT4 */
+ INTEL_VGA_DEVICE(0x192A, info), /* SRV GT4 */ \
+ INTEL_VGA_DEVICE(0x193A, info) /* SRV GT4e */
#define INTEL_SKL_IDS(info) \
INTEL_SKL_GT1_IDS(info), \
@@ -292,6 +287,10 @@
INTEL_VGA_DEVICE(0x5A84, info), /* APL HD Graphics 505 */ \
INTEL_VGA_DEVICE(0x5A85, info) /* APL HD Graphics 500 */
+#define INTEL_GLK_IDS(info) \
+ INTEL_VGA_DEVICE(0x3184, info), \
+ INTEL_VGA_DEVICE(0x3185, info)
+
#define INTEL_KBL_GT1_IDS(info) \
INTEL_VGA_DEVICE(0x5913, info), /* ULT GT1.5 */ \
INTEL_VGA_DEVICE(0x5915, info), /* ULX GT1.5 */ \
diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h
index f49edecd66a3..b3bf717cfc45 100644
--- a/include/drm/intel-gtt.h
+++ b/include/drm/intel-gtt.h
@@ -3,8 +3,10 @@
#ifndef _DRM_INTEL_GTT_H
#define _DRM_INTEL_GTT_H
-void intel_gtt_get(u64 *gtt_total, size_t *stolen_size,
- phys_addr_t *mappable_base, u64 *mappable_end);
+void intel_gtt_get(u64 *gtt_total,
+ u32 *stolen_size,
+ phys_addr_t *mappable_base,
+ u64 *mappable_end);
int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev,
struct agp_bridge_data *bridge);
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
index 8daeb3ce0016..bfb3704fc6fc 100644
--- a/include/linux/dma-buf.h
+++ b/include/linux/dma-buf.h
@@ -39,23 +39,6 @@ struct dma_buf_attachment;
/**
* struct dma_buf_ops - operations possible on struct dma_buf
- * @attach: [optional] allows different devices to 'attach' themselves to the
- * given buffer. It might return -EBUSY to signal that backing storage
- * is already allocated and incompatible with the requirements
- * of requesting device.
- * @detach: [optional] detach a given device from this buffer.
- * @map_dma_buf: returns list of scatter pages allocated, increases usecount
- * of the buffer. Requires atleast one attach to be called
- * before. Returned sg list should already be mapped into
- * _device_ address space. This call may sleep. May also return
- * -EINTR. Should return -EINVAL if attach hasn't been called yet.
- * @unmap_dma_buf: decreases usecount of buffer, might deallocate scatter
- * pages.
- * @release: release this buffer; to be called after the last dma_buf_put.
- * @begin_cpu_access: [optional] called before cpu access to invalidate cpu
- * caches and allocate backing storage (if not yet done)
- * respectively pin the object into memory.
- * @end_cpu_access: [optional] called after cpu access to flush caches.
* @kmap_atomic: maps a page from the buffer into kernel address
* space, users may not block until the subsequent unmap call.
* This callback must not sleep.
@@ -63,43 +46,206 @@ struct dma_buf_attachment;
* This Callback must not sleep.
* @kmap: maps a page from the buffer into kernel address space.
* @kunmap: [optional] unmaps a page from the buffer.
- * @mmap: used to expose the backing storage to userspace. Note that the
- * mapping needs to be coherent - if the exporter doesn't directly
- * support this, it needs to fake coherency by shooting down any ptes
- * when transitioning away from the cpu domain.
* @vmap: [optional] creates a virtual mapping for the buffer into kernel
* address space. Same restrictions as for vmap and friends apply.
* @vunmap: [optional] unmaps a vmap from the buffer
*/
struct dma_buf_ops {
+ /**
+ * @attach:
+ *
+ * This is called from dma_buf_attach() to make sure that a given
+ * &device can access the provided &dma_buf. Exporters which support
+ * buffer objects in special locations like VRAM or device-specific
+ * carveout areas should check whether the buffer could be move to
+ * system memory (or directly accessed by the provided device), and
+ * otherwise need to fail the attach operation.
+ *
+ * The exporter should also in general check whether the current
+ * allocation fullfills the DMA constraints of the new device. If this
+ * is not the case, and the allocation cannot be moved, it should also
+ * fail the attach operation.
+ *
+ * Any exporter-private housekeeping data can be stored in the
+ * &dma_buf_attachment.priv pointer.
+ *
+ * This callback is optional.
+ *
+ * Returns:
+ *
+ * 0 on success, negative error code on failure. It might return -EBUSY
+ * to signal that backing storage is already allocated and incompatible
+ * with the requirements of requesting device.
+ */
int (*attach)(struct dma_buf *, struct device *,
- struct dma_buf_attachment *);
+ struct dma_buf_attachment *);
+ /**
+ * @detach:
+ *
+ * This is called by dma_buf_detach() to release a &dma_buf_attachment.
+ * Provided so that exporters can clean up any housekeeping for an
+ * &dma_buf_attachment.
+ *
+ * This callback is optional.
+ */
void (*detach)(struct dma_buf *, struct dma_buf_attachment *);
- /* For {map,unmap}_dma_buf below, any specific buffer attributes
- * required should get added to device_dma_parameters accessible
- * via dev->dma_params.
+ /**
+ * @map_dma_buf:
+ *
+ * This is called by dma_buf_map_attachment() and is used to map a
+ * shared &dma_buf into device address space, and it is mandatory. It
+ * can only be called if @attach has been called successfully. This
+ * essentially pins the DMA buffer into place, and it cannot be moved
+ * any more
+ *
+ * This call may sleep, e.g. when the backing storage first needs to be
+ * allocated, or moved to a location suitable for all currently attached
+ * devices.
+ *
+ * Note that any specific buffer attributes required for this function
+ * should get added to device_dma_parameters accessible via
+ * &device.dma_params from the &dma_buf_attachment. The @attach callback
+ * should also check these constraints.
+ *
+ * If this is being called for the first time, the exporter can now
+ * choose to scan through the list of attachments for this buffer,
+ * collate the requirements of the attached devices, and choose an
+ * appropriate backing storage for the buffer.
+ *
+ * Based on enum dma_data_direction, it might be possible to have
+ * multiple users accessing at the same time (for reading, maybe), or
+ * any other kind of sharing that the exporter might wish to make
+ * available to buffer-users.
+ *
+ * Returns:
+ *
+ * A &sg_table scatter list of or the backing storage of the DMA buffer,
+ * already mapped into the device address space of the &device attached
+ * with the provided &dma_buf_attachment.
+ *
+ * On failure, returns a negative error value wrapped into a pointer.
+ * May also return -EINTR when a signal was received while being
+ * blocked.
*/
struct sg_table * (*map_dma_buf)(struct dma_buf_attachment *,
- enum dma_data_direction);
+ enum dma_data_direction);
+ /**
+ * @unmap_dma_buf:
+ *
+ * This is called by dma_buf_unmap_attachment() and should unmap and
+ * release the &sg_table allocated in @map_dma_buf, and it is mandatory.
+ * It should also unpin the backing storage if this is the last mapping
+ * of the DMA buffer, it the exporter supports backing storage
+ * migration.
+ */
void (*unmap_dma_buf)(struct dma_buf_attachment *,
- struct sg_table *,
- enum dma_data_direction);
+ struct sg_table *,
+ enum dma_data_direction);
+
/* TODO: Add try_map_dma_buf version, to return immed with -EBUSY
* if the call would block.
*/
- /* after final dma_buf_put() */
+ /**
+ * @release:
+ *
+ * Called after the last dma_buf_put to release the &dma_buf, and
+ * mandatory.
+ */
void (*release)(struct dma_buf *);
+ /**
+ * @begin_cpu_access:
+ *
+ * This is called from dma_buf_begin_cpu_access() and allows the
+ * exporter to ensure that the memory is actually available for cpu
+ * access - the exporter might need to allocate or swap-in and pin the
+ * backing storage. The exporter also needs to ensure that cpu access is
+ * coherent for the access direction. The direction can be used by the
+ * exporter to optimize the cache flushing, i.e. access with a different
+ * direction (read instead of write) might return stale or even bogus
+ * data (e.g. when the exporter needs to copy the data to temporary
+ * storage).
+ *
+ * This callback is optional.
+ *
+ * FIXME: This is both called through the DMA_BUF_IOCTL_SYNC command
+ * from userspace (where storage shouldn't be pinned to avoid handing
+ * de-factor mlock rights to userspace) and for the kernel-internal
+ * users of the various kmap interfaces, where the backing storage must
+ * be pinned to guarantee that the atomic kmap calls can succeed. Since
+ * there's no in-kernel users of the kmap interfaces yet this isn't a
+ * real problem.
+ *
+ * Returns:
+ *
+ * 0 on success or a negative error code on failure. This can for
+ * example fail when the backing storage can't be allocated. Can also
+ * return -ERESTARTSYS or -EINTR when the call has been interrupted and
+ * needs to be restarted.
+ */
int (*begin_cpu_access)(struct dma_buf *, enum dma_data_direction);
+
+ /**
+ * @end_cpu_access:
+ *
+ * This is called from dma_buf_end_cpu_access() when the importer is
+ * done accessing the CPU. The exporter can use this to flush caches and
+ * unpin any resources pinned in @begin_cpu_access.
+ * The result of any dma_buf kmap calls after end_cpu_access is
+ * undefined.
+ *
+ * This callback is optional.
+ *
+ * Returns:
+ *
+ * 0 on success or a negative error code on failure. Can return
+ * -ERESTARTSYS or -EINTR when the call has been interrupted and needs
+ * to be restarted.
+ */
int (*end_cpu_access)(struct dma_buf *, enum dma_data_direction);
void *(*kmap_atomic)(struct dma_buf *, unsigned long);
void (*kunmap_atomic)(struct dma_buf *, unsigned long, void *);
void *(*kmap)(struct dma_buf *, unsigned long);
void (*kunmap)(struct dma_buf *, unsigned long, void *);
+ /**
+ * @mmap:
+ *
+ * This callback is used by the dma_buf_mmap() function
+ *
+ * Note that the mapping needs to be incoherent, userspace is expected
+ * to braket CPU access using the DMA_BUF_IOCTL_SYNC interface.
+ *
+ * Because dma-buf buffers have invariant size over their lifetime, the
+ * dma-buf core checks whether a vma is too large and rejects such
+ * mappings. The exporter hence does not need to duplicate this check.
+ * Drivers do not need to check this themselves.
+ *
+ * If an exporter needs to manually flush caches and hence needs to fake
+ * coherency for mmap support, it needs to be able to zap all the ptes
+ * pointing at the backing storage. Now linux mm needs a struct
+ * address_space associated with the struct file stored in vma->vm_file
+ * to do that with the function unmap_mapping_range. But the dma_buf
+ * framework only backs every dma_buf fd with the anon_file struct file,
+ * i.e. all dma_bufs share the same file.
+ *
+ * Hence exporters need to setup their own file (and address_space)
+ * association by setting vma->vm_file and adjusting vma->vm_pgoff in
+ * the dma_buf mmap callback. In the specific case of a gem driver the
+ * exporter could use the shmem file already provided by gem (and set
+ * vm_pgoff = 0). Exporters can then zap ptes by unmapping the
+ * corresponding range of the struct address_space associated with their
+ * own file.
+ *
+ * This callback is optional.
+ *
+ * Returns:
+ *
+ * 0 on success or a negative error code on failure.
+ */
int (*mmap)(struct dma_buf *, struct vm_area_struct *vma);
void *(*vmap)(struct dma_buf *);
@@ -124,6 +270,15 @@ struct dma_buf_ops {
* @poll: for userspace poll support
* @cb_excl: for userspace poll support
* @cb_shared: for userspace poll support
+ *
+ * This represents a shared buffer, created by calling dma_buf_export(). The
+ * userspace representation is a normal file descriptor, which can be created by
+ * calling dma_buf_fd().
+ *
+ * Shared dma buffers are reference counted using dma_buf_put() and
+ * get_dma_buf().
+ *
+ * Device DMA access is handled by the separate &struct dma_buf_attachment.
*/
struct dma_buf {
size_t size;
@@ -160,6 +315,11 @@ struct dma_buf {
* This structure holds the attachment information between the dma_buf buffer
* and its user device(s). The list contains one attachment struct per device
* attached to the buffer.
+ *
+ * An attachment is created by calling dma_buf_attach(), and released again by
+ * calling dma_buf_detach(). The DMA mapping itself needed to initiate a
+ * transfer is created by dma_buf_map_attachment() and freed again by calling
+ * dma_buf_unmap_attachment().
*/
struct dma_buf_attachment {
struct dma_buf *dmabuf;
@@ -192,9 +352,11 @@ struct dma_buf_export_info {
};
/**
- * helper macro for exporters; zeros and fills in most common values
- *
+ * DEFINE_DMA_BUF_EXPORT_INFO - helper macro for exporters
* @name: export-info name
+ *
+ * DEFINE_DMA_BUF_EXPORT_INFO macro defines the &struct dma_buf_export_info,
+ * zeroes it out and pre-populates exp_name in it.
*/
#define DEFINE_DMA_BUF_EXPORT_INFO(name) \
struct dma_buf_export_info name = { .exp_name = KBUILD_MODNAME, \
diff --git a/include/linux/dma-fence.h b/include/linux/dma-fence.h
index d51a7d23c358..6048fa404e57 100644
--- a/include/linux/dma-fence.h
+++ b/include/linux/dma-fence.h
@@ -47,7 +47,7 @@ struct dma_fence_cb;
* can be compared to decide which fence would be signaled later.
* @flags: A mask of DMA_FENCE_FLAG_* defined below
* @timestamp: Timestamp when the fence was signaled.
- * @status: Optional, only valid if < 0, must be set before calling
+ * @error: Optional, only valid if < 0, must be set before calling
* dma_fence_signal, indicates that the fence has completed with an error.
*
* the flags member must be manipulated and read using the appropriate
@@ -79,7 +79,7 @@ struct dma_fence {
unsigned seqno;
unsigned long flags;
ktime_t timestamp;
- int status;
+ int error;
};
enum dma_fence_flag_bits {
@@ -133,7 +133,7 @@ struct dma_fence_cb {
* or some failure occurred that made it impossible to enable
* signaling. True indicates successful enabling.
*
- * fence->status may be set in enable_signaling, but only when false is
+ * fence->error may be set in enable_signaling, but only when false is
* returned.
*
* Calling dma_fence_signal before enable_signaling is called allows
@@ -145,7 +145,7 @@ struct dma_fence_cb {
* the second time will be a noop since it was already signaled.
*
* Notes on signaled:
- * May set fence->status if returning true.
+ * May set fence->error if returning true.
*
* Notes on wait:
* Must not be NULL, set to dma_fence_default_wait for default implementation.
@@ -378,6 +378,50 @@ static inline struct dma_fence *dma_fence_later(struct dma_fence *f1,
return dma_fence_is_signaled(f2) ? NULL : f2;
}
+/**
+ * dma_fence_get_status_locked - returns the status upon completion
+ * @fence: [in] the dma_fence to query
+ *
+ * Drivers can supply an optional error status condition before they signal
+ * the fence (to indicate whether the fence was completed due to an error
+ * rather than success). The value of the status condition is only valid
+ * if the fence has been signaled, dma_fence_get_status_locked() first checks
+ * the signal state before reporting the error status.
+ *
+ * Returns 0 if the fence has not yet been signaled, 1 if the fence has
+ * been signaled without an error condition, or a negative error code
+ * if the fence has been completed in err.
+ */
+static inline int dma_fence_get_status_locked(struct dma_fence *fence)
+{
+ if (dma_fence_is_signaled_locked(fence))
+ return fence->error ?: 1;
+ else
+ return 0;
+}
+
+int dma_fence_get_status(struct dma_fence *fence);
+
+/**
+ * dma_fence_set_error - flag an error condition on the fence
+ * @fence: [in] the dma_fence
+ * @error: [in] the error to store
+ *
+ * Drivers can supply an optional error status condition before they signal
+ * the fence, to indicate that the fence was completed due to an error
+ * rather than success. This must be set before signaling (so that the value
+ * is visible before any waiters on the signal callback are woken). This
+ * helper exists to help catching erroneous setting of #dma_fence.error.
+ */
+static inline void dma_fence_set_error(struct dma_fence *fence,
+ int error)
+{
+ BUG_ON(test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags));
+ BUG_ON(error >= 0 || error < -MAX_ERRNO);
+
+ fence->error = error;
+}
+
signed long dma_fence_wait_timeout(struct dma_fence *,
bool intr, signed long timeout);
signed long dma_fence_wait_any_timeout(struct dma_fence **fences,
diff --git a/include/linux/kref.h b/include/linux/kref.h
index e15828fd71f1..62f0a84ae94e 100644
--- a/include/linux/kref.h
+++ b/include/linux/kref.h
@@ -133,6 +133,6 @@ static inline int kref_put_mutex(struct kref *kref,
*/
static inline int __must_check kref_get_unless_zero(struct kref *kref)
{
- return atomic_add_unless(&kref->refcount, 1, 0);
+ return atomic_inc_not_zero(&kref->refcount);
}
#endif /* _KREF_H_ */
diff --git a/include/linux/prime_numbers.h b/include/linux/prime_numbers.h
new file mode 100644
index 000000000000..14ec4f567342
--- /dev/null
+++ b/include/linux/prime_numbers.h
@@ -0,0 +1,37 @@
+#ifndef __LINUX_PRIME_NUMBERS_H
+#define __LINUX_PRIME_NUMBERS_H
+
+#include <linux/types.h>
+
+bool is_prime_number(unsigned long x);
+unsigned long next_prime_number(unsigned long x);
+
+/**
+ * for_each_prime_number - iterate over each prime upto a value
+ * @prime: the current prime number in this iteration
+ * @max: the upper limit
+ *
+ * Starting from the first prime number 2 iterate over each prime number up to
+ * the @max value. On each iteration, @prime is set to the current prime number.
+ * @max should be less than ULONG_MAX to ensure termination. To begin with
+ * @prime set to 1 on the first iteration use for_each_prime_number_from()
+ * instead.
+ */
+#define for_each_prime_number(prime, max) \
+ for_each_prime_number_from((prime), 2, (max))
+
+/**
+ * for_each_prime_number_from - iterate over each prime upto a value
+ * @prime: the current prime number in this iteration
+ * @from: the initial value
+ * @max: the upper limit
+ *
+ * Starting from @from iterate over each successive prime number up to the
+ * @max value. On each iteration, @prime is set to the current prime number.
+ * @max should be less than ULONG_MAX, and @from less than @max, to ensure
+ * termination.
+ */
+#define for_each_prime_number_from(prime, from, max) \
+ for (prime = (from); prime <= (max); prime = next_prime_number(prime))
+
+#endif /* !__LINUX_PRIME_NUMBERS_H */
diff --git a/include/linux/reservation.h b/include/linux/reservation.h
index d9706a6f5ae2..2b5a4679daea 100644
--- a/include/linux/reservation.h
+++ b/include/linux/reservation.h
@@ -145,6 +145,40 @@ reservation_object_get_list(struct reservation_object *obj)
}
/**
+ * reservation_object_lock - lock the reservation object
+ * @obj: the reservation object
+ * @ctx: the locking context
+ *
+ * Locks the reservation object for exclusive access and modification. Note,
+ * that the lock is only against other writers, readers will run concurrently
+ * with a writer under RCU. The seqlock is used to notify readers if they
+ * overlap with a writer.
+ *
+ * As the reservation object may be locked by multiple parties in an
+ * undefined order, a #ww_acquire_ctx is passed to unwind if a cycle
+ * is detected. See ww_mutex_lock() and ww_acquire_init(). A reservation
+ * object may be locked by itself by passing NULL as @ctx.
+ */
+static inline int
+reservation_object_lock(struct reservation_object *obj,
+ struct ww_acquire_ctx *ctx)
+{
+ return ww_mutex_lock(&obj->lock, ctx);
+}
+
+/**
+ * reservation_object_unlock - unlock the reservation object
+ * @obj: the reservation object
+ *
+ * Unlocks the reservation object following exclusive access.
+ */
+static inline void
+reservation_object_unlock(struct reservation_object *obj)
+{
+ ww_mutex_unlock(&obj->lock);
+}
+
+/**
* reservation_object_get_excl - get the reservation object's
* exclusive fence, with update-side lock held
* @obj: the reservation object
diff --git a/include/uapi/drm/Kbuild b/include/uapi/drm/Kbuild
index 9355dd8eff3b..c97addd08f8c 100644
--- a/include/uapi/drm/Kbuild
+++ b/include/uapi/drm/Kbuild
@@ -9,6 +9,7 @@ header-y += i810_drm.h
header-y += i915_drm.h
header-y += mga_drm.h
header-y += nouveau_drm.h
+header-y += omap_drm.h
header-y += qxl_drm.h
header-y += r128_drm.h
header-y += radeon_drm.h
diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
index a5890bf44c0a..9e1bb7fabcde 100644
--- a/include/uapi/drm/drm_fourcc.h
+++ b/include/uapi/drm/drm_fourcc.h
@@ -154,6 +154,7 @@ extern "C" {
/* Vendor Ids: */
#define DRM_FORMAT_MOD_NONE 0
+#define DRM_FORMAT_MOD_VENDOR_NONE 0
#define DRM_FORMAT_MOD_VENDOR_INTEL 0x01
#define DRM_FORMAT_MOD_VENDOR_AMD 0x02
#define DRM_FORMAT_MOD_VENDOR_NV 0x03
@@ -172,6 +173,16 @@ extern "C" {
* authoritative source for all of these.
*/
+/*
+ * Linear Layout
+ *
+ * Just plain linear layout. Note that this is different from no specifying any
+ * modifier (e.g. not setting DRM_MODE_FB_MODIFIERS in the DRM_ADDFB2 ioctl),
+ * which tells the driver to also take driver-internal information into account
+ * and so might actually result in a tiled framebuffer.
+ */
+#define DRM_FORMAT_MOD_LINEAR fourcc_mod_code(NONE, 0)
+
/* Intel framebuffer modifiers */
/*
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 1c12a350eca3..da32c2f6c3f9 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -258,6 +258,7 @@ typedef struct _drm_i915_sarea {
#define DRM_I915_GEM_USERPTR 0x33
#define DRM_I915_GEM_CONTEXT_GETPARAM 0x34
#define DRM_I915_GEM_CONTEXT_SETPARAM 0x35
+#define DRM_I915_PERF_OPEN 0x36
#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -311,6 +312,7 @@ typedef struct _drm_i915_sarea {
#define DRM_IOCTL_I915_GEM_USERPTR DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_USERPTR, struct drm_i915_gem_userptr)
#define DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_GETPARAM, struct drm_i915_gem_context_param)
#define DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_SETPARAM, struct drm_i915_gem_context_param)
+#define DRM_IOCTL_I915_PERF_OPEN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param)
/* Allow drivers to submit batchbuffers directly to hardware, relying
* on the security mechanisms provided by hardware.
@@ -1224,9 +1226,142 @@ struct drm_i915_gem_context_param {
#define I915_CONTEXT_PARAM_NO_ZEROMAP 0x2
#define I915_CONTEXT_PARAM_GTT_SIZE 0x3
#define I915_CONTEXT_PARAM_NO_ERROR_CAPTURE 0x4
+#define I915_CONTEXT_PARAM_BANNABLE 0x5
__u64 value;
};
+enum drm_i915_oa_format {
+ I915_OA_FORMAT_A13 = 1,
+ I915_OA_FORMAT_A29,
+ I915_OA_FORMAT_A13_B8_C8,
+ I915_OA_FORMAT_B4_C8,
+ I915_OA_FORMAT_A45_B8_C8,
+ I915_OA_FORMAT_B4_C8_A16,
+ I915_OA_FORMAT_C4_B8,
+
+ I915_OA_FORMAT_MAX /* non-ABI */
+};
+
+enum drm_i915_perf_property_id {
+ /**
+ * Open the stream for a specific context handle (as used with
+ * execbuffer2). A stream opened for a specific context this way
+ * won't typically require root privileges.
+ */
+ DRM_I915_PERF_PROP_CTX_HANDLE = 1,
+
+ /**
+ * A value of 1 requests the inclusion of raw OA unit reports as
+ * part of stream samples.
+ */
+ DRM_I915_PERF_PROP_SAMPLE_OA,
+
+ /**
+ * The value specifies which set of OA unit metrics should be
+ * be configured, defining the contents of any OA unit reports.
+ */
+ DRM_I915_PERF_PROP_OA_METRICS_SET,
+
+ /**
+ * The value specifies the size and layout of OA unit reports.
+ */
+ DRM_I915_PERF_PROP_OA_FORMAT,
+
+ /**
+ * Specifying this property implicitly requests periodic OA unit
+ * sampling and (at least on Haswell) the sampling frequency is derived
+ * from this exponent as follows:
+ *
+ * 80ns * 2^(period_exponent + 1)
+ */
+ DRM_I915_PERF_PROP_OA_EXPONENT,
+
+ DRM_I915_PERF_PROP_MAX /* non-ABI */
+};
+
+struct drm_i915_perf_open_param {
+ __u32 flags;
+#define I915_PERF_FLAG_FD_CLOEXEC (1<<0)
+#define I915_PERF_FLAG_FD_NONBLOCK (1<<1)
+#define I915_PERF_FLAG_DISABLED (1<<2)
+
+ /** The number of u64 (id, value) pairs */
+ __u32 num_properties;
+
+ /**
+ * Pointer to array of u64 (id, value) pairs configuring the stream
+ * to open.
+ */
+ __u64 properties_ptr;
+};
+
+/**
+ * Enable data capture for a stream that was either opened in a disabled state
+ * via I915_PERF_FLAG_DISABLED or was later disabled via
+ * I915_PERF_IOCTL_DISABLE.
+ *
+ * It is intended to be cheaper to disable and enable a stream than it may be
+ * to close and re-open a stream with the same configuration.
+ *
+ * It's undefined whether any pending data for the stream will be lost.
+ */
+#define I915_PERF_IOCTL_ENABLE _IO('i', 0x0)
+
+/**
+ * Disable data capture for a stream.
+ *
+ * It is an error to try and read a stream that is disabled.
+ */
+#define I915_PERF_IOCTL_DISABLE _IO('i', 0x1)
+
+/**
+ * Common to all i915 perf records
+ */
+struct drm_i915_perf_record_header {
+ __u32 type;
+ __u16 pad;
+ __u16 size;
+};
+
+enum drm_i915_perf_record_type {
+
+ /**
+ * Samples are the work horse record type whose contents are extensible
+ * and defined when opening an i915 perf stream based on the given
+ * properties.
+ *
+ * Boolean properties following the naming convention
+ * DRM_I915_PERF_SAMPLE_xyz_PROP request the inclusion of 'xyz' data in
+ * every sample.
+ *
+ * The order of these sample properties given by userspace has no
+ * affect on the ordering of data within a sample. The order is
+ * documented here.
+ *
+ * struct {
+ * struct drm_i915_perf_record_header header;
+ *
+ * { u32 oa_report[]; } && DRM_I915_PERF_PROP_SAMPLE_OA
+ * };
+ */
+ DRM_I915_PERF_RECORD_SAMPLE = 1,
+
+ /*
+ * Indicates that one or more OA reports were not written by the
+ * hardware. This can happen for example if an MI_REPORT_PERF_COUNT
+ * command collides with periodic sampling - which would be more likely
+ * at higher sampling frequencies.
+ */
+ DRM_I915_PERF_RECORD_OA_REPORT_LOST = 2,
+
+ /**
+ * An error occurred that resulted in all pending OA reports being lost.
+ */
+ DRM_I915_PERF_RECORD_OA_BUFFER_LOST = 3,
+
+ DRM_I915_PERF_RECORD_MAX /* non-ABI */
+};
+
#if defined(__cplusplus)
}
#endif