Pull drm fixes from Dave Airlie: "Exynos, i915 and msm fixes and one core fix. exynos: hdmi power off and mixer issues msm: iommu, build fixes, i915: regression races and warning fixes" * 'drm-fixes' of git://people.freedesktop.org/~airlied/linux: (22 commits) drm/i915: vlv_prepare_pll is only needed in case of non DSI interfaces drm: fix NULL pointer access by wrong ioctl drm/exynos: enable vsync interrupt while waiting for vblank drm/exynos: soft reset mixer before reconfigure after power-on drm/exynos: allow multiple layer updates per vsync for mixer drm/i915: Hold the table lock whilst walking the file's idr and counting the objects in debugfs drm/i915: BDW: Adding Reserved PCI IDs. drm/i915: Only mark the ctx as initialised after a SET_CONTEXT operation drm/exynos: stop mixer before gating clocks during poweroff drm/exynos: set power state variable after enabling clocks and power drm/exynos: disable unused windows on apply drm/exynos: Fix de-registration ordering drm/exynos: change zero to NULL for sparse drm/exynos: dpi: Fix NULL pointer dereference with legacy bindings drm/exynos: hdmi: fix power order issue drm/i915: default to having backlight if VBT not available drm/i915: cache hw power well enabled state drm/msm: fix IOMMU cleanup for -EPROBE_DEFER drm/msm: use PAGE_ALIGNED instead of IS_ALIGNED(PAGE_SIZE) drm/msm/hdmi: set hdp clock rate before prepare_enable ...
Unified · Split
| @@ -419,8 +419,9 @@ long drm_ioctl(struct file *filp, · 418 unmodified lines | |||
| 419 | retcode = -EFAULT; | 419 | retcode = -EFAULT; |
| 420 | goto err_i1; | 420 | goto err_i1; |
| 421 | } | 421 | } |
| 422 | } else | 422 | } else if (cmd & IOC_OUT) { |
| 423 | memset(kdata, 0, usize); | 423 | memset(kdata, 0, usize); |
| 424 | } | ||
| 424 | 425 | ||
| 425 | if (ioctl->flags & DRM_UNLOCKED) | 426 | if (ioctl->flags & DRM_UNLOCKED) |
| 426 | retcode = func(dev, kdata, file_priv); | 427 | retcode = func(dev, kdata, file_priv); |
| @@ -40,7 +40,7 @@ exynos_dpi_detect(struct drm_connector *connector, bool force) · 39 unmodified lines | |||
| 40 | { | 40 | { |
| 41 | struct exynos_dpi *ctx = connector_to_dpi(connector); | 41 | struct exynos_dpi *ctx = connector_to_dpi(connector); |
| 42 | 42 | ||
| 43 | if (!ctx->panel->connector) | 43 | if (ctx->panel && !ctx->panel->connector) |
| 44 | drm_panel_attach(ctx->panel, &ctx->connector); | 44 | drm_panel_attach(ctx->panel, &ctx->connector); |
| 45 | 45 | ||
| 46 | return connector_status_connected; | 46 | return connector_status_connected; |
| @@ -765,24 +765,24 @@ static int exynos_drm_init(void) · 764 unmodified lines | |||
| 765 | 765 | ||
| 766 | return 0; | 766 | return 0; |
| 767 | 767 | ||
| 768 | err_unregister_pd: | ||
| 769 | platform_device_unregister(exynos_drm_pdev); | ||
| 770 | |||
| 771 | err_remove_vidi: | 768 | err_remove_vidi: |
| 772 | #ifdef CONFIG_DRM_EXYNOS_VIDI | 769 | #ifdef CONFIG_DRM_EXYNOS_VIDI |
| 773 | exynos_drm_remove_vidi(); | 770 | exynos_drm_remove_vidi(); |
| 771 | |||
| 772 | err_unregister_pd: | ||
| 774 | #endif | 773 | #endif |
| 774 | platform_device_unregister(exynos_drm_pdev); | ||
| 775 | 775 | ||
| 776 | return ret; | 776 | return ret; |
| 777 | } | 777 | } |
| 778 | 778 | ||
| 779 | static void exynos_drm_exit(void) | 779 | static void exynos_drm_exit(void) |
| 780 | { | 780 | { |
| 781 | platform_driver_unregister(&exynos_drm_platform_driver); | ||
| 781 | #ifdef CONFIG_DRM_EXYNOS_VIDI | 782 | #ifdef CONFIG_DRM_EXYNOS_VIDI |
| 782 | exynos_drm_remove_vidi(); | 783 | exynos_drm_remove_vidi(); |
| 783 | #endif | 784 | #endif |
| 784 | platform_device_unregister(exynos_drm_pdev); | 785 | platform_device_unregister(exynos_drm_pdev); |
| 785 | platform_driver_unregister(&exynos_drm_platform_driver); | ||
| 786 | } | 786 | } |
| 787 | 787 | ||
| 788 | module_init(exynos_drm_init); | 788 | module_init(exynos_drm_init); |
| @@ -343,7 +343,7 @@ struct exynos_drm_display * exynos_dpi_probe(struct device *dev); · 342 unmodified lines | |||
| 343 | int exynos_dpi_remove(struct device *dev); | 343 | int exynos_dpi_remove(struct device *dev); |
| 344 | #else | 344 | #else |
| 345 | static inline struct exynos_drm_display * | 345 | static inline struct exynos_drm_display * |
| 346 | exynos_dpi_probe(struct device *dev) { return 0; } | 346 | exynos_dpi_probe(struct device *dev) { return NULL; } |
| 347 | static inline int exynos_dpi_remove(struct device *dev) { return 0; } | 347 | static inline int exynos_dpi_remove(struct device *dev) { return 0; } |
| 348 | #endif | 348 | #endif |
| 349 | 349 | ||
| @@ -741,6 +741,8 @@ static void fimd_apply(struct exynos_drm_manager *mgr) · 740 unmodified lines | |||
| 741 | win_data = &ctx->win_data[i]; | 741 | win_data = &ctx->win_data[i]; |
| 742 | if (win_data->enabled) | 742 | if (win_data->enabled) |
| 743 | fimd_win_commit(mgr, i); | 743 | fimd_win_commit(mgr, i); |
| 744 | else | ||
| 745 | fimd_win_disable(mgr, i); | ||
| 744 | } | 746 | } |
| 745 | 747 | ||
| 746 | fimd_commit(mgr); | 748 | fimd_commit(mgr); |
| @@ -2090,6 +2090,11 @@ out: · 2089 unmodified lines | |||
| 2090 | 2090 | ||
| 2091 | static void hdmi_dpms(struct exynos_drm_display *display, int mode) | 2091 | static void hdmi_dpms(struct exynos_drm_display *display, int mode) |
| 2092 | { | 2092 | { |
| 2093 | struct hdmi_context *hdata = display->ctx; | ||
| 2094 | struct drm_encoder *encoder = hdata->encoder; | ||
| 2095 | struct drm_crtc *crtc = encoder->crtc; | ||
| 2096 | struct drm_crtc_helper_funcs *funcs = NULL; | ||
| 2097 | |||
| 2093 | DRM_DEBUG_KMS("mode %d\n", mode); | 2098 | DRM_DEBUG_KMS("mode %d\n", mode); |
| 2094 | 2099 | ||
| 2095 | switch (mode) { | 2100 | switch (mode) { |
| @@ -2099,6 +2104,20 @@ static void hdmi_dpms(struct exynos_drm_display *display, int mode) · 3 unmodified lines | |||
| 2099 | case DRM_MODE_DPMS_STANDBY: | 2104 | case DRM_MODE_DPMS_STANDBY: |
| 2100 | case DRM_MODE_DPMS_SUSPEND: | 2105 | case DRM_MODE_DPMS_SUSPEND: |
| 2101 | case DRM_MODE_DPMS_OFF: | 2106 | case DRM_MODE_DPMS_OFF: |
| 2107 | /* | ||
| 2108 | * The SFRs of VP and Mixer are updated by Vertical Sync of | ||
| 2109 | * Timing generator which is a part of HDMI so the sequence | ||
| 2110 | * to disable TV Subsystem should be as following, | ||
| 2111 | * VP -> Mixer -> HDMI | ||
| 2112 | * | ||
| 2113 | * Below codes will try to disable Mixer and VP(if used) | ||
| 2114 | * prior to disabling HDMI. | ||
| 2115 | */ | ||
| 2116 | if (crtc) | ||
| 2117 | funcs = crtc->helper_private; | ||
| 2118 | if (funcs && funcs->dpms) | ||
| 2119 | (*funcs->dpms)(crtc, mode); | ||
| 2120 | |||
| 2102 | hdmi_poweroff(display); | 2121 | hdmi_poweroff(display); |
| 2103 | break; | 2122 | break; |
| 2104 | default: | 2123 | default: |
| @@ -377,6 +377,20 @@ static void mixer_run(struct mixer_context *ctx) · 376 unmodified lines | |||
| 377 | mixer_regs_dump(ctx); | 377 | mixer_regs_dump(ctx); |
| 378 | } | 378 | } |
| 379 | 379 | ||
| 380 | static void mixer_stop(struct mixer_context *ctx) | ||
| 381 | { | ||
| 382 | struct mixer_resources *res = &ctx->mixer_res; | ||
| 383 | int timeout = 20; | ||
| 384 | |||
| 385 | mixer_reg_writemask(res, MXR_STATUS, 0, MXR_STATUS_REG_RUN); | ||
| 386 | |||
| 387 | while (!(mixer_reg_read(res, MXR_STATUS) & MXR_STATUS_REG_IDLE) && | ||
| 388 | --timeout) | ||
| 389 | usleep_range(10000, 12000); | ||
| 390 | |||
| 391 | mixer_regs_dump(ctx); | ||
| 392 | } | ||
| 393 | |||
| 380 | static void vp_video_buffer(struct mixer_context *ctx, int win) | 394 | static void vp_video_buffer(struct mixer_context *ctx, int win) |
| 381 | { | 395 | { |
| 382 | struct mixer_resources *res = &ctx->mixer_res; | 396 | struct mixer_resources *res = &ctx->mixer_res; |
| @@ -497,13 +511,8 @@ static void vp_video_buffer(struct mixer_context *ctx, int win) · 114 unmodified lines | |||
| 497 | static void mixer_layer_update(struct mixer_context *ctx) | 511 | static void mixer_layer_update(struct mixer_context *ctx) |
| 498 | { | 512 | { |
| 499 | struct mixer_resources *res = &ctx->mixer_res; | 513 | struct mixer_resources *res = &ctx->mixer_res; |
| 500 | u32 val; | ||
| 501 | |||
| 502 | val = mixer_reg_read(res, MXR_CFG); | ||
| 503 | 514 | ||
| 504 | /* allow one update per vsync only */ | 515 | mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE); |
| 505 | if (!(val & MXR_CFG_LAYER_UPDATE_COUNT_MASK)) | ||
| 506 | mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE); | ||
| 507 | } | 516 | } |
| 508 | 517 | ||
| 509 | static void mixer_graph_buffer(struct mixer_context *ctx, int win) | 518 | static void mixer_graph_buffer(struct mixer_context *ctx, int win) |
| @@ -1010,6 +1019,8 @@ static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr) · 500 unmodified lines | |||
| 1010 | } | 1019 | } |
| 1011 | mutex_unlock(&mixer_ctx->mixer_mutex); | 1020 | mutex_unlock(&mixer_ctx->mixer_mutex); |
| 1012 | 1021 | ||
| 1022 | drm_vblank_get(mgr->crtc->dev, mixer_ctx->pipe); | ||
| 1023 | |||
| 1013 | atomic_set(&mixer_ctx->wait_vsync_event, 1); | 1024 | atomic_set(&mixer_ctx->wait_vsync_event, 1); |
| 1014 | 1025 | ||
| 1015 | /* | 1026 | /* |
| @@ -1020,6 +1031,8 @@ static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr) · 4 unmodified lines | |||
| 1020 | !atomic_read(&mixer_ctx->wait_vsync_event), | 1031 | !atomic_read(&mixer_ctx->wait_vsync_event), |
| 1021 | HZ/20)) | 1032 | HZ/20)) |
| 1022 | DRM_DEBUG_KMS("vblank wait timed out.\n"); | 1033 | DRM_DEBUG_KMS("vblank wait timed out.\n"); |
| 1034 | |||
| 1035 | drm_vblank_put(mgr->crtc->dev, mixer_ctx->pipe); | ||
| 1023 | } | 1036 | } |
| 1024 | 1037 | ||
| 1025 | static void mixer_window_suspend(struct exynos_drm_manager *mgr) | 1038 | static void mixer_window_suspend(struct exynos_drm_manager *mgr) |
| @@ -1061,7 +1074,7 @@ static void mixer_poweron(struct exynos_drm_manager *mgr) · 35 unmodified lines | |||
| 1061 | mutex_unlock(&ctx->mixer_mutex); | 1074 | mutex_unlock(&ctx->mixer_mutex); |
| 1062 | return; | 1075 | return; |
| 1063 | } | 1076 | } |
| 1064 | ctx->powered = true; | 1077 | |
| 1065 | mutex_unlock(&ctx->mixer_mutex); | 1078 | mutex_unlock(&ctx->mixer_mutex); |
| 1066 | 1079 | ||
| 1067 | pm_runtime_get_sync(ctx->dev); | 1080 | pm_runtime_get_sync(ctx->dev); |
| @@ -1072,6 +1085,12 @@ static void mixer_poweron(struct exynos_drm_manager *mgr) · 4 unmodified lines | |||
| 1072 | clk_prepare_enable(res->sclk_mixer); | 1085 | clk_prepare_enable(res->sclk_mixer); |
| 1073 | } | 1086 | } |
| 1074 | 1087 | ||
| 1088 | mutex_lock(&ctx->mixer_mutex); | ||
| 1089 | ctx->powered = true; | ||
| 1090 | mutex_unlock(&ctx->mixer_mutex); | ||
| 1091 | |||
| 1092 | mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET); | ||
| 1093 | |||
| 1075 | mixer_reg_write(res, MXR_INT_EN, ctx->int_en); | 1094 | mixer_reg_write(res, MXR_INT_EN, ctx->int_en); |
| 1076 | mixer_win_reset(ctx); | 1095 | mixer_win_reset(ctx); |
| 1077 | 1096 | ||
| @@ -1084,14 +1103,21 @@ static void mixer_poweroff(struct exynos_drm_manager *mgr) · 6 unmodified lines | |||
| 1084 | struct mixer_resources *res = &ctx->mixer_res; | 1103 | struct mixer_resources *res = &ctx->mixer_res; |
| 1085 | 1104 | ||
| 1086 | mutex_lock(&ctx->mixer_mutex); | 1105 | mutex_lock(&ctx->mixer_mutex); |
| 1087 | if (!ctx->powered) | 1106 | if (!ctx->powered) { |
| 1088 | goto out; | 1107 | mutex_unlock(&ctx->mixer_mutex); |
| 1108 | return; | ||
| 1109 | } | ||
| 1089 | mutex_unlock(&ctx->mixer_mutex); | 1110 | mutex_unlock(&ctx->mixer_mutex); |
| 1090 | 1111 | ||
| 1112 | mixer_stop(ctx); | ||
| 1091 | mixer_window_suspend(mgr); | 1113 | mixer_window_suspend(mgr); |
| 1092 | 1114 | ||
| 1093 | ctx->int_en = mixer_reg_read(res, MXR_INT_EN); | 1115 | ctx->int_en = mixer_reg_read(res, MXR_INT_EN); |
| 1094 | 1116 | ||
| 1117 | mutex_lock(&ctx->mixer_mutex); | ||
| 1118 | ctx->powered = false; | ||
| 1119 | mutex_unlock(&ctx->mixer_mutex); | ||
| 1120 | |||
| 1095 | clk_disable_unprepare(res->mixer); | 1121 | clk_disable_unprepare(res->mixer); |
| 1096 | if (ctx->vp_enabled) { | 1122 | if (ctx->vp_enabled) { |
| 1097 | clk_disable_unprepare(res->vp); | 1123 | clk_disable_unprepare(res->vp); |
| @@ -1099,12 +1125,6 @@ static void mixer_poweroff(struct exynos_drm_manager *mgr) · 1 unmodified line | |||
| 1099 | } | 1125 | } |
| 1100 | 1126 | ||
| 1101 | pm_runtime_put_sync(ctx->dev); | 1127 | pm_runtime_put_sync(ctx->dev); |
| 1102 | |||
| 1103 | mutex_lock(&ctx->mixer_mutex); | ||
| 1104 | ctx->powered = false; | ||
| 1105 | |||
| 1106 | out: | ||
| 1107 | mutex_unlock(&ctx->mixer_mutex); | ||
| 1108 | } | 1128 | } |
| 1109 | 1129 | ||
| 1110 | static void mixer_dpms(struct exynos_drm_manager *mgr, int mode) | 1130 | static void mixer_dpms(struct exynos_drm_manager *mgr, int mode) |
| @@ -78,6 +78,7 @@ · 77 unmodified lines | |||
| 78 | #define MXR_STATUS_BIG_ENDIAN (1 << 3) | 78 | #define MXR_STATUS_BIG_ENDIAN (1 << 3) |
| 79 | #define MXR_STATUS_ENDIAN_MASK (1 << 3) | 79 | #define MXR_STATUS_ENDIAN_MASK (1 << 3) |
| 80 | #define MXR_STATUS_SYNC_ENABLE (1 << 2) | 80 | #define MXR_STATUS_SYNC_ENABLE (1 << 2) |
| 81 | #define MXR_STATUS_REG_IDLE (1 << 1) | ||
| 81 | #define MXR_STATUS_REG_RUN (1 << 0) | 82 | #define MXR_STATUS_REG_RUN (1 << 0) |
| 82 | 83 | ||
| 83 | /* bits for MXR_CFG */ | 84 | /* bits for MXR_CFG */ |
| @@ -446,7 +446,9 @@ static int i915_gem_object_info(struct seq_file *m, void* data) · 445 unmodified lines | |||
| 446 | 446 | ||
| 447 | memset(&stats, 0, sizeof(stats)); | 447 | memset(&stats, 0, sizeof(stats)); |
| 448 | stats.file_priv = file->driver_priv; | 448 | stats.file_priv = file->driver_priv; |
| 449 | spin_lock(&file->table_lock); | ||
| 449 | idr_for_each(&file->object_idr, per_file_stats, &stats); | 450 | idr_for_each(&file->object_idr, per_file_stats, &stats); |
| 451 | spin_unlock(&file->table_lock); | ||
| 450 | /* | 452 | /* |
| 451 | * Although we have a valid reference on file->pid, that does | 453 | * Although we have a valid reference on file->pid, that does |
| 452 | * not guarantee that the task_struct who called get_pid() is | 454 | * not guarantee that the task_struct who called get_pid() is |
| @@ -977,6 +977,8 @@ struct i915_power_well { · 976 unmodified lines | |||
| 977 | bool always_on; | 977 | bool always_on; |
| 978 | /* power well enable/disable usage count */ | 978 | /* power well enable/disable usage count */ |
| 979 | int count; | 979 | int count; |
| 980 | /* cached hw enabled state */ | ||
| 981 | bool hw_enabled; | ||
| 980 | unsigned long domains; | 982 | unsigned long domains; |
| 981 | unsigned long data; | 983 | unsigned long data; |
| 982 | const struct i915_power_well_ops *ops; | 984 | const struct i915_power_well_ops *ops; |
| @@ -598,6 +598,7 @@ static int do_switch(struct intel_engine_cs *ring, · 597 unmodified lines | |||
| 598 | struct intel_context *from = ring->last_context; | 598 | struct intel_context *from = ring->last_context; |
| 599 | struct i915_hw_ppgtt *ppgtt = ctx_to_ppgtt(to); | 599 | struct i915_hw_ppgtt *ppgtt = ctx_to_ppgtt(to); |
| 600 | u32 hw_flags = 0; | 600 | u32 hw_flags = 0; |
| 601 | bool uninitialized = false; | ||
| 601 | int ret, i; | 602 | int ret, i; |
| 602 | 603 | ||
| 603 | if (from != NULL && ring == &dev_priv->ring[RCS]) { | 604 | if (from != NULL && ring == &dev_priv->ring[RCS]) { |
| @@ -696,19 +697,20 @@ static int do_switch(struct intel_engine_cs *ring, · 92 unmodified lines | |||
| 696 | i915_gem_context_unreference(from); | 697 | i915_gem_context_unreference(from); |
| 697 | } | 698 | } |
| 698 | 699 | ||
| 700 | uninitialized = !to->is_initialized && from == NULL; | ||
| 701 | to->is_initialized = true; | ||
| 702 | |||
| 699 | done: | 703 | done: |
| 700 | i915_gem_context_reference(to); | 704 | i915_gem_context_reference(to); |
| 701 | ring->last_context = to; | 705 | ring->last_context = to; |
| 702 | to->last_ring = ring; | 706 | to->last_ring = ring; |
| 703 | 707 | ||
| 704 | if (ring->id == RCS && !to->is_initialized && from == NULL) { | 708 | if (uninitialized) { |
| 705 | ret = i915_gem_render_state_init(ring); | 709 | ret = i915_gem_render_state_init(ring); |
| 706 | if (ret) | 710 | if (ret) |
| 707 | DRM_ERROR("init render state: %d\n", ret); | 711 | DRM_ERROR("init render state: %d\n", ret); |
| 708 | } | 712 | } |
| 709 | 713 | ||
| 710 | to->is_initialized = true; | ||
| 711 | |||
| 712 | return 0; | 714 | return 0; |
| 713 | 715 | ||
| 714 | unpin_out: | 716 | unpin_out: |
| @@ -315,9 +315,6 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb) · 314 unmodified lines | |||
| 315 | const struct bdb_lfp_backlight_data *backlight_data; | 315 | const struct bdb_lfp_backlight_data *backlight_data; |
| 316 | const struct bdb_lfp_backlight_data_entry *entry; | 316 | const struct bdb_lfp_backlight_data_entry *entry; |
| 317 | 317 | ||
| 318 | /* Err to enabling backlight if no backlight block. */ | ||
| 319 | dev_priv->vbt.backlight.present = true; | ||
| 320 | |||
| 321 | backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT); | 318 | backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT); |
| 322 | if (!backlight_data) | 319 | if (!backlight_data) |
| 323 | return; | 320 | return; |
| @@ -1088,6 +1085,9 @@ init_vbt_defaults(struct drm_i915_private *dev_priv) · 764 unmodified lines | |||
| 1088 | 1085 | ||
| 1089 | dev_priv->vbt.crt_ddc_pin = GMBUS_PORT_VGADDC; | 1086 | dev_priv->vbt.crt_ddc_pin = GMBUS_PORT_VGADDC; |
| 1090 | 1087 | ||
| 1088 | /* Default to having backlight */ | ||
| 1089 | dev_priv->vbt.backlight.present = true; | ||
| 1090 | |||
| 1091 | /* LFP panel data */ | 1091 | /* LFP panel data */ |
| 1092 | dev_priv->vbt.lvds_dither = 1; | 1092 | dev_priv->vbt.lvds_dither = 1; |
| 1093 | dev_priv->vbt.lvds_vbt = 0; | 1093 | dev_priv->vbt.lvds_vbt = 0; |
| @@ -4564,7 +4564,10 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc) · 4563 unmodified lines | |||
| 4564 | if (intel_crtc->active) | 4564 | if (intel_crtc->active) |
| 4565 | return; | 4565 | return; |
| 4566 | 4566 | ||
| 4567 | vlv_prepare_pll(intel_crtc); | 4567 | is_dsi = intel_pipe_has_type(crtc, INTEL_OUTPUT_DSI); |
| 4568 | |||
| 4569 | if (!is_dsi && !IS_CHERRYVIEW(dev)) | ||
| 4570 | vlv_prepare_pll(intel_crtc); | ||
| 4568 | 4571 | ||
| 4569 | /* Set up the display plane register */ | 4572 | /* Set up the display plane register */ |
| 4570 | dspcntr = DISPPLANE_GAMMA_ENABLE; | 4573 | dspcntr = DISPPLANE_GAMMA_ENABLE; |
| @@ -4598,8 +4601,6 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc) · 27 unmodified lines | |||
| 4598 | if (encoder->pre_pll_enable) | 4601 | if (encoder->pre_pll_enable) |
| 4599 | encoder->pre_pll_enable(encoder); | 4602 | encoder->pre_pll_enable(encoder); |
| 4600 | 4603 | ||
| 4601 | is_dsi = intel_pipe_has_type(crtc, INTEL_OUTPUT_DSI); | ||
| 4602 | |||
| 4603 | if (!is_dsi) { | 4604 | if (!is_dsi) { |
| 4604 | if (IS_CHERRYVIEW(dev)) | 4605 | if (IS_CHERRYVIEW(dev)) |
| 4605 | chv_enable_pll(intel_crtc); | 4606 | chv_enable_pll(intel_crtc); |
| @@ -12411,8 +12412,8 @@ intel_display_capture_error_state(struct drm_device *dev) · 7805 unmodified lines | |||
| 12411 | 12412 | ||
| 12412 | for_each_pipe(i) { | 12413 | for_each_pipe(i) { |
| 12413 | error->pipe[i].power_domain_on = | 12414 | error->pipe[i].power_domain_on = |
| 12414 | intel_display_power_enabled_sw(dev_priv, | 12415 | intel_display_power_enabled_unlocked(dev_priv, |
| 12415 | POWER_DOMAIN_PIPE(i)); | 12416 | POWER_DOMAIN_PIPE(i)); |
| 12416 | if (!error->pipe[i].power_domain_on) | 12417 | if (!error->pipe[i].power_domain_on) |
| 12417 | continue; | 12418 | continue; |
| 12418 | 12419 | ||
| @@ -12447,7 +12448,7 @@ intel_display_capture_error_state(struct drm_device *dev) · 28 unmodified lines | |||
| 12447 | enum transcoder cpu_transcoder = transcoders[i]; | 12448 | enum transcoder cpu_transcoder = transcoders[i]; |
| 12448 | 12449 | ||
| 12449 | error->transcoder[i].power_domain_on = | 12450 | error->transcoder[i].power_domain_on = |
| 12450 | intel_display_power_enabled_sw(dev_priv, | 12451 | intel_display_power_enabled_unlocked(dev_priv, |
| 12451 | POWER_DOMAIN_TRANSCODER(cpu_transcoder)); | 12452 | POWER_DOMAIN_TRANSCODER(cpu_transcoder)); |
| 12452 | if (!error->transcoder[i].power_domain_on) | 12453 | if (!error->transcoder[i].power_domain_on) |
| 12453 | continue; | 12454 | continue; |
| @@ -950,8 +950,8 @@ int intel_power_domains_init(struct drm_i915_private *); · 949 unmodified lines | |||
| 950 | void intel_power_domains_remove(struct drm_i915_private *); | 950 | void intel_power_domains_remove(struct drm_i915_private *); |
| 951 | bool intel_display_power_enabled(struct drm_i915_private *dev_priv, | 951 | bool intel_display_power_enabled(struct drm_i915_private *dev_priv, |
| 952 | enum intel_display_power_domain domain); | 952 | enum intel_display_power_domain domain); |
| 953 | bool intel_display_power_enabled_sw(struct drm_i915_private *dev_priv, | 953 | bool intel_display_power_enabled_unlocked(struct drm_i915_private *dev_priv, |
| 954 | enum intel_display_power_domain domain); | 954 | enum intel_display_power_domain domain); |
| 955 | void intel_display_power_get(struct drm_i915_private *dev_priv, | 955 | void intel_display_power_get(struct drm_i915_private *dev_priv, |
| 956 | enum intel_display_power_domain domain); | 956 | enum intel_display_power_domain domain); |
| 957 | void intel_display_power_put(struct drm_i915_private *dev_priv, | 957 | void intel_display_power_put(struct drm_i915_private *dev_priv, |
| @@ -5603,8 +5603,8 @@ static bool hsw_power_well_enabled(struct drm_i915_private *dev_priv, · 5602 unmodified lines | |||
| 5603 | (HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED); | 5603 | (HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED); |
| 5604 | } | 5604 | } |
| 5605 | 5605 | ||
| 5606 | bool intel_display_power_enabled_sw(struct drm_i915_private *dev_priv, | 5606 | bool intel_display_power_enabled_unlocked(struct drm_i915_private *dev_priv, |
| 5607 | enum intel_display_power_domain domain) | 5607 | enum intel_display_power_domain domain) |
| 5608 | { | 5608 | { |
| 5609 | struct i915_power_domains *power_domains; | 5609 | struct i915_power_domains *power_domains; |
| 5610 | struct i915_power_well *power_well; | 5610 | struct i915_power_well *power_well; |
| @@ -5615,16 +5615,19 @@ bool intel_display_power_enabled_sw(struct drm_i915_private *dev_priv, · 4 unmodified lines | |||
| 5615 | return false; | 5615 | return false; |
| 5616 | 5616 | ||
| 5617 | power_domains = &dev_priv->power_domains; | 5617 | power_domains = &dev_priv->power_domains; |
| 5618 | |||
| 5618 | is_enabled = true; | 5619 | is_enabled = true; |
| 5620 | |||
| 5619 | for_each_power_well_rev(i, power_well, BIT(domain), power_domains) { | 5621 | for_each_power_well_rev(i, power_well, BIT(domain), power_domains) { |
| 5620 | if (power_well->always_on) | 5622 | if (power_well->always_on) |
| 5621 | continue; | 5623 | continue; |
| 5622 | 5624 | ||
| 5623 | if (!power_well->count) { | 5625 | if (!power_well->hw_enabled) { |
| 5624 | is_enabled = false; | 5626 | is_enabled = false; |
| 5625 | break; | 5627 | break; |
| 5626 | } | 5628 | } |
| 5627 | } | 5629 | } |
| 5630 | |||
| 5628 | return is_enabled; | 5631 | return is_enabled; |
| 5629 | } | 5632 | } |
| 5630 | 5633 | ||
| @@ -5632,30 +5635,15 @@ bool intel_display_power_enabled(struct drm_i915_private *dev_priv, · 1 unmodified line | |||
| 5632 | enum intel_display_power_domain domain) | 5635 | enum intel_display_power_domain domain) |
| 5633 | { | 5636 | { |
| 5634 | struct i915_power_domains *power_domains; | 5637 | struct i915_power_domains *power_domains; |
| 5635 | struct i915_power_well *power_well; | 5638 | bool ret; |
| 5636 | bool is_enabled; | ||
| 5637 | int i; | ||
| 5638 | |||
| 5639 | if (dev_priv->pm.suspended) | ||
| 5640 | return false; | ||
| 5641 | 5639 | ||
| 5642 | power_domains = &dev_priv->power_domains; | 5640 | power_domains = &dev_priv->power_domains; |
| 5643 | 5641 | ||
| 5644 | is_enabled = true; | ||
| 5645 | |||
| 5646 | mutex_lock(&power_domains->lock); | 5642 | mutex_lock(&power_domains->lock); |
| 5647 | for_each_power_well_rev(i, power_well, BIT(domain), power_domains) { | 5643 | ret = intel_display_power_enabled_unlocked(dev_priv, domain); |
| 5648 | if (power_well->always_on) | ||
| 5649 | continue; | ||
| 5650 | |||
| 5651 | if (!power_well->ops->is_enabled(dev_priv, power_well)) { | ||
| 5652 | is_enabled = false; | ||
| 5653 | break; | ||
| 5654 | } | ||
| 5655 | } | ||
| 5656 | mutex_unlock(&power_domains->lock); | 5644 | mutex_unlock(&power_domains->lock); |
| 5657 | 5645 | ||
| 5658 | return is_enabled; | 5646 | return ret; |
| 5659 | } | 5647 | } |
| 5660 | 5648 | ||
| 5661 | /* | 5649 | /* |
| @@ -5976,6 +5964,7 @@ void intel_display_power_get(struct drm_i915_private *dev_priv, · 314 unmodified lines | |||
| 5976 | if (!power_well->count++) { | 5964 | if (!power_well->count++) { |
| 5977 | DRM_DEBUG_KMS("enabling %s\n", power_well->name); | 5965 | DRM_DEBUG_KMS("enabling %s\n", power_well->name); |
| 5978 | power_well->ops->enable(dev_priv, power_well); | 5966 | power_well->ops->enable(dev_priv, power_well); |
| 5967 | power_well->hw_enabled = true; | ||
| 5979 | } | 5968 | } |
| 5980 | 5969 | ||
| 5981 | check_power_well_state(dev_priv, power_well); | 5970 | check_power_well_state(dev_priv, power_well); |
| @@ -6005,6 +5994,7 @@ void intel_display_power_put(struct drm_i915_private *dev_priv, · 23 unmodified lines | |||
| 6005 | 5994 | ||
| 6006 | if (!--power_well->count && i915.disable_power_well) { | 5995 | if (!--power_well->count && i915.disable_power_well) { |
| 6007 | DRM_DEBUG_KMS("disabling %s\n", power_well->name); | 5996 | DRM_DEBUG_KMS("disabling %s\n", power_well->name); |
| 5997 | power_well->hw_enabled = false; | ||
| 6008 | power_well->ops->disable(dev_priv, power_well); | 5998 | power_well->ops->disable(dev_priv, power_well); |
| 6009 | } | 5999 | } |
| 6010 | 6000 | ||
| @@ -6267,8 +6257,11 @@ static void intel_power_domains_resume(struct drm_i915_private *dev_priv) · 256 unmodified lines | |||
| 6267 | int i; | 6257 | int i; |
| 6268 | 6258 | ||
| 6269 | mutex_lock(&power_domains->lock); | 6259 | mutex_lock(&power_domains->lock); |
| 6270 | for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) | 6260 | for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) { |
| 6271 | power_well->ops->sync_hw(dev_priv, power_well); | 6261 | power_well->ops->sync_hw(dev_priv, power_well); |
| 6262 | power_well->hw_enabled = power_well->ops->is_enabled(dev_priv, | ||
| 6263 | power_well); | ||
| 6264 | } | ||
| 6272 | mutex_unlock(&power_domains->lock); | 6265 | mutex_unlock(&power_domains->lock); |
| 6273 | } | 6266 | } |
| 6274 | 6267 | ||
| @@ -277,6 +277,7 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data) · 276 unmodified lines | |||
| 277 | static const char *hpd_reg_names[] = {"hpd-gdsc", "hpd-5v"}; | 277 | static const char *hpd_reg_names[] = {"hpd-gdsc", "hpd-5v"}; |
| 278 | static const char *pwr_reg_names[] = {"core-vdda", "core-vcc"}; | 278 | static const char *pwr_reg_names[] = {"core-vdda", "core-vcc"}; |
| 279 | static const char *hpd_clk_names[] = {"iface_clk", "core_clk", "mdp_core_clk"}; | 279 | static const char *hpd_clk_names[] = {"iface_clk", "core_clk", "mdp_core_clk"}; |
| 280 | static unsigned long hpd_clk_freq[] = {0, 19200000, 0}; | ||
| 280 | static const char *pwr_clk_names[] = {"extp_clk", "alt_iface_clk"}; | 281 | static const char *pwr_clk_names[] = {"extp_clk", "alt_iface_clk"}; |
| 281 | 282 | ||
| 282 | config.phy_init = hdmi_phy_8x74_init; | 283 | config.phy_init = hdmi_phy_8x74_init; |
| @@ -286,6 +287,7 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data) · 3 unmodified lines | |||
| 286 | config.pwr_reg_names = pwr_reg_names; | 287 | config.pwr_reg_names = pwr_reg_names; |
| 287 | config.pwr_reg_cnt = ARRAY_SIZE(pwr_reg_names); | 288 | config.pwr_reg_cnt = ARRAY_SIZE(pwr_reg_names); |
| 288 | config.hpd_clk_names = hpd_clk_names; | 289 | config.hpd_clk_names = hpd_clk_names; |
| 290 | config.hpd_freq = hpd_clk_freq; | ||
| 289 | config.hpd_clk_cnt = ARRAY_SIZE(hpd_clk_names); | 291 | config.hpd_clk_cnt = ARRAY_SIZE(hpd_clk_names); |
| 290 | config.pwr_clk_names = pwr_clk_names; | 292 | config.pwr_clk_names = pwr_clk_names; |
| 291 | config.pwr_clk_cnt = ARRAY_SIZE(pwr_clk_names); | 293 | config.pwr_clk_cnt = ARRAY_SIZE(pwr_clk_names); |
| @@ -87,6 +87,7 @@ struct hdmi_platform_config { · 86 unmodified lines | |||
| 87 | 87 | ||
| 88 | /* clks that need to be on for hpd: */ | 88 | /* clks that need to be on for hpd: */ |
| 89 | const char **hpd_clk_names; | 89 | const char **hpd_clk_names; |
| 90 | const long unsigned *hpd_freq; | ||
| 90 | int hpd_clk_cnt; | 91 | int hpd_clk_cnt; |
| 91 | 92 | ||
| 92 | /* clks that need to be on for screen pwr (ie pixel clk): */ | 93 | /* clks that need to be on for screen pwr (ie pixel clk): */ |
| @@ -127,6 +127,14 @@ static int hpd_enable(struct hdmi_connector *hdmi_connector) · 126 unmodified lines | |||
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | for (i = 0; i < config->hpd_clk_cnt; i++) { | 129 | for (i = 0; i < config->hpd_clk_cnt; i++) { |
| 130 | if (config->hpd_freq && config->hpd_freq[i]) { | ||
| 131 | ret = clk_set_rate(hdmi->hpd_clks[i], | ||
| 132 | config->hpd_freq[i]); | ||
| 133 | if (ret) | ||
| 134 | dev_warn(dev->dev, "failed to set clk %s (%d)\n", | ||
| 135 | config->hpd_clk_names[i], ret); | ||
| 136 | } | ||
| 137 | |||
| 130 | ret = clk_prepare_enable(hdmi->hpd_clks[i]); | 138 | ret = clk_prepare_enable(hdmi->hpd_clks[i]); |
| 131 | if (ret) { | 139 | if (ret) { |
| 132 | dev_err(dev->dev, "failed to enable hpd clk: %s (%d)\n", | 140 | dev_err(dev->dev, "failed to enable hpd clk: %s (%d)\n", |
| @@ -20,6 +20,10 @@ · 19 unmodified lines | |||
| 20 | #include "msm_mmu.h" | 20 | #include "msm_mmu.h" |
| 21 | #include "mdp5_kms.h" | 21 | #include "mdp5_kms.h" |
| 22 | 22 | ||
| 23 | static const char *iommu_ports[] = { | ||
| 24 | "mdp_0", | ||
| 25 | }; | ||
| 26 | |||
| 23 | static struct mdp5_platform_config *mdp5_get_config(struct platform_device *dev); | 27 | static struct mdp5_platform_config *mdp5_get_config(struct platform_device *dev); |
| 24 | 28 | ||
| 25 | static int mdp5_hw_init(struct msm_kms *kms) | 29 | static int mdp5_hw_init(struct msm_kms *kms) |
| @@ -104,6 +108,12 @@ static void mdp5_preclose(struct msm_kms *kms, struct drm_file *file) · 78 unmodified lines | |||
| 104 | static void mdp5_destroy(struct msm_kms *kms) | 108 | static void mdp5_destroy(struct msm_kms *kms) |
| 105 | { | 109 | { |
| 106 | struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); | 110 | struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); |
| 111 | struct msm_mmu *mmu = mdp5_kms->mmu; | ||
| 112 | |||
| 113 | if (mmu) { | ||
| 114 | mmu->funcs->detach(mmu, iommu_ports, ARRAY_SIZE(iommu_ports)); | ||
| 115 | mmu->funcs->destroy(mmu); | ||
| 116 | } | ||
| 107 | kfree(mdp5_kms); | 117 | kfree(mdp5_kms); |
| 108 | } | 118 | } |
| 109 | 119 | ||
| @@ -216,10 +226,6 @@ fail: · 106 unmodified lines | |||
| 216 | return ret; | 226 | return ret; |
| 217 | } | 227 | } |
| 218 | 228 | ||
| 219 | static const char *iommu_ports[] = { | ||
| 220 | "mdp_0", | ||
| 221 | }; | ||
| 222 | |||
| 223 | static int get_clk(struct platform_device *pdev, struct clk **clkp, | 229 | static int get_clk(struct platform_device *pdev, struct clk **clkp, |
| 224 | const char *name) | 230 | const char *name) |
| 225 | { | 231 | { |
| @@ -317,17 +323,23 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev) · 91 unmodified lines | |||
| 317 | mmu = msm_iommu_new(dev, config->iommu); | 323 | mmu = msm_iommu_new(dev, config->iommu); |
| 318 | if (IS_ERR(mmu)) { | 324 | if (IS_ERR(mmu)) { |
| 319 | ret = PTR_ERR(mmu); | 325 | ret = PTR_ERR(mmu); |
| 326 | dev_err(dev->dev, "failed to init iommu: %d\n", ret); | ||
| 320 | goto fail; | 327 | goto fail; |
| 321 | } | 328 | } |
| 329 | |||
| 322 | ret = mmu->funcs->attach(mmu, iommu_ports, | 330 | ret = mmu->funcs->attach(mmu, iommu_ports, |
| 323 | ARRAY_SIZE(iommu_ports)); | 331 | ARRAY_SIZE(iommu_ports)); |
| 324 | if (ret) | 332 | if (ret) { |
| 333 | dev_err(dev->dev, "failed to attach iommu: %d\n", ret); | ||
| 334 | mmu->funcs->destroy(mmu); | ||
| 325 | goto fail; | 335 | goto fail; |
| 336 | } | ||
| 326 | } else { | 337 | } else { |
| 327 | dev_info(dev->dev, "no iommu, fallback to phys " | 338 | dev_info(dev->dev, "no iommu, fallback to phys " |
| 328 | "contig buffers for scanout\n"); | 339 | "contig buffers for scanout\n"); |
| 329 | mmu = NULL; | 340 | mmu = NULL; |
| 330 | } | 341 | } |
| 342 | mdp5_kms->mmu = mmu; | ||
| 331 | 343 | ||
| 332 | mdp5_kms->id = msm_register_mmu(dev, mmu); | 344 | mdp5_kms->id = msm_register_mmu(dev, mmu); |
| 333 | if (mdp5_kms->id < 0) { | 345 | if (mdp5_kms->id < 0) { |
| @@ -33,6 +33,7 @@ struct mdp5_kms { · 32 unmodified lines | |||
| 33 | 33 | ||
| 34 | /* mapper-id used to request GEM buffer mapped for scanout: */ | 34 | /* mapper-id used to request GEM buffer mapped for scanout: */ |
| 35 | int id; | 35 | int id; |
| 36 | struct msm_mmu *mmu; | ||
| 36 | 37 | ||
| 37 | /* for tracking smp allocation amongst pipes: */ | 38 | /* for tracking smp allocation amongst pipes: */ |
| 38 | mdp5_smp_state_t smp_state; | 39 | mdp5_smp_state_t smp_state; |
| @@ -159,7 +159,7 @@ static int msm_unload(struct drm_device *dev) · 158 unmodified lines | |||
| 159 | static int get_mdp_ver(struct platform_device *pdev) | 159 | static int get_mdp_ver(struct platform_device *pdev) |
| 160 | { | 160 | { |
| 161 | #ifdef CONFIG_OF | 161 | #ifdef CONFIG_OF |
| 162 | const static struct of_device_id match_types[] = { { | 162 | static const struct of_device_id match_types[] = { { |
| 163 | .compatible = "qcom,mdss_mdp", | 163 | .compatible = "qcom,mdss_mdp", |
| 164 | .data = (void *)5, | 164 | .data = (void *)5, |
| 165 | }, { | 165 | }, { |
| @@ -59,7 +59,7 @@ static int msm_fbdev_create(struct drm_fb_helper *helper, · 58 unmodified lines | |||
| 59 | struct drm_framebuffer *fb = NULL; | 59 | struct drm_framebuffer *fb = NULL; |
| 60 | struct fb_info *fbi = NULL; | 60 | struct fb_info *fbi = NULL; |
| 61 | struct drm_mode_fb_cmd2 mode_cmd = {0}; | 61 | struct drm_mode_fb_cmd2 mode_cmd = {0}; |
| 62 | dma_addr_t paddr; | 62 | uint32_t paddr; |
| 63 | int ret, size; | 63 | int ret, size; |
| 64 | 64 | ||
| 65 | sizes->surface_bpp = 32; | 65 | sizes->surface_bpp = 32; |
| @@ -278,6 +278,7 @@ int msm_gem_get_iova_locked(struct drm_gem_object *obj, int id, · 277 unmodified lines | |||
| 278 | uint32_t *iova) | 278 | uint32_t *iova) |
| 279 | { | 279 | { |
| 280 | struct msm_gem_object *msm_obj = to_msm_bo(obj); | 280 | struct msm_gem_object *msm_obj = to_msm_bo(obj); |
| 281 | struct drm_device *dev = obj->dev; | ||
| 281 | int ret = 0; | 282 | int ret = 0; |
| 282 | 283 | ||
| 283 | if (!msm_obj->domain[id].iova) { | 284 | if (!msm_obj->domain[id].iova) { |
| @@ -285,6 +286,11 @@ int msm_gem_get_iova_locked(struct drm_gem_object *obj, int id, · 1 unmodified line | |||
| 285 | struct msm_mmu *mmu = priv->mmus[id]; | 286 | struct msm_mmu *mmu = priv->mmus[id]; |
| 286 | struct page **pages = get_pages(obj); | 287 | struct page **pages = get_pages(obj); |
| 287 | 288 | ||
| 289 | if (!mmu) { | ||
| 290 | dev_err(dev->dev, "null MMU pointer\n"); | ||
| 291 | return -EINVAL; | ||
| 292 | } | ||
| 293 | |||
| 288 | if (IS_ERR(pages)) | 294 | if (IS_ERR(pages)) |
| 289 | return PTR_ERR(pages); | 295 | return PTR_ERR(pages); |
| 290 | 296 | ||
| @@ -28,7 +28,7 @@ static int msm_fault_handler(struct iommu_domain *iommu, struct device *dev, · 27 unmodified lines | |||
| 28 | unsigned long iova, int flags, void *arg) | 28 | unsigned long iova, int flags, void *arg) |
| 29 | { | 29 | { |
| 30 | DBG("*** fault: iova=%08lx, flags=%d", iova, flags); | 30 | DBG("*** fault: iova=%08lx, flags=%d", iova, flags); |
| 31 | return 0; | 31 | return -ENOSYS; |
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | static int msm_iommu_attach(struct msm_mmu *mmu, const char **names, int cnt) | 34 | static int msm_iommu_attach(struct msm_mmu *mmu, const char **names, int cnt) |
| @@ -40,8 +40,10 @@ static int msm_iommu_attach(struct msm_mmu *mmu, const char **names, int cnt) · 5 unmodified lines | |||
| 40 | for (i = 0; i < cnt; i++) { | 40 | for (i = 0; i < cnt; i++) { |
| 41 | struct device *msm_iommu_get_ctx(const char *ctx_name); | 41 | struct device *msm_iommu_get_ctx(const char *ctx_name); |
| 42 | struct device *ctx = msm_iommu_get_ctx(names[i]); | 42 | struct device *ctx = msm_iommu_get_ctx(names[i]); |
| 43 | if (IS_ERR_OR_NULL(ctx)) | 43 | if (IS_ERR_OR_NULL(ctx)) { |
| 44 | dev_warn(dev->dev, "couldn't get %s context", names[i]); | ||
| 44 | continue; | 45 | continue; |
| 46 | } | ||
| 45 | ret = iommu_attach_device(iommu->domain, ctx); | 47 | ret = iommu_attach_device(iommu->domain, ctx); |
| 46 | if (ret) { | 48 | if (ret) { |
| 47 | dev_warn(dev->dev, "could not attach iommu to %s", names[i]); | 49 | dev_warn(dev->dev, "could not attach iommu to %s", names[i]); |
| @@ -52,6 +54,20 @@ static int msm_iommu_attach(struct msm_mmu *mmu, const char **names, int cnt) · 4 unmodified lines | |||
| 52 | return 0; | 54 | return 0; |
| 53 | } | 55 | } |
| 54 | 56 | ||
| 57 | static void msm_iommu_detach(struct msm_mmu *mmu, const char **names, int cnt) | ||
| 58 | { | ||
| 59 | struct msm_iommu *iommu = to_msm_iommu(mmu); | ||
| 60 | int i; | ||
| 61 | |||
| 62 | for (i = 0; i < cnt; i++) { | ||
| 63 | struct device *msm_iommu_get_ctx(const char *ctx_name); | ||
| 64 | struct device *ctx = msm_iommu_get_ctx(names[i]); | ||
| 65 | if (IS_ERR_OR_NULL(ctx)) | ||
| 66 | continue; | ||
| 67 | iommu_detach_device(iommu->domain, ctx); | ||
| 68 | } | ||
| 69 | } | ||
| 70 | |||
| 55 | static int msm_iommu_map(struct msm_mmu *mmu, uint32_t iova, | 71 | static int msm_iommu_map(struct msm_mmu *mmu, uint32_t iova, |
| 56 | struct sg_table *sgt, unsigned len, int prot) | 72 | struct sg_table *sgt, unsigned len, int prot) |
| 57 | { | 73 | { |
| @@ -110,7 +126,7 @@ static int msm_iommu_unmap(struct msm_mmu *mmu, uint32_t iova, · 52 unmodified lines | |||
| 110 | 126 | ||
| 111 | VERB("unmap[%d]: %08x(%x)", i, iova, bytes); | 127 | VERB("unmap[%d]: %08x(%x)", i, iova, bytes); |
| 112 | 128 | ||
| 113 | BUG_ON(!IS_ALIGNED(bytes, PAGE_SIZE)); | 129 | BUG_ON(!PAGE_ALIGNED(bytes)); |
| 114 | 130 | ||
| 115 | da += bytes; | 131 | da += bytes; |
| 116 | } | 132 | } |
| @@ -127,6 +143,7 @@ static void msm_iommu_destroy(struct msm_mmu *mmu) · 10 unmodified lines | |||
| 127 | 143 | ||
| 128 | static const struct msm_mmu_funcs funcs = { | 144 | static const struct msm_mmu_funcs funcs = { |
| 129 | .attach = msm_iommu_attach, | 145 | .attach = msm_iommu_attach, |
| 146 | .detach = msm_iommu_detach, | ||
| 130 | .map = msm_iommu_map, | 147 | .map = msm_iommu_map, |
| 131 | .unmap = msm_iommu_unmap, | 148 | .unmap = msm_iommu_unmap, |
| 132 | .destroy = msm_iommu_destroy, | 149 | .destroy = msm_iommu_destroy, |
| @@ -22,6 +22,7 @@ · 21 unmodified lines | |||
| 22 | 22 | ||
| 23 | struct msm_mmu_funcs { | 23 | struct msm_mmu_funcs { |
| 24 | int (*attach)(struct msm_mmu *mmu, const char **names, int cnt); | 24 | int (*attach)(struct msm_mmu *mmu, const char **names, int cnt); |
| 25 | void (*detach)(struct msm_mmu *mmu, const char **names, int cnt); | ||
| 25 | int (*map)(struct msm_mmu *mmu, uint32_t iova, struct sg_table *sgt, | 26 | int (*map)(struct msm_mmu *mmu, uint32_t iova, struct sg_table *sgt, |
| 26 | unsigned len, int prot); | 27 | unsigned len, int prot); |
| 27 | int (*unmap)(struct msm_mmu *mmu, uint32_t iova, struct sg_table *sgt, | 28 | int (*unmap)(struct msm_mmu *mmu, uint32_t iova, struct sg_table *sgt, |
| @@ -237,13 +237,21 @@ · 236 unmodified lines | |||
| 237 | #define INTEL_BDW_GT3D_IDS(info) \ | 237 | #define INTEL_BDW_GT3D_IDS(info) \ |
| 238 | _INTEL_BDW_D_IDS(3, info) | 238 | _INTEL_BDW_D_IDS(3, info) |
| 239 | 239 | ||
| 240 | #define INTEL_BDW_RSVDM_IDS(info) \ | ||
| 241 | _INTEL_BDW_M_IDS(4, info) | ||
| 242 | |||
| 243 | #define INTEL_BDW_RSVDD_IDS(info) \ | ||
| 244 | _INTEL_BDW_D_IDS(4, info) | ||
| 245 | |||
| 240 | #define INTEL_BDW_M_IDS(info) \ | 246 | #define INTEL_BDW_M_IDS(info) \ |
| 241 | INTEL_BDW_GT12M_IDS(info), \ | 247 | INTEL_BDW_GT12M_IDS(info), \ |
| 242 | INTEL_BDW_GT3M_IDS(info) | 248 | INTEL_BDW_GT3M_IDS(info), \ |
| 249 | INTEL_BDW_RSVDM_IDS(info) | ||
| 243 | 250 | ||
| 244 | #define INTEL_BDW_D_IDS(info) \ | 251 | #define INTEL_BDW_D_IDS(info) \ |
| 245 | INTEL_BDW_GT12D_IDS(info), \ | 252 | INTEL_BDW_GT12D_IDS(info), \ |
| 246 | INTEL_BDW_GT3D_IDS(info) | 253 | INTEL_BDW_GT3D_IDS(info), \ |
| 254 | INTEL_BDW_RSVDD_IDS(info) | ||
| 247 | 255 | ||
| 248 | #define INTEL_CHV_IDS(info) \ | 256 | #define INTEL_CHV_IDS(info) \ |
| 249 | INTEL_VGA_DEVICE(0x22b0, info), \ | 257 | INTEL_VGA_DEVICE(0x22b0, info), \ |