diff options
Diffstat (limited to 'include/drm')
26 files changed, 662 insertions, 584 deletions
diff --git a/include/drm/bridge/dw_mipi_dsi.h b/include/drm/bridge/dw_mipi_dsi.h index b0e390b3288e..bda8aa7c2280 100644 --- a/include/drm/bridge/dw_mipi_dsi.h +++ b/include/drm/bridge/dw_mipi_dsi.h @@ -36,6 +36,7 @@ struct dw_mipi_dsi_phy_ops { unsigned int *lane_mbps); int (*get_timing)(void *priv_data, unsigned int lane_mbps, struct dw_mipi_dsi_dphy_timing *timing); + int (*get_esc_clk_rate)(void *priv_data, unsigned int *esc_clk_rate); }; struct dw_mipi_dsi_host_ops { diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index b268180c97eb..85df04c8e62f 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -74,6 +74,9 @@ void drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev, struct drm_atomic_state *old_state); +void +drm_atomic_helper_calc_timestamping_constants(struct drm_atomic_state *state); + void drm_atomic_helper_commit_modeset_disables(struct drm_device *dev, struct drm_atomic_state *state); void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev, diff --git a/include/drm/drm_audio_component.h b/include/drm/drm_audio_component.h index a45f93487039..0d36bfd1a4cd 100644 --- a/include/drm/drm_audio_component.h +++ b/include/drm/drm_audio_component.h @@ -117,6 +117,10 @@ struct drm_audio_component { * @audio_ops: Ops implemented by hda driver, called by DRM driver */ const struct drm_audio_component_audio_ops *audio_ops; + /** + * @master_bind_complete: completion held during component master binding + */ + struct completion master_bind_complete; }; #endif /* _DRM_AUDIO_COMPONENT_H_ */ diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index af145608b5ed..928136556174 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1604,10 +1604,13 @@ const char *drm_get_dvi_i_subconnector_name(int val); const char *drm_get_dvi_i_select_name(int val); const char *drm_get_tv_subconnector_name(int val); const char *drm_get_tv_select_name(int val); +const char *drm_get_dp_subconnector_name(int val); const char *drm_get_content_protection_name(int val); const char *drm_get_hdcp_content_type_name(int val); int drm_mode_create_dvi_i_properties(struct drm_device *dev); +void drm_connector_attach_dp_subconnector_property(struct drm_connector *connector); + int drm_mode_create_tv_margin_properties(struct drm_device *dev); int drm_mode_create_tv_properties(struct drm_device *dev, unsigned int num_modes, diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h index 0988351d743c..f4f68e7a9149 100644 --- a/include/drm/drm_device.h +++ b/include/drm/drm_device.h @@ -92,7 +92,7 @@ struct drm_device { * NULL. * * Instead of using this pointer it is recommended that drivers use - * drm_dev_init() and embed struct &drm_device in their larger + * devm_drm_dev_alloc() and embed struct &drm_device in their larger * per-device structure. */ void *dev_private; diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index e47dc22ebf50..da53aebb7230 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -26,6 +26,9 @@ #include <linux/delay.h> #include <linux/i2c.h> #include <linux/types.h> +#include <drm/drm_connector.h> + +struct drm_device; /* * Unless otherwise noted, all values are from the DP 1.1a spec. Note that @@ -384,13 +387,30 @@ # define DP_DS_PORT_TYPE_DP_DUALMODE 5 # define DP_DS_PORT_TYPE_WIRELESS 6 # define DP_DS_PORT_HPD (1 << 3) +# define DP_DS_NON_EDID_MASK (0xf << 4) +# define DP_DS_NON_EDID_720x480i_60 (1 << 4) +# define DP_DS_NON_EDID_720x480i_50 (2 << 4) +# define DP_DS_NON_EDID_1920x1080i_60 (3 << 4) +# define DP_DS_NON_EDID_1920x1080i_50 (4 << 4) +# define DP_DS_NON_EDID_1280x720_60 (5 << 4) +# define DP_DS_NON_EDID_1280x720_50 (7 << 4) /* offset 1 for VGA is maximum megapixels per second / 8 */ -/* offset 2 */ +/* offset 1 for DVI/HDMI is maximum TMDS clock in Mbps / 2.5 */ +/* offset 2 for VGA/DVI/HDMI */ # define DP_DS_MAX_BPC_MASK (3 << 0) # define DP_DS_8BPC 0 # define DP_DS_10BPC 1 # define DP_DS_12BPC 2 # define DP_DS_16BPC 3 +/* offset 3 for DVI */ +# define DP_DS_DVI_DUAL_LINK (1 << 1) +# define DP_DS_DVI_HIGH_COLOR_DEPTH (1 << 2) +/* offset 3 for HDMI */ +# define DP_DS_HDMI_FRAME_SEQ_TO_FRAME_PACK (1 << 0) +# define DP_DS_HDMI_YCBCR422_PASS_THROUGH (1 << 1) +# define DP_DS_HDMI_YCBCR420_PASS_THROUGH (1 << 2) +# define DP_DS_HDMI_YCBCR444_TO_422_CONV (1 << 3) +# define DP_DS_HDMI_YCBCR444_TO_420_CONV (1 << 4) #define DP_MAX_DOWNSTREAM_PORTS 0x10 @@ -983,6 +1003,16 @@ #define DP_CEC_TX_MESSAGE_BUFFER 0x3020 #define DP_CEC_MESSAGE_BUFFER_LENGTH 0x10 +#define DP_PROTOCOL_CONVERTER_CONTROL_0 0x3050 /* DP 1.3 */ +# define DP_HDMI_DVI_OUTPUT_CONFIG (1 << 0) /* DP 1.3 */ +#define DP_PROTOCOL_CONVERTER_CONTROL_1 0x3051 /* DP 1.3 */ +# define DP_CONVERSION_TO_YCBCR420_ENABLE (1 << 0) /* DP 1.3 */ +# define DP_HDMI_EDID_PROCESSING_DISABLE (1 << 1) /* DP 1.4 */ +# define DP_HDMI_AUTONOMOUS_SCRAMBLING_DISABLE (1 << 2) /* DP 1.4 */ +# define DP_HDMI_FORCE_SCRAMBLING (1 << 3) /* DP 1.4 */ +#define DP_PROTOCOL_CONVERTER_CONTROL_2 0x3052 /* DP 1.3 */ +# define DP_CONVERSION_TO_YCBCR422_ENABLE (1 << 0) /* DP 1.3 */ + #define DP_AUX_HDCP_BKSV 0x68000 #define DP_AUX_HDCP_RI_PRIME 0x68005 #define DP_AUX_HDCP_AKSV 0x68007 @@ -1108,6 +1138,9 @@ #define DP_POWER_DOWN_PHY 0x25 #define DP_SINK_EVENT_NOTIFY 0x30 #define DP_QUERY_STREAM_ENC_STATUS 0x38 +#define DP_QUERY_STREAM_ENC_STATUS_STATE_NO_EXIST 0 +#define DP_QUERY_STREAM_ENC_STATUS_STATE_INACTIVE 1 +#define DP_QUERY_STREAM_ENC_STATUS_STATE_ACTIVE 2 /* DP 1.2 MST sideband reply types */ #define DP_SIDEBAND_REPLY_ACK 0x00 @@ -1134,6 +1167,7 @@ #define DP_MST_PHYSICAL_PORT_0 0 #define DP_MST_LOGICAL_PORT_0 8 +#define DP_LINK_CONSTANT_N_VALUE 0x8000 #define DP_LINK_STATUS_SIZE 6 bool drm_dp_channel_eq_ok(const u8 link_status[DP_LINK_STATUS_SIZE], int lane_count); @@ -1606,19 +1640,60 @@ static inline ssize_t drm_dp_dpcd_writeb(struct drm_dp_aux *aux, return drm_dp_dpcd_write(aux, offset, &value, 1); } +int drm_dp_read_dpcd_caps(struct drm_dp_aux *aux, + u8 dpcd[DP_RECEIVER_CAP_SIZE]); + int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux, u8 status[DP_LINK_STATUS_SIZE]); bool drm_dp_send_real_edid_checksum(struct drm_dp_aux *aux, u8 real_edid_checksum); -int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], - const u8 port_cap[4]); +int drm_dp_read_downstream_info(struct drm_dp_aux *aux, + const u8 dpcd[DP_RECEIVER_CAP_SIZE], + u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS]); +bool drm_dp_downstream_is_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4], u8 type); +bool drm_dp_downstream_is_tmds(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4], + const struct edid *edid); +int drm_dp_downstream_max_dotclock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4]); +int drm_dp_downstream_max_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4], + const struct edid *edid); +int drm_dp_downstream_min_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4], + const struct edid *edid); int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE], - const u8 port_cap[4]); + const u8 port_cap[4], + const struct edid *edid); +bool drm_dp_downstream_420_passthrough(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4]); +bool drm_dp_downstream_444_to_420_conversion(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4]); +struct drm_display_mode *drm_dp_downstream_mode(struct drm_device *dev, + const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4]); int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]); -void drm_dp_downstream_debug(struct seq_file *m, const u8 dpcd[DP_RECEIVER_CAP_SIZE], - const u8 port_cap[4], struct drm_dp_aux *aux); +void drm_dp_downstream_debug(struct seq_file *m, + const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4], + const struct edid *edid, + struct drm_dp_aux *aux); +enum drm_mode_subconnector +drm_dp_subconnector_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4]); +void drm_dp_set_subconnector_property(struct drm_connector *connector, + enum drm_connector_status status, + const u8 *dpcd, + const u8 port_cap[4]); + +struct drm_dp_desc; +bool drm_dp_read_sink_count_cap(struct drm_connector *connector, + const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const struct drm_dp_desc *desc); +int drm_dp_read_sink_count(struct drm_dp_aux *aux); void drm_dp_remote_aux_init(struct drm_dp_aux *aux); void drm_dp_aux_init(struct drm_dp_aux *aux); @@ -1678,7 +1753,8 @@ enum drm_dp_quirk { * @DP_DPCD_QUIRK_NO_SINK_COUNT: * * The device does not set SINK_COUNT to a non-zero value. - * The driver should ignore SINK_COUNT during detection. + * The driver should ignore SINK_COUNT during detection. Note that + * drm_dp_read_sink_count_cap() automatically checks for this quirk. */ DP_DPCD_QUIRK_NO_SINK_COUNT, /** diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h index 8b9eb4db3381..f5e92fe9151c 100644 --- a/include/drm/drm_dp_mst_helper.h +++ b/include/drm/drm_dp_mst_helper.h @@ -313,6 +313,34 @@ struct drm_dp_remote_i2c_write_ack_reply { u8 port_number; }; +struct drm_dp_query_stream_enc_status_ack_reply { + /* Bit[23:16]- Stream Id */ + u8 stream_id; + + /* Bit[15]- Signed */ + bool reply_signed; + + /* Bit[10:8]- Stream Output Sink Type */ + bool unauthorizable_device_present; + bool legacy_device_present; + bool query_capable_device_present; + + /* Bit[12:11]- Stream Output CP Type */ + bool hdcp_1x_device_present; + bool hdcp_2x_device_present; + + /* Bit[4]- Stream Authentication */ + bool auth_completed; + + /* Bit[3]- Stream Encryption */ + bool encryption_enabled; + + /* Bit[2]- Stream Repeater Function Present */ + bool repeater_present; + + /* Bit[1:0]- Stream State */ + u8 state; +}; #define DRM_DP_MAX_SDP_STREAMS 16 struct drm_dp_allocate_payload { @@ -374,6 +402,15 @@ struct drm_dp_remote_i2c_write { u8 *bytes; }; +struct drm_dp_query_stream_enc_status { + u8 stream_id; + u8 client_id[7]; /* 56-bit nonce */ + u8 stream_event; + bool valid_stream_event; + u8 stream_behavior; + u8 valid_stream_behavior; +}; + /* this covers ENUM_RESOURCES, POWER_DOWN_PHY, POWER_UP_PHY */ struct drm_dp_port_number_req { u8 port_number; @@ -422,6 +459,8 @@ struct drm_dp_sideband_msg_req_body { struct drm_dp_remote_i2c_read i2c_read; struct drm_dp_remote_i2c_write i2c_write; + + struct drm_dp_query_stream_enc_status enc_status; } u; }; @@ -444,6 +483,8 @@ struct drm_dp_sideband_msg_reply_body { struct drm_dp_remote_i2c_read_ack_reply remote_i2c_read_ack; struct drm_dp_remote_i2c_read_nak_reply remote_i2c_read_nack; struct drm_dp_remote_i2c_write_ack_reply remote_i2c_write_ack; + + struct drm_dp_query_stream_enc_status_ack_reply enc_status; } u; }; @@ -728,10 +769,9 @@ int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr, void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr); - +bool drm_dp_read_mst_cap(struct drm_dp_aux *aux, const u8 dpcd[DP_RECEIVER_CAP_SIZE]); int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool mst_state); - int drm_dp_mst_hpd_irq(struct drm_dp_mst_topology_mgr *mgr, u8 *esi, bool *handled); @@ -808,6 +848,9 @@ drm_dp_atomic_release_vcpi_slots(struct drm_atomic_state *state, struct drm_dp_mst_port *port); int drm_dp_send_power_updown_phy(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, bool power_up); +int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_port *port, + struct drm_dp_query_stream_enc_status_ack_reply *status); int __must_check drm_dp_mst_atomic_check(struct drm_atomic_state *state); void drm_dp_mst_get_port_malloc(struct drm_dp_mst_port *port); diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index 7116abc1a04e..e57d0440f00f 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h @@ -163,13 +163,12 @@ 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. + * 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 devm_drm_dev_alloc() and drm_dev_register() for + * proper and race-free way to set up a &struct drm_device. * * This is deprecated, do not use! * @@ -589,13 +588,6 @@ struct drm_driver { int dev_priv_size; }; -int drm_dev_init(struct drm_device *dev, - struct drm_driver *driver, - struct device *parent); -int devm_drm_dev_init(struct device *parent, - struct drm_device *dev, - struct drm_driver *driver); - void *__devm_drm_dev_alloc(struct device *parent, struct drm_driver *driver, size_t size, size_t offset); diff --git a/include/drm/drm_dsc.h b/include/drm/drm_dsc.h index 887954cbfc60..732f32740c86 100644 --- a/include/drm/drm_dsc.h +++ b/include/drm/drm_dsc.h @@ -588,7 +588,7 @@ struct drm_dsc_picture_parameter_set { * This structure represents the DSC PPS infoframe required to send the Picture * Parameter Set metadata required before enabling VESA Display Stream * Compression. This is based on the DP Secondary Data Packet structure and - * comprises of SDP Header as defined &struct struct dp_sdp_header in drm_dp_helper.h + * comprises of SDP Header as defined &struct dp_sdp_header in drm_dp_helper.h * and PPS payload defined in &struct drm_dsc_picture_parameter_set. * * @pps_header: Header for PPS as per DP SDP header format of type diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index cfa4f5af49af..b27a0e2169c8 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -517,4 +517,8 @@ void drm_edid_get_monitor_name(struct edid *edid, char *name, struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev, int hsize, int vsize, int fresh, bool rb); +struct drm_display_mode * +drm_display_mode_from_cea_vic(struct drm_device *dev, + u8 video_code); + #endif /* __DRM_EDID_H__ */ diff --git a/include/drm/drm_gem_vram_helper.h b/include/drm/drm_gem_vram_helper.h index 035332f3723f..62cc6e6c3a4f 100644 --- a/include/drm/drm_gem_vram_helper.h +++ b/include/drm/drm_gem_vram_helper.h @@ -9,7 +9,6 @@ #include <drm/drm_modes.h> #include <drm/ttm/ttm_bo_api.h> #include <drm/ttm/ttm_bo_driver.h> -#include <drm/ttm/ttm_placement.h> #include <linux/kernel.h> /* for container_of() */ @@ -20,9 +19,9 @@ struct drm_simple_display_pipe; struct filp; struct vm_area_struct; -#define DRM_GEM_VRAM_PL_FLAG_VRAM TTM_PL_FLAG_VRAM -#define DRM_GEM_VRAM_PL_FLAG_SYSTEM TTM_PL_FLAG_SYSTEM -#define DRM_GEM_VRAM_PL_FLAG_TOPDOWN TTM_PL_FLAG_TOPDOWN +#define DRM_GEM_VRAM_PL_FLAG_SYSTEM (1 << 0) +#define DRM_GEM_VRAM_PL_FLAG_VRAM (1 << 1) +#define DRM_GEM_VRAM_PL_FLAG_TOPDOWN (1 << 2) /* * Buffer-object helpers @@ -101,9 +100,6 @@ u64 drm_gem_vram_mmap_offset(struct drm_gem_vram_object *gbo); s64 drm_gem_vram_offset(struct drm_gem_vram_object *gbo); int drm_gem_vram_pin(struct drm_gem_vram_object *gbo, unsigned long pl_flag); int drm_gem_vram_unpin(struct drm_gem_vram_object *gbo); -void *drm_gem_vram_kmap(struct drm_gem_vram_object *gbo, bool map, - bool *is_iomem); -void drm_gem_vram_kunmap(struct drm_gem_vram_object *gbo); void *drm_gem_vram_vmap(struct drm_gem_vram_object *gbo); void drm_gem_vram_vunmap(struct drm_gem_vram_object *gbo, void *vaddr); diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index a01bc6fac83c..9b4292f229c6 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h @@ -338,7 +338,7 @@ static inline u64 drm_mm_hole_node_end(const struct drm_mm_node *hole_node) /** * drm_mm_nodes - list of nodes under the drm_mm range manager - * @mm: the struct drm_mm range manger + * @mm: the struct drm_mm range manager * * As the drm_mm range manager hides its node_list deep with its * structure, extracting it looks painful and repetitive. This is diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index c2d3d71d133c..a18f73eb3cf6 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h @@ -681,6 +681,12 @@ struct drm_mode_config { struct drm_property *dvi_i_select_subconnector_property; /** + * @dp_subconnector_property: Optional DP property to differentiate + * between different DP downstream port types. + */ + struct drm_property *dp_subconnector_property; + + /** * @tv_subconnector_property: Optional TV property to differentiate * between different TV connector types. */ diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h index eee3c9de6c4f..cdf2a299ccd4 100644 --- a/include/drm/drm_modes.h +++ b/include/drm/drm_modes.h @@ -350,14 +350,15 @@ struct drm_display_mode { u8 type; /** - * @private_flags: + * @expose_to_userspace: * - * Driver private flags. private_flags can only be used for mode - * objects passed to drivers in modeset operations. It shouldn't be used - * by atomic drivers since they can store any additional data by - * subclassing state structures. + * Indicates whether the mode is to be exposed to the userspace. + * This is to maintain a set of exposed modes while preparing + * user-mode's list in drm_mode_getconnector ioctl. The purpose of + * this only lies in the ioctl function, and is not to be used + * outside the function. */ - int private_flags; + bool expose_to_userspace; /** * @head: @@ -367,19 +368,6 @@ struct drm_display_mode { struct list_head head; /** - * @export_head: - * - * struct list_head for modes to be exposed to the userspace. - * This is to maintain a list of exposed modes while preparing - * user-mode's list in drm_mode_getconnector ioctl. The purpose of this - * list_head only lies in the ioctl function, and is not expected to be - * used outside the function. - * Once used, the stale pointers are not reset, but left as it is, to - * avoid overhead of protecting it by mode_config.mutex. - */ - struct list_head export_head; - - /** * @name: * * Human-readable name of the mode, filled out with drm_mode_set_name(). diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index 6193cb555acc..33605c3f0eba 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -35,6 +35,8 @@ struct drm_device; struct drm_panel; struct display_timing; +enum drm_panel_orientation; + /** * struct drm_panel_funcs - perform operations on a given panel * @@ -175,12 +177,9 @@ void drm_panel_init(struct drm_panel *panel, struct device *dev, const struct drm_panel_funcs *funcs, int connector_type); -int drm_panel_add(struct drm_panel *panel); +void drm_panel_add(struct drm_panel *panel); void drm_panel_remove(struct drm_panel *panel); -int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector); -void drm_panel_detach(struct drm_panel *panel); - int drm_panel_prepare(struct drm_panel *panel); int drm_panel_unprepare(struct drm_panel *panel); @@ -191,11 +190,19 @@ int drm_panel_get_modes(struct drm_panel *panel, struct drm_connector *connector #if defined(CONFIG_OF) && defined(CONFIG_DRM_PANEL) struct drm_panel *of_drm_find_panel(const struct device_node *np); +int of_drm_get_panel_orientation(const struct device_node *np, + enum drm_panel_orientation *orientation); #else static inline struct drm_panel *of_drm_find_panel(const struct device_node *np) { return ERR_PTR(-ENODEV); } + +static inline int of_drm_get_panel_orientation(const struct device_node *np, + enum drm_panel_orientation *orientation) +{ + return -ENODEV; +} #endif #if IS_ENABLED(CONFIG_DRM_PANEL) && (IS_BUILTIN(CONFIG_BACKLIGHT_CLASS_DEVICE) || \ diff --git a/include/drm/drm_prime.h b/include/drm/drm_prime.h index 9af7422b44cf..0f69f9fbf12c 100644 --- a/include/drm/drm_prime.h +++ b/include/drm/drm_prime.h @@ -88,10 +88,13 @@ void drm_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr); int drm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma); int drm_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma); -struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int nr_pages); +struct sg_table *drm_prime_pages_to_sg(struct drm_device *dev, + struct page **pages, unsigned int nr_pages); struct dma_buf *drm_gem_prime_export(struct drm_gem_object *obj, int flags); +unsigned long drm_prime_get_contiguous_size(struct sg_table *sgt); + /* helper functions for importing */ struct drm_gem_object *drm_gem_prime_import_dev(struct drm_device *dev, struct dma_buf *dma_buf, diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h index b9780ae9dd26..92436553fd6a 100644 --- a/include/drm/gpu_scheduler.h +++ b/include/drm/gpu_scheduler.h @@ -33,15 +33,16 @@ struct drm_gpu_scheduler; struct drm_sched_rq; +/* These are often used as an (initial) index + * to an array, and as such should start at 0. + */ enum drm_sched_priority { DRM_SCHED_PRIORITY_MIN, - DRM_SCHED_PRIORITY_LOW = DRM_SCHED_PRIORITY_MIN, DRM_SCHED_PRIORITY_NORMAL, - DRM_SCHED_PRIORITY_HIGH_SW, - DRM_SCHED_PRIORITY_HIGH_HW, + DRM_SCHED_PRIORITY_HIGH, DRM_SCHED_PRIORITY_KERNEL, - DRM_SCHED_PRIORITY_MAX, - DRM_SCHED_PRIORITY_INVALID = -1, + + DRM_SCHED_PRIORITY_COUNT, DRM_SCHED_PRIORITY_UNSET = -2 }; @@ -274,7 +275,7 @@ struct drm_gpu_scheduler { uint32_t hw_submission_limit; long timeout; const char *name; - struct drm_sched_rq sched_rq[DRM_SCHED_PRIORITY_MAX]; + struct drm_sched_rq sched_rq[DRM_SCHED_PRIORITY_COUNT]; wait_queue_head_t wake_up_worker; wait_queue_head_t job_scheduled; atomic_t hw_rq_count; diff --git a/include/drm/i915_pciids.h b/include/drm/i915_pciids.h index 96e408b4bdc9..7eeecb07c9a1 100644 --- a/include/drm/i915_pciids.h +++ b/include/drm/i915_pciids.h @@ -258,9 +258,7 @@ INTEL_VGA_DEVICE(0x0f30, info), \ INTEL_VGA_DEVICE(0x0f31, info), \ INTEL_VGA_DEVICE(0x0f32, info), \ - INTEL_VGA_DEVICE(0x0f33, info), \ - INTEL_VGA_DEVICE(0x0157, info), \ - INTEL_VGA_DEVICE(0x0155, info) + INTEL_VGA_DEVICE(0x0f33, info) #define INTEL_BDW_ULT_GT1_IDS(info) \ INTEL_VGA_DEVICE(0x1606, info), /* GT1 ULT */ \ @@ -596,19 +594,25 @@ INTEL_VGA_DEVICE(0x4E51, info) /* TGL */ -#define INTEL_TGL_12_IDS(info) \ +#define INTEL_TGL_12_GT1_IDS(info) \ + INTEL_VGA_DEVICE(0x9A60, info), \ + INTEL_VGA_DEVICE(0x9A68, info), \ + INTEL_VGA_DEVICE(0x9A70, info) + +#define INTEL_TGL_12_GT2_IDS(info) \ INTEL_VGA_DEVICE(0x9A40, info), \ INTEL_VGA_DEVICE(0x9A49, info), \ INTEL_VGA_DEVICE(0x9A59, info), \ - INTEL_VGA_DEVICE(0x9A60, info), \ - INTEL_VGA_DEVICE(0x9A68, info), \ - INTEL_VGA_DEVICE(0x9A70, info), \ INTEL_VGA_DEVICE(0x9A78, info), \ INTEL_VGA_DEVICE(0x9AC0, info), \ INTEL_VGA_DEVICE(0x9AC9, info), \ INTEL_VGA_DEVICE(0x9AD9, info), \ INTEL_VGA_DEVICE(0x9AF8, info) +#define INTEL_TGL_12_IDS(info) \ + INTEL_TGL_12_GT1_IDS(info), \ + INTEL_TGL_12_GT2_IDS(info) + /* RKL */ #define INTEL_RKL_IDS(info) \ INTEL_VGA_DEVICE(0x4C80, info), \ diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h index 71d81923e6b0..abfefaaf897a 100644 --- a/include/drm/intel-gtt.h +++ b/include/drm/intel-gtt.h @@ -5,6 +5,7 @@ #define _DRM_INTEL_GTT_H #include <linux/agp_backend.h> +#include <linux/intel-iommu.h> #include <linux/kernel.h> void intel_gtt_get(u64 *gtt_total, @@ -33,8 +34,4 @@ void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries); /* flag for GFDT type */ #define AGP_USER_CACHED_MEMORY_GFDT (1 << 3) -#ifdef CONFIG_INTEL_IOMMU -extern int intel_iommu_gfx_mapped; -#endif - #endif diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index a9e13b252820..0f7cd21d6d74 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -42,6 +42,8 @@ #include <linux/bitmap.h> #include <linux/dma-resv.h> +#include "ttm_resource.h" + struct ttm_bo_global; struct ttm_bo_device; @@ -55,55 +57,6 @@ struct ttm_place; struct ttm_lru_bulk_move; /** - * struct ttm_bus_placement - * - * @addr: mapped virtual address - * @base: bus base address - * @is_iomem: is this io memory ? - * @size: size in byte - * @offset: offset from the base address - * @io_reserved_vm: The VM system has a refcount in @io_reserved_count - * @io_reserved_count: Refcounting the numbers of callers to ttm_mem_io_reserve - * - * Structure indicating the bus placement of an object. - */ -struct ttm_bus_placement { - void *addr; - phys_addr_t base; - unsigned long size; - unsigned long offset; - bool is_iomem; - bool io_reserved_vm; - uint64_t io_reserved_count; -}; - - -/** - * struct ttm_mem_reg - * - * @mm_node: Memory manager node. - * @size: Requested size of memory region. - * @num_pages: Actual size of memory region in pages. - * @page_alignment: Page alignment. - * @placement: Placement flags. - * @bus: Placement on io bus accessible to the CPU - * - * Structure indicating the placement and space resources used by a - * buffer object. - */ - -struct ttm_mem_reg { - void *mm_node; - unsigned long start; - unsigned long size; - unsigned long num_pages; - uint32_t page_alignment; - uint32_t mem_type; - uint32_t placement; - struct ttm_bus_placement bus; -}; - -/** * enum ttm_bo_type * * @ttm_bo_type_device: These are 'normal' buffers that can @@ -185,10 +138,9 @@ struct ttm_buffer_object { * Members protected by the bo::resv::reserved lock. */ - struct ttm_mem_reg mem; + struct ttm_resource mem; struct file *persistent_swap_storage; struct ttm_tt *ttm; - bool evicted; bool deleted; /** @@ -198,7 +150,6 @@ struct ttm_buffer_object { struct list_head lru; struct list_head ddestroy; struct list_head swap; - struct list_head io_reserve_lru; /** * Members protected by a bo reservation. @@ -314,12 +265,12 @@ int ttm_bo_wait(struct ttm_buffer_object *bo, bool interruptible, bool no_wait); * ttm_bo_mem_compat - Check if proposed placement is compatible with a bo * * @placement: Return immediately if buffer is busy. - * @mem: The struct ttm_mem_reg indicating the region where the bo resides + * @mem: The struct ttm_resource indicating the region where the bo resides * @new_flags: Describes compatible placement found * * Returns true if the placement is compatible */ -bool ttm_bo_mem_compat(struct ttm_placement *placement, struct ttm_mem_reg *mem, +bool ttm_bo_mem_compat(struct ttm_placement *placement, struct ttm_resource *mem, uint32_t *new_flags); /** @@ -400,18 +351,6 @@ void ttm_bo_unlock_delayed_workqueue(struct ttm_bo_device *bdev, int resched); bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, const struct ttm_place *place); -/** - * ttm_bo_acc_size - * - * @bdev: Pointer to a ttm_bo_device struct. - * @bo_size: size of the buffer object in byte. - * @struct_size: size of the structure holding buffer object datas - * - * Returns size to account for a buffer object - */ -size_t ttm_bo_acc_size(struct ttm_bo_device *bdev, - unsigned long bo_size, - unsigned struct_size); size_t ttm_bo_dma_acc_size(struct ttm_bo_device *bdev, unsigned long bo_size, unsigned struct_size); @@ -532,52 +471,6 @@ int ttm_bo_create(struct ttm_bo_device *bdev, unsigned long size, struct ttm_buffer_object **p_bo); /** - * ttm_bo_init_mm - * - * @bdev: Pointer to a ttm_bo_device struct. - * @mem_type: The memory type. - * @p_size: size managed area in pages. - * - * Initialize a manager for a given memory type. - * Note: if part of driver firstopen, it must be protected from a - * potentially racing lastclose. - * Returns: - * -EINVAL: invalid size or memory type. - * -ENOMEM: Not enough memory. - * May also return driver-specified errors. - */ -int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, - unsigned long p_size); - -/** - * ttm_bo_clean_mm - * - * @bdev: Pointer to a ttm_bo_device struct. - * @mem_type: The memory type. - * - * Take down a manager for a given memory type after first walking - * the LRU list to evict any buffers left alive. - * - * Normally, this function is part of lastclose() or unload(), and at that - * point there shouldn't be any buffers left created by user-space, since - * there should've been removed by the file descriptor release() method. - * However, before this function is run, make sure to signal all sync objects, - * and verify that the delayed delete queue is empty. The driver must also - * make sure that there are no NO_EVICT buffers present in this memory type - * when the call is made. - * - * If this function is part of a VT switch, the caller must make sure that - * there are no appications currently validating buffers before this - * function is called. The caller can do that by first taking the - * struct ttm_bo_device::ttm_lock in write mode. - * - * Returns: - * -EINVAL: invalid or uninitialized memory type. - * -EBUSY: There are still buffers left in this memory type. - */ -int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type); - -/** * ttm_bo_evict_mm * * @bdev: Pointer to a ttm_bo_device struct. @@ -713,6 +606,12 @@ static inline bool ttm_bo_uses_embedded_gem_object(struct ttm_buffer_object *bo) return bo->base.dev != NULL; } +int ttm_mem_evict_first(struct ttm_bo_device *bdev, + struct ttm_resource_manager *man, + const struct ttm_place *place, + struct ttm_operation_ctx *ctx, + struct ww_acquire_ctx *ticket); + /* Default number of pre-faulted pages in the TTM fault handler */ #define TTM_BO_VM_NUM_PREFAULT 16 diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 5a37f1cc057e..864afa8f6f18 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -43,171 +43,10 @@ #include "ttm_placement.h" #include "ttm_tt.h" -#define TTM_MAX_BO_PRIORITY 4U - -#define TTM_MEMTYPE_FLAG_FIXED (1 << 0) /* Fixed (on-card) PCI memory */ -#define TTM_MEMTYPE_FLAG_MAPPABLE (1 << 1) /* Memory mappable */ - -struct ttm_mem_type_manager; - -struct ttm_mem_type_manager_func { - /** - * struct ttm_mem_type_manager member init - * - * @man: Pointer to a memory type manager. - * @p_size: Implementation dependent, but typically the size of the - * range to be managed in pages. - * - * Called to initialize a private range manager. The function is - * expected to initialize the man::priv member. - * Returns 0 on success, negative error code on failure. - */ - int (*init)(struct ttm_mem_type_manager *man, unsigned long p_size); - - /** - * struct ttm_mem_type_manager member takedown - * - * @man: Pointer to a memory type manager. - * - * Called to undo the setup done in init. All allocated resources - * should be freed. - */ - int (*takedown)(struct ttm_mem_type_manager *man); - - /** - * struct ttm_mem_type_manager member get_node - * - * @man: Pointer to a memory type manager. - * @bo: Pointer to the buffer object we're allocating space for. - * @placement: Placement details. - * @flags: Additional placement flags. - * @mem: Pointer to a struct ttm_mem_reg to be filled in. - * - * This function should allocate space in the memory type managed - * by @man. Placement details if - * applicable are given by @placement. If successful, - * @mem::mm_node should be set to a non-null value, and - * @mem::start should be set to a value identifying the beginning - * of the range allocated, and the function should return zero. - * If the memory region accommodate the buffer object, @mem::mm_node - * should be set to NULL, and the function should return 0. - * If a system error occurred, preventing the request to be fulfilled, - * the function should return a negative error code. - * - * Note that @mem::mm_node will only be dereferenced by - * struct ttm_mem_type_manager functions and optionally by the driver, - * which has knowledge of the underlying type. - * - * This function may not be called from within atomic context, so - * an implementation can and must use either a mutex or a spinlock to - * protect any data structures managing the space. - */ - int (*get_node)(struct ttm_mem_type_manager *man, - struct ttm_buffer_object *bo, - const struct ttm_place *place, - struct ttm_mem_reg *mem); - - /** - * struct ttm_mem_type_manager member put_node - * - * @man: Pointer to a memory type manager. - * @mem: Pointer to a struct ttm_mem_reg to be filled in. - * - * This function frees memory type resources previously allocated - * and that are identified by @mem::mm_node and @mem::start. May not - * be called from within atomic context. - */ - void (*put_node)(struct ttm_mem_type_manager *man, - struct ttm_mem_reg *mem); - - /** - * struct ttm_mem_type_manager member debug - * - * @man: Pointer to a memory type manager. - * @printer: Prefix to be used in printout to identify the caller. - * - * This function is called to print out the state of the memory - * type manager to aid debugging of out-of-memory conditions. - * It may not be called from within atomic context. - */ - void (*debug)(struct ttm_mem_type_manager *man, - struct drm_printer *printer); -}; - -/** - * struct ttm_mem_type_manager - * - * @has_type: The memory type has been initialized. - * @use_type: The memory type is enabled. - * @flags: TTM_MEMTYPE_XX flags identifying the traits of the memory - * managed by this memory type. - * @gpu_offset: If used, the GPU offset of the first managed page of - * fixed memory or the first managed location in an aperture. - * @size: Size of the managed region. - * @available_caching: A mask of available caching types, TTM_PL_FLAG_XX, - * as defined in ttm_placement_common.h - * @default_caching: The default caching policy used for a buffer object - * placed in this memory type if the user doesn't provide one. - * @func: structure pointer implementing the range manager. See above - * @priv: Driver private closure for @func. - * @io_reserve_mutex: Mutex optionally protecting shared io_reserve structures - * @use_io_reserve_lru: Use an lru list to try to unreserve io_mem_regions - * reserved by the TTM vm system. - * @io_reserve_lru: Optional lru list for unreserving io mem regions. - * @move_lock: lock for move fence - * static information. bdev::driver::io_mem_free is never used. - * @lru: The lru list for this memory type. - * @move: The fence of the last pipelined move operation. - * - * This structure is used to identify and manage memory types for a device. - * It's set up by the ttm_bo_driver::init_mem_type method. - */ - - - -struct ttm_mem_type_manager { - struct ttm_bo_device *bdev; - - /* - * No protection. Constant from start. - */ - - bool has_type; - bool use_type; - uint32_t flags; - uint64_t size; - uint32_t available_caching; - uint32_t default_caching; - const struct ttm_mem_type_manager_func *func; - void *priv; - struct mutex io_reserve_mutex; - bool use_io_reserve_lru; - spinlock_t move_lock; - - /* - * Protected by @io_reserve_mutex: - */ - - struct list_head io_reserve_lru; - - /* - * Protected by the global->lru_lock. - */ - - struct list_head lru[TTM_MAX_BO_PRIORITY]; - - /* - * Protected by @move_lock. - */ - struct dma_fence *move; -}; - /** * struct ttm_bo_driver * * @create_ttm_backend_entry: Callback to create a struct ttm_backend. - * @init_mem_type: Callback to initialize a struct ttm_mem_type_manager - * structure. * @evict_flags: Callback to obtain placement flags when a buffer is evicted. * @move: Callback for a driver to hook in accelerated functions to * move a buffer. @@ -238,8 +77,9 @@ struct ttm_bo_driver { * Returns: * -ENOMEM: Out of memory. */ - int (*ttm_tt_populate)(struct ttm_tt *ttm, - struct ttm_operation_ctx *ctx); + int (*ttm_tt_populate)(struct ttm_bo_device *bdev, + struct ttm_tt *ttm, + struct ttm_operation_ctx *ctx); /** * ttm_tt_unpopulate @@ -248,10 +88,43 @@ struct ttm_bo_driver { * * Free all backing page */ - void (*ttm_tt_unpopulate)(struct ttm_tt *ttm); + void (*ttm_tt_unpopulate)(struct ttm_bo_device *bdev, struct ttm_tt *ttm); - int (*init_mem_type)(struct ttm_bo_device *bdev, uint32_t type, - struct ttm_mem_type_manager *man); + /** + * ttm_tt_bind + * + * @bdev: Pointer to a ttm device + * @ttm: Pointer to a struct ttm_tt. + * @bo_mem: Pointer to a struct ttm_resource describing the + * memory type and location for binding. + * + * Bind the backend pages into the aperture in the location + * indicated by @bo_mem. This function should be able to handle + * differences between aperture and system page sizes. + */ + int (*ttm_tt_bind)(struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct ttm_resource *bo_mem); + + /** + * ttm_tt_unbind + * + * @bdev: Pointer to a ttm device + * @ttm: Pointer to a struct ttm_tt. + * + * Unbind previously bound backend pages. This function should be + * able to handle differences between aperture and system page sizes. + */ + void (*ttm_tt_unbind)(struct ttm_bo_device *bdev, struct ttm_tt *ttm); + + /** + * ttm_tt_destroy + * + * @bdev: Pointer to a ttm device + * @ttm: Pointer to a struct ttm_tt. + * + * Destroy the backend. This will be call back from ttm_tt_destroy so + * don't call ttm_tt_destroy from the callback or infinite loop. + */ + void (*ttm_tt_destroy)(struct ttm_bo_device *bdev, struct ttm_tt *ttm); /** * struct ttm_bo_driver member eviction_valuable @@ -290,7 +163,7 @@ struct ttm_bo_driver { */ int (*move)(struct ttm_buffer_object *bo, bool evict, struct ttm_operation_ctx *ctx, - struct ttm_mem_reg *new_mem); + struct ttm_resource *new_mem); /** * struct ttm_bo_driver_member verify_access @@ -316,7 +189,7 @@ struct ttm_bo_driver { */ void (*move_notify)(struct ttm_buffer_object *bo, bool evict, - struct ttm_mem_reg *new_mem); + struct ttm_resource *new_mem); /* notify the driver we are taking a fault on this BO * and have reserved it */ int (*fault_reserve_notify)(struct ttm_buffer_object *bo); @@ -333,9 +206,9 @@ struct ttm_bo_driver { * are balanced. */ int (*io_mem_reserve)(struct ttm_bo_device *bdev, - struct ttm_mem_reg *mem); + struct ttm_resource *mem); void (*io_mem_free)(struct ttm_bo_device *bdev, - struct ttm_mem_reg *mem); + struct ttm_resource *mem); /** * Return the pfn for a given page_offset inside the BO. @@ -429,7 +302,7 @@ extern struct ttm_bo_global { * struct ttm_bo_device - Buffer object driver device-specific data. * * @driver: Pointer to a struct ttm_bo_driver struct setup by the driver. - * @man: An array of mem_type_managers. + * @man: An array of resource_managers. * @vma_manager: Address space manager (pointer) * lru_lock: Spinlock that protects the buffer+device lru lists and * ddestroy lists. @@ -447,8 +320,11 @@ struct ttm_bo_device { */ struct list_head device_list; struct ttm_bo_driver *driver; - struct ttm_mem_type_manager man[TTM_NUM_MEM_TYPES]; - + /* + * access via ttm_manager_type. + */ + struct ttm_resource_manager sysman; + struct ttm_resource_manager *man_drv[TTM_NUM_MEM_TYPES]; /* * Protected by internal locks. */ @@ -476,6 +352,19 @@ struct ttm_bo_device { bool no_retry; }; +static inline struct ttm_resource_manager *ttm_manager_type(struct ttm_bo_device *bdev, + int mem_type) +{ + return bdev->man_drv[mem_type]; +} + +static inline void ttm_set_driver_manager(struct ttm_bo_device *bdev, + int type, + struct ttm_resource_manager *manager) +{ + bdev->man_drv[type] = manager; +} + /** * struct ttm_lru_bulk_move_pos * @@ -504,23 +393,6 @@ struct ttm_lru_bulk_move { struct ttm_lru_bulk_move_pos swap[TTM_MAX_BO_PRIORITY]; }; -/** - * ttm_flag_masked - * - * @old: Pointer to the result and original value. - * @new: New value of bits. - * @mask: Mask of bits to change. - * - * Convenience function to change a number of bits identified by a mask. - */ - -static inline uint32_t -ttm_flag_masked(uint32_t *old, uint32_t new, uint32_t mask) -{ - *old ^= (*old ^ new) & mask; - return *old; -} - /* * ttm_bo.c */ @@ -531,7 +403,7 @@ ttm_flag_masked(uint32_t *old, uint32_t new, uint32_t mask) * @bo: Pointer to a struct ttm_buffer_object. the data of which * we want to allocate space for. * @proposed_placement: Proposed new placement for the buffer object. - * @mem: A struct ttm_mem_reg. + * @mem: A struct ttm_resource. * @interruptible: Sleep interruptible when sliping. * @no_wait_gpu: Return immediately if the GPU is busy. * @@ -546,11 +418,9 @@ ttm_flag_masked(uint32_t *old, uint32_t new, uint32_t mask) */ int ttm_bo_mem_space(struct ttm_buffer_object *bo, struct ttm_placement *placement, - struct ttm_mem_reg *mem, + struct ttm_resource *mem, struct ttm_operation_ctx *ctx); -void ttm_bo_mem_put(struct ttm_buffer_object *bo, struct ttm_mem_reg *mem); - int ttm_bo_device_release(struct ttm_bo_device *bdev); /** @@ -591,35 +461,31 @@ void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo); */ void ttm_bo_unmap_virtual_locked(struct ttm_buffer_object *bo); -int ttm_mem_io_reserve_vm(struct ttm_buffer_object *bo); -void ttm_mem_io_free_vm(struct ttm_buffer_object *bo); -int ttm_mem_io_lock(struct ttm_mem_type_manager *man, bool interruptible); -void ttm_mem_io_unlock(struct ttm_mem_type_manager *man); - /** - * __ttm_bo_reserve: + * ttm_bo_reserve: * * @bo: A pointer to a struct ttm_buffer_object. * @interruptible: Sleep interruptible if waiting. * @no_wait: Don't sleep while trying to reserve, rather return -EBUSY. * @ticket: ticket used to acquire the ww_mutex. * - * Will not remove reserved buffers from the lru lists. - * Otherwise identical to ttm_bo_reserve. + * Locks a buffer object for validation. (Or prevents other processes from + * locking it for validation), while taking a number of measures to prevent + * deadlocks. * * Returns: * -EDEADLK: The reservation may cause a deadlock. * Release all buffer reservations, wait for @bo to become unreserved and - * try again. (only if use_sequence == 1). + * try again. * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by * a signal. Release all buffer reservations and return to user-space. * -EBUSY: The function needed to sleep, but @no_wait was true * -EALREADY: Bo already reserved using @ticket. This error code will only * be returned if @use_ticket is set to true. */ -static inline int __ttm_bo_reserve(struct ttm_buffer_object *bo, - bool interruptible, bool no_wait, - struct ww_acquire_ctx *ticket) +static inline int ttm_bo_reserve(struct ttm_buffer_object *bo, + bool interruptible, bool no_wait, + struct ww_acquire_ctx *ticket) { int ret = 0; @@ -642,59 +508,6 @@ static inline int __ttm_bo_reserve(struct ttm_buffer_object *bo, } /** - * ttm_bo_reserve: - * - * @bo: A pointer to a struct ttm_buffer_object. - * @interruptible: Sleep interruptible if waiting. - * @no_wait: Don't sleep while trying to reserve, rather return -EBUSY. - * @ticket: ticket used to acquire the ww_mutex. - * - * Locks a buffer object for validation. (Or prevents other processes from - * locking it for validation) and removes it from lru lists, while taking - * a number of measures to prevent deadlocks. - * - * Deadlocks may occur when two processes try to reserve multiple buffers in - * different order, either by will or as a result of a buffer being evicted - * to make room for a buffer already reserved. (Buffers are reserved before - * they are evicted). The following algorithm prevents such deadlocks from - * occurring: - * Processes attempting to reserve multiple buffers other than for eviction, - * (typically execbuf), should first obtain a unique 32-bit - * validation sequence number, - * and call this function with @use_ticket == 1 and @ticket->stamp == the unique - * sequence number. If upon call of this function, the buffer object is already - * reserved, the validation sequence is checked against the validation - * sequence of the process currently reserving the buffer, - * and if the current validation sequence is greater than that of the process - * holding the reservation, the function returns -EDEADLK. Otherwise it sleeps - * waiting for the buffer to become unreserved, after which it retries - * reserving. - * The caller should, when receiving an -EDEADLK error - * release all its buffer reservations, wait for @bo to become unreserved, and - * then rerun the validation with the same validation sequence. This procedure - * will always guarantee that the process with the lowest validation sequence - * will eventually succeed, preventing both deadlocks and starvation. - * - * Returns: - * -EDEADLK: The reservation may cause a deadlock. - * Release all buffer reservations, wait for @bo to become unreserved and - * try again. (only if use_sequence == 1). - * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by - * a signal. Release all buffer reservations and return to user-space. - * -EBUSY: The function needed to sleep, but @no_wait was true - * -EALREADY: Bo already reserved using @ticket. This error code will only - * be returned if @use_ticket is set to true. - */ -static inline int ttm_bo_reserve(struct ttm_buffer_object *bo, - bool interruptible, bool no_wait, - struct ww_acquire_ctx *ticket) -{ - WARN_ON(!kref_read(&bo->kref)); - - return __ttm_bo_reserve(bo, interruptible, no_wait, ticket); -} - -/** * ttm_bo_reserve_slowpath: * @bo: A pointer to a struct ttm_buffer_object. * @interruptible: Sleep interruptible if waiting. @@ -708,20 +521,45 @@ static inline int ttm_bo_reserve_slowpath(struct ttm_buffer_object *bo, bool interruptible, struct ww_acquire_ctx *ticket) { - int ret = 0; + if (interruptible) { + int ret = dma_resv_lock_slow_interruptible(bo->base.resv, + ticket); + if (ret == -EINTR) + ret = -ERESTARTSYS; + return ret; + } + dma_resv_lock_slow(bo->base.resv, ticket); + return 0; +} - WARN_ON(!kref_read(&bo->kref)); +static inline void ttm_bo_move_to_lru_tail_unlocked(struct ttm_buffer_object *bo) +{ + spin_lock(&ttm_bo_glob.lru_lock); + ttm_bo_move_to_lru_tail(bo, NULL); + spin_unlock(&ttm_bo_glob.lru_lock); +} - if (interruptible) - ret = dma_resv_lock_slow_interruptible(bo->base.resv, - ticket); - else - dma_resv_lock_slow(bo->base.resv, ticket); +static inline void ttm_bo_assign_mem(struct ttm_buffer_object *bo, + struct ttm_resource *new_mem) +{ + bo->mem = *new_mem; + new_mem->mm_node = NULL; +} - if (ret == -EINTR) - ret = -ERESTARTSYS; +/** + * ttm_bo_move_null = assign memory for a buffer object. + * @bo: The bo to assign the memory to + * @new_mem: The memory to be assigned. + * + * Assign the memory from new_mem to the memory of the buffer object bo. + */ +static inline void ttm_bo_move_null(struct ttm_buffer_object *bo, + struct ttm_resource *new_mem) +{ + struct ttm_resource *old_mem = &bo->mem; - return ret; + WARN_ON(old_mem->mm_node != NULL); + ttm_bo_assign_mem(bo, new_mem); } /** @@ -733,9 +571,7 @@ static inline int ttm_bo_reserve_slowpath(struct ttm_buffer_object *bo, */ static inline void ttm_bo_unreserve(struct ttm_buffer_object *bo) { - spin_lock(&ttm_bo_glob.lru_lock); - ttm_bo_move_to_lru_tail(bo, NULL); - spin_unlock(&ttm_bo_glob.lru_lock); + ttm_bo_move_to_lru_tail_unlocked(bo); dma_resv_unlock(bo->base.resv); } @@ -744,16 +580,16 @@ static inline void ttm_bo_unreserve(struct ttm_buffer_object *bo) */ int ttm_mem_io_reserve(struct ttm_bo_device *bdev, - struct ttm_mem_reg *mem); + struct ttm_resource *mem); void ttm_mem_io_free(struct ttm_bo_device *bdev, - struct ttm_mem_reg *mem); + struct ttm_resource *mem); /** * ttm_bo_move_ttm * * @bo: A pointer to a struct ttm_buffer_object. * @interruptible: Sleep interruptible if waiting. * @no_wait_gpu: Return immediately if the GPU is busy. - * @new_mem: struct ttm_mem_reg indicating where to move. + * @new_mem: struct ttm_resource indicating where to move. * * Optimized move function for a buffer object with both old and * new placement backed by a TTM. The function will, if successful, @@ -767,7 +603,7 @@ void ttm_mem_io_free(struct ttm_bo_device *bdev, int ttm_bo_move_ttm(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx, - struct ttm_mem_reg *new_mem); + struct ttm_resource *new_mem); /** * ttm_bo_move_memcpy @@ -775,7 +611,7 @@ int ttm_bo_move_ttm(struct ttm_buffer_object *bo, * @bo: A pointer to a struct ttm_buffer_object. * @interruptible: Sleep interruptible if waiting. * @no_wait_gpu: Return immediately if the GPU is busy. - * @new_mem: struct ttm_mem_reg indicating where to move. + * @new_mem: struct ttm_resource indicating where to move. * * Fallback move function for a mappable buffer object in mappable memory. * The function will, if successful, @@ -789,7 +625,7 @@ int ttm_bo_move_ttm(struct ttm_buffer_object *bo, int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx, - struct ttm_mem_reg *new_mem); + struct ttm_resource *new_mem); /** * ttm_bo_free_old_node @@ -806,7 +642,8 @@ void ttm_bo_free_old_node(struct ttm_buffer_object *bo); * @bo: A pointer to a struct ttm_buffer_object. * @fence: A fence object that signals when moving is complete. * @evict: This is an evict move. Don't return until the buffer is idle. - * @new_mem: struct ttm_mem_reg indicating where to move. + * @pipeline: evictions are to be pipelined. + * @new_mem: struct ttm_resource indicating where to move. * * Accelerated move function to be called when an accelerated move * has been scheduled. The function will create a new temporary buffer object @@ -817,22 +654,8 @@ void ttm_bo_free_old_node(struct ttm_buffer_object *bo); */ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, struct dma_fence *fence, bool evict, - struct ttm_mem_reg *new_mem); - -/** - * ttm_bo_pipeline_move. - * - * @bo: A pointer to a struct ttm_buffer_object. - * @fence: A fence object that signals when moving is complete. - * @evict: This is an evict move. Don't return until the buffer is idle. - * @new_mem: struct ttm_mem_reg indicating where to move. - * - * Function for pipelining accelerated moves. Either free the memory - * immediately or hang it on a temporary buffer object. - */ -int ttm_bo_pipeline_move(struct ttm_buffer_object *bo, - struct dma_fence *fence, bool evict, - struct ttm_mem_reg *new_mem); + bool pipeline, + struct ttm_resource *new_mem); /** * ttm_bo_pipeline_gutting. @@ -854,6 +677,49 @@ int ttm_bo_pipeline_gutting(struct ttm_buffer_object *bo); */ pgprot_t ttm_io_prot(uint32_t caching_flags, pgprot_t tmp); -extern const struct ttm_mem_type_manager_func ttm_bo_manager_func; +/** + * ttm_bo_tt_bind + * + * Bind the object tt to a memory resource. + */ +int ttm_bo_tt_bind(struct ttm_buffer_object *bo, struct ttm_resource *mem); + +/** + * ttm_bo_tt_bind + * + * Unbind the object tt from a memory resource. + */ +void ttm_bo_tt_unbind(struct ttm_buffer_object *bo); + +/** + * ttm_bo_tt_destroy. + */ +void ttm_bo_tt_destroy(struct ttm_buffer_object *bo); + +/** + * ttm_range_man_init + * + * @bdev: ttm device + * @type: memory manager type + * @use_tt: if the memory manager uses tt + * @p_size: size of area to be managed in pages. + * + * Initialise a generic range manager for the selected memory type. + * The range manager is installed for this device in the type slot. + */ +int ttm_range_man_init(struct ttm_bo_device *bdev, + unsigned type, bool use_tt, + unsigned long p_size); + +/** + * ttm_range_man_fini + * + * @bdev: ttm device + * @type: memory manager type + * + * Remove the generic range manager from a slot and tear it down. + */ +int ttm_range_man_fini(struct ttm_bo_device *bdev, + unsigned type); #endif diff --git a/include/drm/ttm/ttm_execbuf_util.h b/include/drm/ttm/ttm_execbuf_util.h index 5a19843bb80d..a99d7fdf2964 100644 --- a/include/drm/ttm/ttm_execbuf_util.h +++ b/include/drm/ttm/ttm_execbuf_util.h @@ -58,9 +58,8 @@ struct ttm_validate_buffer { * Undoes all buffer validation reservations for bos pointed to by * the list entries. */ - -extern void ttm_eu_backoff_reservation(struct ww_acquire_ctx *ticket, - struct list_head *list); +void ttm_eu_backoff_reservation(struct ww_acquire_ctx *ticket, + struct list_head *list); /** * function ttm_eu_reserve_buffers @@ -96,10 +95,9 @@ extern void ttm_eu_backoff_reservation(struct ww_acquire_ctx *ticket, * ttm_eu_fence_buffer_objects() when command submission is complete or * has failed. */ - -extern int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket, - struct list_head *list, bool intr, - struct list_head *dups); +int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket, + struct list_head *list, bool intr, + struct list_head *dups); /** * function ttm_eu_fence_buffer_objects. @@ -113,9 +111,8 @@ extern int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket, * It also unreserves all buffers, putting them on lru lists. * */ - -extern void ttm_eu_fence_buffer_objects(struct ww_acquire_ctx *ticket, - struct list_head *list, - struct dma_fence *fence); +void ttm_eu_fence_buffer_objects(struct ww_acquire_ctx *ticket, + struct list_head *list, + struct dma_fence *fence); #endif diff --git a/include/drm/ttm/ttm_memory.h b/include/drm/ttm/ttm_memory.h index c78ea99c42cf..c1f167881e33 100644 --- a/include/drm/ttm/ttm_memory.h +++ b/include/drm/ttm/ttm_memory.h @@ -79,19 +79,17 @@ extern struct ttm_mem_global { #endif } ttm_mem_glob; -extern int ttm_mem_global_init(struct ttm_mem_global *glob); -extern void ttm_mem_global_release(struct ttm_mem_global *glob); -extern int ttm_mem_global_alloc(struct ttm_mem_global *glob, uint64_t memory, +int ttm_mem_global_init(struct ttm_mem_global *glob); +void ttm_mem_global_release(struct ttm_mem_global *glob); +int ttm_mem_global_alloc(struct ttm_mem_global *glob, uint64_t memory, + struct ttm_operation_ctx *ctx); +void ttm_mem_global_free(struct ttm_mem_global *glob, uint64_t amount); +int ttm_mem_global_alloc_page(struct ttm_mem_global *glob, + struct page *page, uint64_t size, + struct ttm_operation_ctx *ctx); +void ttm_mem_global_free_page(struct ttm_mem_global *glob, + struct page *page, uint64_t size); +size_t ttm_round_pot(size_t size); +bool ttm_check_under_lowerlimit(struct ttm_mem_global *glob, uint64_t num_pages, struct ttm_operation_ctx *ctx); -extern void ttm_mem_global_free(struct ttm_mem_global *glob, - uint64_t amount); -extern int ttm_mem_global_alloc_page(struct ttm_mem_global *glob, - struct page *page, uint64_t size, - struct ttm_operation_ctx *ctx); -extern void ttm_mem_global_free_page(struct ttm_mem_global *glob, - struct page *page, uint64_t size); -extern size_t ttm_round_pot(size_t size); -extern uint64_t ttm_get_kernel_zone_memory_size(struct ttm_mem_global *glob); -extern bool ttm_check_under_lowerlimit(struct ttm_mem_global *glob, - uint64_t num_pages, struct ttm_operation_ctx *ctx); #endif diff --git a/include/drm/ttm/ttm_placement.h b/include/drm/ttm/ttm_placement.h index e88a8e39767b..d4022655eae4 100644 --- a/include/drm/ttm/ttm_placement.h +++ b/include/drm/ttm/ttm_placement.h @@ -42,12 +42,6 @@ #define TTM_PL_VRAM 2 #define TTM_PL_PRIV 3 -#define TTM_PL_FLAG_SYSTEM (1 << TTM_PL_SYSTEM) -#define TTM_PL_FLAG_TT (1 << TTM_PL_TT) -#define TTM_PL_FLAG_VRAM (1 << TTM_PL_VRAM) -#define TTM_PL_FLAG_PRIV (1 << TTM_PL_PRIV) -#define TTM_PL_MASK_MEM 0x0000FFFF - /* * Other flags that affects data placement. * TTM_PL_FLAG_CACHED indicates cache-coherent mappings @@ -71,8 +65,6 @@ TTM_PL_FLAG_UNCACHED | \ TTM_PL_FLAG_WC) -#define TTM_PL_MASK_MEMTYPE (TTM_PL_MASK_MEM | TTM_PL_MASK_CACHING) - /** * struct ttm_place * @@ -85,6 +77,7 @@ struct ttm_place { unsigned fpfn; unsigned lpfn; + uint32_t mem_type; uint32_t flags; }; diff --git a/include/drm/ttm/ttm_resource.h b/include/drm/ttm/ttm_resource.h new file mode 100644 index 000000000000..0e172d94a0c1 --- /dev/null +++ b/include/drm/ttm/ttm_resource.h @@ -0,0 +1,237 @@ +/* + * Copyright 2020 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Christian König + */ + +#ifndef _TTM_RESOURCE_H_ +#define _TTM_RESOURCE_H_ + +#include <linux/types.h> +#include <linux/mutex.h> +#include <linux/dma-fence.h> +#include <drm/drm_print.h> + +#define TTM_MAX_BO_PRIORITY 4U + +struct ttm_bo_device; +struct ttm_resource_manager; +struct ttm_resource; +struct ttm_place; +struct ttm_buffer_object; + +struct ttm_resource_manager_func { + /** + * struct ttm_resource_manager_func member alloc + * + * @man: Pointer to a memory type manager. + * @bo: Pointer to the buffer object we're allocating space for. + * @placement: Placement details. + * @flags: Additional placement flags. + * @mem: Pointer to a struct ttm_resource to be filled in. + * + * This function should allocate space in the memory type managed + * by @man. Placement details if + * applicable are given by @placement. If successful, + * @mem::mm_node should be set to a non-null value, and + * @mem::start should be set to a value identifying the beginning + * of the range allocated, and the function should return zero. + * If the memory region accommodate the buffer object, @mem::mm_node + * should be set to NULL, and the function should return 0. + * If a system error occurred, preventing the request to be fulfilled, + * the function should return a negative error code. + * + * Note that @mem::mm_node will only be dereferenced by + * struct ttm_resource_manager functions and optionally by the driver, + * which has knowledge of the underlying type. + * + * This function may not be called from within atomic context, so + * an implementation can and must use either a mutex or a spinlock to + * protect any data structures managing the space. + */ + int (*alloc)(struct ttm_resource_manager *man, + struct ttm_buffer_object *bo, + const struct ttm_place *place, + struct ttm_resource *mem); + + /** + * struct ttm_resource_manager_func member free + * + * @man: Pointer to a memory type manager. + * @mem: Pointer to a struct ttm_resource to be filled in. + * + * This function frees memory type resources previously allocated + * and that are identified by @mem::mm_node and @mem::start. May not + * be called from within atomic context. + */ + void (*free)(struct ttm_resource_manager *man, + struct ttm_resource *mem); + + /** + * struct ttm_resource_manager_func member debug + * + * @man: Pointer to a memory type manager. + * @printer: Prefix to be used in printout to identify the caller. + * + * This function is called to print out the state of the memory + * type manager to aid debugging of out-of-memory conditions. + * It may not be called from within atomic context. + */ + void (*debug)(struct ttm_resource_manager *man, + struct drm_printer *printer); +}; + +/** + * struct ttm_resource_manager + * + * @use_type: The memory type is enabled. + * @flags: TTM_MEMTYPE_XX flags identifying the traits of the memory + * managed by this memory type. + * @gpu_offset: If used, the GPU offset of the first managed page of + * fixed memory or the first managed location in an aperture. + * @size: Size of the managed region. + * @func: structure pointer implementing the range manager. See above + * @move_lock: lock for move fence + * static information. bdev::driver::io_mem_free is never used. + * @lru: The lru list for this memory type. + * @move: The fence of the last pipelined move operation. + * + * This structure is used to identify and manage memory types for a device. + */ +struct ttm_resource_manager { + /* + * No protection. Constant from start. + */ + bool use_type; + bool use_tt; + uint64_t size; + const struct ttm_resource_manager_func *func; + spinlock_t move_lock; + + /* + * Protected by the global->lru_lock. + */ + + struct list_head lru[TTM_MAX_BO_PRIORITY]; + + /* + * Protected by @move_lock. + */ + struct dma_fence *move; +}; + +/** + * struct ttm_bus_placement + * + * @addr: mapped virtual address + * @offset: physical addr + * @is_iomem: is this io memory ? + * + * Structure indicating the bus placement of an object. + */ +struct ttm_bus_placement { + void *addr; + phys_addr_t offset; + bool is_iomem; +}; + +/** + * struct ttm_resource + * + * @mm_node: Memory manager node. + * @size: Requested size of memory region. + * @num_pages: Actual size of memory region in pages. + * @page_alignment: Page alignment. + * @placement: Placement flags. + * @bus: Placement on io bus accessible to the CPU + * + * Structure indicating the placement and space resources used by a + * buffer object. + */ +struct ttm_resource { + void *mm_node; + unsigned long start; + unsigned long size; + unsigned long num_pages; + uint32_t page_alignment; + uint32_t mem_type; + uint32_t placement; + struct ttm_bus_placement bus; +}; + +/** + * ttm_resource_manager_set_used + * + * @man: A memory manager object. + * @used: usage state to set. + * + * Set the manager in use flag. If disabled the manager is no longer + * used for object placement. + */ +static inline void +ttm_resource_manager_set_used(struct ttm_resource_manager *man, bool used) +{ + man->use_type = used; +} + +/** + * ttm_resource_manager_used + * + * @man: Manager to get used state for + * + * Get the in use flag for a manager. + * Returns: + * true is used, false if not. + */ +static inline bool ttm_resource_manager_used(struct ttm_resource_manager *man) +{ + return man->use_type; +} + +/** + * ttm_resource_manager_cleanup + * + * @man: A memory manager object. + * + * Cleanup the move fences from the memory manager object. + */ +static inline void +ttm_resource_manager_cleanup(struct ttm_resource_manager *man) +{ + dma_fence_put(man->move); + man->move = NULL; +} + +int ttm_resource_alloc(struct ttm_buffer_object *bo, + const struct ttm_place *place, + struct ttm_resource *res); +void ttm_resource_free(struct ttm_buffer_object *bo, struct ttm_resource *res); + +void ttm_resource_manager_init(struct ttm_resource_manager *man, + unsigned long p_size); + +int ttm_resource_manager_force_list_clean(struct ttm_bo_device *bdev, + struct ttm_resource_manager *man); + +void ttm_resource_manager_debug(struct ttm_resource_manager *man, + struct drm_printer *p); + +#endif diff --git a/include/drm/ttm/ttm_tt.h b/include/drm/ttm/ttm_tt.h index 5e2393fe42c6..75208c0a0cac 100644 --- a/include/drm/ttm/ttm_tt.h +++ b/include/drm/ttm/ttm_tt.h @@ -30,7 +30,7 @@ #include <linux/types.h> struct ttm_tt; -struct ttm_mem_reg; +struct ttm_resource; struct ttm_buffer_object; struct ttm_operation_ctx; @@ -42,54 +42,17 @@ struct ttm_operation_ctx; #define TTM_PAGE_FLAG_SG (1 << 8) #define TTM_PAGE_FLAG_NO_RETRY (1 << 9) +#define TTM_PAGE_FLAG_PRIV_POPULATED (1 << 31) + enum ttm_caching_state { tt_uncached, tt_wc, tt_cached }; -struct ttm_backend_func { - /** - * struct ttm_backend_func member bind - * - * @ttm: Pointer to a struct ttm_tt. - * @bo_mem: Pointer to a struct ttm_mem_reg describing the - * memory type and location for binding. - * - * Bind the backend pages into the aperture in the location - * indicated by @bo_mem. This function should be able to handle - * differences between aperture and system page sizes. - */ - int (*bind) (struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem); - - /** - * struct ttm_backend_func member unbind - * - * @ttm: Pointer to a struct ttm_tt. - * - * Unbind previously bound backend pages. This function should be - * able to handle differences between aperture and system page sizes. - */ - void (*unbind) (struct ttm_tt *ttm); - - /** - * struct ttm_backend_func member destroy - * - * @ttm: Pointer to a struct ttm_tt. - * - * Destroy the backend. This will be call back from ttm_tt_destroy so - * don't call ttm_tt_destroy from the callback or infinite loop. - */ - void (*destroy) (struct ttm_tt *ttm); -}; - /** * struct ttm_tt * - * @bdev: Pointer to a struct ttm_bo_device. - * @func: Pointer to a struct ttm_backend_func that describes - * the backend methods. - * pointer. * @pages: Array of pages backing the data. * @num_pages: Number of pages in the page array. * @bdev: Pointer to the current struct ttm_bo_device. @@ -103,21 +66,29 @@ struct ttm_backend_func { * memory. */ struct ttm_tt { - struct ttm_bo_device *bdev; - struct ttm_backend_func *func; struct page **pages; uint32_t page_flags; unsigned long num_pages; struct sg_table *sg; /* for SG objects via dma-buf */ struct file *swap_storage; enum ttm_caching_state caching_state; - enum { - tt_bound, - tt_unbound, - tt_unpopulated, - } state; }; +static inline bool ttm_tt_is_populated(struct ttm_tt *tt) +{ + return tt->page_flags & TTM_PAGE_FLAG_PRIV_POPULATED; +} + +static inline void ttm_tt_set_unpopulated(struct ttm_tt *tt) +{ + tt->page_flags &= ~TTM_PAGE_FLAG_PRIV_POPULATED; +} + +static inline void ttm_tt_set_populated(struct ttm_tt *tt) +{ + tt->page_flags |= TTM_PAGE_FLAG_PRIV_POPULATED; +} + /** * struct ttm_dma_tt * @@ -176,33 +147,20 @@ void ttm_tt_fini(struct ttm_tt *ttm); void ttm_dma_tt_fini(struct ttm_dma_tt *ttm_dma); /** - * ttm_ttm_bind: - * - * @ttm: The struct ttm_tt containing backing pages. - * @bo_mem: The struct ttm_mem_reg identifying the binding location. - * - * Bind the pages of @ttm to an aperture location identified by @bo_mem - */ -int ttm_tt_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem, - struct ttm_operation_ctx *ctx); - -/** * ttm_ttm_destroy: * * @ttm: The struct ttm_tt. * * Unbind, unpopulate and destroy common struct ttm_tt. */ -void ttm_tt_destroy(struct ttm_tt *ttm); +void ttm_tt_destroy(struct ttm_bo_device *bdev, struct ttm_tt *ttm); /** - * ttm_ttm_unbind: - * - * @ttm: The struct ttm_tt. + * ttm_tt_destroy_common: * - * Unbind a struct ttm_tt. + * Called from driver to destroy common path. */ -void ttm_tt_unbind(struct ttm_tt *ttm); +void ttm_tt_destroy_common(struct ttm_bo_device *bdev, struct ttm_tt *ttm); /** * ttm_tt_swapin: @@ -227,7 +185,7 @@ int ttm_tt_swapin(struct ttm_tt *ttm); * and cache flushes and potential page splitting / combining. */ int ttm_tt_set_placement_caching(struct ttm_tt *ttm, uint32_t placement); -int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage); +int ttm_tt_swapout(struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct file *persistent_swap_storage); /** * ttm_tt_populate - allocate pages for a ttm @@ -236,7 +194,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage); * * Calls the driver method to allocate pages for a ttm */ -int ttm_tt_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx); +int ttm_tt_populate(struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct ttm_operation_ctx *ctx); /** * ttm_tt_unpopulate - free pages from a ttm @@ -245,7 +203,7 @@ int ttm_tt_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx); * * Calls the driver method to free all pages from a ttm */ -void ttm_tt_unpopulate(struct ttm_tt *ttm); +void ttm_tt_unpopulate(struct ttm_bo_device *bdev, struct ttm_tt *ttm); #if IS_ENABLED(CONFIG_AGP) #include <linux/agp_backend.h> @@ -265,8 +223,10 @@ void ttm_tt_unpopulate(struct ttm_tt *ttm); struct ttm_tt *ttm_agp_tt_create(struct ttm_buffer_object *bo, struct agp_bridge_data *bridge, uint32_t page_flags); -int ttm_agp_tt_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx); -void ttm_agp_tt_unpopulate(struct ttm_tt *ttm); +int ttm_agp_bind(struct ttm_tt *ttm, struct ttm_resource *bo_mem); +void ttm_agp_unbind(struct ttm_tt *ttm); +void ttm_agp_destroy(struct ttm_tt *ttm); +bool ttm_agp_is_bound(struct ttm_tt *ttm); #endif #endif |