diff options
Diffstat (limited to 'drivers/gpu')
86 files changed, 189 insertions, 1896 deletions
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c index 3a29d857640b..7e3a7fcb9fe6 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c @@ -24,6 +24,7 @@ #include <linux/hmm.h> #include <linux/dma-direction.h> #include <linux/dma-mapping.h> +#include <linux/migrate.h> #include "amdgpu_sync.h" #include "amdgpu_object.h" #include "amdgpu_vm.h" @@ -221,7 +222,6 @@ svm_migrate_get_vram_page(struct svm_range *prange, unsigned long pfn) page = pfn_to_page(pfn); svm_range_bo_ref(prange->svm_bo); page->zone_device_data = prange->svm_bo; - get_page(page); lock_page(page); } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index f36062be9ca8..9967a73d5b0f 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -26,6 +26,7 @@ #include <linux/hashtable.h> #include <linux/mmu_notifier.h> +#include <linux/memremap.h> #include <linux/mutex.h> #include <linux/types.h> #include <linux/atomic.h> diff --git a/drivers/gpu/drm/arm/Kconfig b/drivers/gpu/drm/arm/Kconfig index 58a242871b28..6e3f1d600541 100644 --- a/drivers/gpu/drm/arm/Kconfig +++ b/drivers/gpu/drm/arm/Kconfig @@ -6,6 +6,7 @@ config DRM_HDLCD depends on DRM && OF && (ARM || ARM64 || COMPILE_TEST) depends on COMMON_CLK select DRM_KMS_HELPER + select DRM_GEM_CMA_HELPER help Choose this option if you have an ARM High Definition Colour LCD controller. diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c index 51e51ff299b7..ba16895690f1 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c @@ -93,11 +93,6 @@ static const struct component_master_ops komeda_master_ops = { .unbind = komeda_unbind, }; -static int compare_of(struct device *dev, void *data) -{ - return dev->of_node == data; -} - static void komeda_add_slave(struct device *master, struct component_match **match, struct device_node *np, @@ -107,7 +102,7 @@ static void komeda_add_slave(struct device *master, remote = of_graph_get_remote_node(np, port, endpoint); if (remote) { - drm_of_component_match_add(master, match, compare_of, remote); + drm_of_component_match_add(master, match, component_compare_of, remote); of_node_put(remote); } } diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c index 4f9b0a9f13e3..0643887800b4 100644 --- a/drivers/gpu/drm/armada/armada_drv.c +++ b/drivers/gpu/drm/armada/armada_drv.c @@ -177,17 +177,6 @@ static void armada_drm_unbind(struct device *dev) drm_mm_takedown(&priv->linear); } -static int compare_of(struct device *dev, void *data) -{ - return dev->of_node == data; -} - -static int compare_dev_name(struct device *dev, void *data) -{ - const char *name = data; - return !strcmp(dev_name(dev), name); -} - static void armada_add_endpoints(struct device *dev, struct component_match **match, struct device_node *dev_node) { @@ -196,7 +185,7 @@ static void armada_add_endpoints(struct device *dev, for_each_endpoint_of_node(dev_node, ep) { remote = of_graph_get_remote_port_parent(ep); if (remote && of_device_is_available(remote)) - drm_of_component_match_add(dev, match, compare_of, + drm_of_component_match_add(dev, match, component_compare_of, remote); of_node_put(remote); } @@ -213,7 +202,7 @@ static int armada_drm_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; int ret; - ret = drm_of_component_probe(dev, compare_dev_name, &armada_master_ops); + ret = drm_of_component_probe(dev, component_compare_dev_name, &armada_master_ops); if (ret != -EINVAL) return ret; @@ -223,7 +212,7 @@ static int armada_drm_probe(struct platform_device *pdev) int i; for (i = 0; devices[i]; i++) - component_match_add(dev, &match, compare_dev_name, + component_match_add(dev, &match, component_compare_dev_name, devices[i]); if (i == 0) { diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index c86f5be4dfe0..007e5a282f67 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -8,7 +8,6 @@ config DRM_BRIDGE config DRM_PANEL_BRIDGE def_bool y depends on DRM_BRIDGE - depends on DRM_KMS_HELPER select DRM_PANEL help DRM bridge wrapper of DRM panels @@ -30,7 +29,7 @@ config DRM_CDNS_DSI config DRM_CHIPONE_ICN6211 tristate "Chipone ICN6211 MIPI-DSI/RGB Converter bridge" depends on OF - depends on DRM_KMS_HELPER + select DRM_KMS_HELPER select DRM_MIPI_DSI select DRM_PANEL_BRIDGE help diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index 38616aab12ac..fb6c588b0f71 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -1758,6 +1758,7 @@ static inline void ti_sn_gpio_unregister(void) {} static void ti_sn65dsi86_runtime_disable(void *data) { + pm_runtime_dont_use_autosuspend(data); pm_runtime_disable(data); } @@ -1817,11 +1818,11 @@ static int ti_sn65dsi86_probe(struct i2c_client *client, "failed to get reference clock\n"); pm_runtime_enable(dev); + pm_runtime_set_autosuspend_delay(pdata->dev, 500); + pm_runtime_use_autosuspend(pdata->dev); ret = devm_add_action_or_reset(dev, ti_sn65dsi86_runtime_disable, dev); if (ret) return ret; - pm_runtime_set_autosuspend_delay(pdata->dev, 500); - pm_runtime_use_autosuspend(pdata->dev); ti_sn65dsi86_debugfs_init(pdata); diff --git a/drivers/gpu/drm/drm_cache.c b/drivers/gpu/drm/drm_cache.c index c3e6e615bf09..7051c9c909c2 100644 --- a/drivers/gpu/drm/drm_cache.c +++ b/drivers/gpu/drm/drm_cache.c @@ -27,10 +27,10 @@ /* * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com> */ - #include <linux/cc_platform.h> #include <linux/export.h> #include <linux/highmem.h> +#include <linux/ioport.h> #include <linux/iosys-map.h> #include <xen/xen.h> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index a50c82bc2b2f..76a8c707c34b 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -2330,6 +2330,9 @@ EXPORT_SYMBOL(drm_connector_atomic_hdr_metadata_equal); void drm_connector_set_vrr_capable_property( struct drm_connector *connector, bool capable) { + if (!connector->vrr_capable_property) + return; + drm_object_property_set_value(&connector->base, connector->vrr_capable_property, capable); diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 561f53831e29..cc7bd58369df 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -4859,7 +4859,8 @@ bool drm_detect_monitor_audio(struct edid *edid) if (!edid_ext) goto end; - has_audio = ((edid_ext[3] & EDID_BASIC_AUDIO) != 0); + has_audio = (edid_ext[0] == CEA_EXT && + (edid_ext[3] & EDID_BASIC_AUDIO) != 0); if (has_audio) { DRM_DEBUG_KMS("Monitor has basic audio support\n"); @@ -5187,10 +5188,14 @@ static void drm_parse_cea_ext(struct drm_connector *connector, /* The existence of a CEA block should imply RGB support */ info->color_formats = DRM_COLOR_FORMAT_RGB444; - if (edid_ext[3] & EDID_CEA_YCRCB444) - info->color_formats |= DRM_COLOR_FORMAT_YCBCR444; - if (edid_ext[3] & EDID_CEA_YCRCB422) - info->color_formats |= DRM_COLOR_FORMAT_YCBCR422; + + /* CTA DisplayID Data Block does not have byte #3 */ + if (edid_ext[0] == CEA_EXT) { + if (edid_ext[3] & EDID_CEA_YCRCB444) + info->color_formats |= DRM_COLOR_FORMAT_YCBCR444; + if (edid_ext[3] & EDID_CEA_YCRCB422) + info->color_formats |= DRM_COLOR_FORMAT_YCBCR422; + } if (cea_db_offsets(edid_ext, &start, &end)) return; diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c index 9d90cd75c457..026e4e29a0f3 100644 --- a/drivers/gpu/drm/drm_of.c +++ b/drivers/gpu/drm/drm_of.c @@ -18,11 +18,6 @@ * properties. */ -static void drm_release_of(struct device *dev, void *data) -{ - of_node_put(data); -} - /** * drm_of_crtc_port_mask - find the mask of a registered CRTC by port OF node * @dev: DRM device @@ -94,7 +89,7 @@ void drm_of_component_match_add(struct device *master, struct device_node *node) { of_node_get(node); - component_match_add_release(master, matchptr, drm_release_of, + component_match_add_release(master, matchptr, component_release_of, compare, node); } EXPORT_SYMBOL_GPL(drm_of_component_match_add); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c index 0b756ecb1bc2..1d2b4fb4bcf8 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c @@ -574,18 +574,6 @@ static const struct component_master_ops etnaviv_master_ops = { .unbind = etnaviv_unbind, }; -static int compare_of(struct device *dev, void *data) -{ - struct device_node *np = data; - - return dev->of_node == np; -} - -static int compare_str(struct device *dev, void *data) -{ - return !strcmp(dev_name(dev), data); -} - static int etnaviv_pdev_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -603,14 +591,14 @@ static int etnaviv_pdev_probe(struct platform_device *pdev) first_node = core_node; drm_of_component_match_add(&pdev->dev, &match, - compare_of, core_node); + component_compare_of, core_node); } } else { char **names = dev->platform_data; unsigned i; for (i = 0; names[i]; i++) - component_match_add(dev, &match, compare_str, names[i]); + component_match_add(dev, &match, component_compare_dev_name, names[i]); } /* diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index c68498497c0b..424ea23eec32 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -212,11 +212,6 @@ static struct exynos_drm_driver_info exynos_drm_drivers[] = { } }; -static int compare_dev(struct device *dev, void *data) -{ - return dev == (struct device *)data; -} - static struct component_match *exynos_drm_match_add(struct device *dev) { struct component_match *match = NULL; @@ -234,8 +229,7 @@ static struct component_match *exynos_drm_match_add(struct device *dev) if (!(info->flags & DRM_FIMC_DEVICE) || exynos_drm_check_fimc_device(d) == 0) - component_match_add(dev, &match, - compare_dev, d); + component_match_add(dev, &match, component_compare_dev, d); p = d; } put_device(p); diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c index 3cf057269f2a..2af51df6dca7 100644 --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c @@ -204,11 +204,6 @@ err_mode_config_cleanup: return ret; } -static int compare_of(struct device *dev, void *data) -{ - return dev->of_node == data; -} - static int kirin_drm_kms_cleanup(struct drm_device *dev) { drm_kms_helper_poll_fini(dev); @@ -279,7 +274,7 @@ static int kirin_drm_platform_probe(struct platform_device *pdev) if (!remote) return -ENODEV; - drm_of_component_match_add(dev, &match, compare_of, remote); + drm_of_component_match_add(dev, &match, component_compare_of, remote); of_node_put(remote); return component_master_add_with_match(dev, &kirin_drm_ops, match); diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 9d588d936e3d..7df74a71d454 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -18,6 +18,7 @@ subdir-ccflags-y += -Wno-unused-parameter subdir-ccflags-y += -Wno-type-limits subdir-ccflags-y += -Wno-missing-field-initializers subdir-ccflags-y += -Wno-sign-compare +subdir-ccflags-y += -Wno-shift-negative-value subdir-ccflags-y += $(call cc-disable-warning, unused-but-set-variable) subdir-ccflags-y += $(call cc-disable-warning, frame-address) subdir-ccflags-$(CONFIG_DRM_I915_WERROR) += -Werror diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index ad1564ca7269..adf58c58513b 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -992,7 +992,8 @@ int intel_bw_atomic_check(struct intel_atomic_state *state) * cause. */ if (!intel_can_enable_sagv(dev_priv, new_bw_state)) { - allowed_points = BIT(max_bw_point); + allowed_points &= ADLS_PSF_PT_MASK; + allowed_points |= BIT(max_bw_point); drm_dbg_kms(&dev_priv->drm, "No SAGV, using single QGV point %d\n", max_bw_point); } diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 1aa5bdc7b0dc..6512f014cad4 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -1836,6 +1836,7 @@ hdmi_port_clock_valid(struct intel_hdmi *hdmi, bool has_hdmi_sink) { struct drm_i915_private *dev_priv = intel_hdmi_to_i915(hdmi); + enum phy phy = intel_port_to_phy(dev_priv, hdmi_to_dig_port(hdmi)->base.port); if (clock < 25000) return MODE_CLOCK_LOW; @@ -1856,6 +1857,14 @@ hdmi_port_clock_valid(struct intel_hdmi *hdmi, if (IS_CHERRYVIEW(dev_priv) && clock > 216000 && clock < 240000) return MODE_CLOCK_RANGE; + /* ICL+ combo PHY PLL can't generate 500-533.2 MHz */ + if (intel_phy_is_combo(dev_priv, phy) && clock > 500000 && clock < 533200) + return MODE_CLOCK_RANGE; + + /* ICL+ TC PHY PLL can't generate 500-532.8 MHz */ + if (intel_phy_is_tc(dev_priv, phy) && clock > 500000 && clock < 532800) + return MODE_CLOCK_RANGE; + /* * SNPS PHYs' MPLLB table-based programming can only handle a fixed * set of link rates. diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 5895b89df03a..bff8c2d73cdf 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -1439,6 +1439,13 @@ static inline u32 man_trk_ctl_single_full_frame_bit_get(struct drm_i915_private PSR2_MAN_TRK_CTL_SF_SINGLE_FULL_FRAME; } +static inline u32 man_trk_ctl_partial_frame_bit_get(struct drm_i915_private *dev_priv) +{ + return IS_ALDERLAKE_P(dev_priv) ? + ADLP_PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE : + PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE; +} + static void psr_force_hw_tracking_exit(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); @@ -1543,7 +1550,13 @@ static void psr2_man_trk_ctl_calc(struct intel_crtc_state *crtc_state, { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - u32 val = PSR2_MAN_TRK_CTL_ENABLE; + u32 val = 0; + + if (!IS_ALDERLAKE_P(dev_priv)) + val = PSR2_MAN_TRK_CTL_ENABLE; + + /* SF partial frame enable has to be set even on full update */ + val |= man_trk_ctl_partial_frame_bit_get(dev_priv); if (full_update) { /* @@ -1563,7 +1576,6 @@ static void psr2_man_trk_ctl_calc(struct intel_crtc_state *crtc_state, } else { drm_WARN_ON(crtc_state->uapi.crtc->dev, clip->y1 % 4 || clip->y2 % 4); - val |= PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE; val |= PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR(clip->y1 / 4 + 1); val |= PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR(clip->y2 / 4 + 1); } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c index 9bb551b83e7a..92cb88248391 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c @@ -57,7 +57,7 @@ struct __guc_ads_blob { struct guc_gt_system_info system_info; struct guc_engine_usage engine_usage; /* From here on, location is dynamic! Refer to above diagram. */ - struct guc_mmio_reg regset[0]; + struct guc_mmio_reg regset[]; } __packed; #define ads_blob_read(guc_, field_) \ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d134838b3458..fa14da84362e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -947,7 +947,7 @@ static inline struct intel_gt *to_gt(struct drm_i915_private *i915) (GRAPHICS_VER(i915) >= (from) && GRAPHICS_VER(i915) <= (until)) #define MEDIA_VER(i915) (INTEL_INFO(i915)->media.ver) -#define MEDIA_VER_FULL(i915) IP_VER(INTEL_INFO(i915)->media.arch, \ +#define MEDIA_VER_FULL(i915) IP_VER(INTEL_INFO(i915)->media.ver, \ INTEL_INFO(i915)->media.rel) #define IS_MEDIA_VER(i915, from, until) \ (MEDIA_VER(i915) >= (from) && MEDIA_VER(i915) <= (until)) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 4da10e131216..3c87d77d2cf6 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2320,6 +2320,7 @@ #define ADLP_PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR(val) REG_FIELD_PREP(ADLP_PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR_MASK, val) #define ADLP_PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR_MASK REG_GENMASK(12, 0) #define ADLP_PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR(val) REG_FIELD_PREP(ADLP_PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR_MASK, val) +#define ADLP_PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE REG_BIT(31) #define ADLP_PSR2_MAN_TRK_CTL_SF_SINGLE_FULL_FRAME REG_BIT(14) #define ADLP_PSR2_MAN_TRK_CTL_SF_CONTINUOS_FULL_FRAME REG_BIT(13) diff --git a/drivers/gpu/drm/i915/intel_pch.c b/drivers/gpu/drm/i915/intel_pch.c index 4f7a61d5502e..4cce044efde2 100644 --- a/drivers/gpu/drm/i915/intel_pch.c +++ b/drivers/gpu/drm/i915/intel_pch.c @@ -108,6 +108,7 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id) /* Comet Lake V PCH is based on KBP, which is SPT compatible */ return PCH_SPT; case INTEL_PCH_ICP_DEVICE_ID_TYPE: + case INTEL_PCH_ICP2_DEVICE_ID_TYPE: drm_dbg_kms(&dev_priv->drm, "Found Ice Lake PCH\n"); drm_WARN_ON(&dev_priv->drm, !IS_ICELAKE(dev_priv)); return PCH_ICP; @@ -123,7 +124,6 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id) !IS_GEN9_BC(dev_priv)); return PCH_TGP; case INTEL_PCH_JSP_DEVICE_ID_TYPE: - case INTEL_PCH_JSP2_DEVICE_ID_TYPE: drm_dbg_kms(&dev_priv->drm, "Found Jasper Lake PCH\n"); drm_WARN_ON(&dev_priv->drm, !IS_JSL_EHL(dev_priv)); return PCH_JSP; diff --git a/drivers/gpu/drm/i915/intel_pch.h b/drivers/gpu/drm/i915/intel_pch.h index 6fd20408f7bf..b7a8cf409d48 100644 --- a/drivers/gpu/drm/i915/intel_pch.h +++ b/drivers/gpu/drm/i915/intel_pch.h @@ -50,11 +50,11 @@ enum intel_pch { #define INTEL_PCH_CMP2_DEVICE_ID_TYPE 0x0680 #define INTEL_PCH_CMP_V_DEVICE_ID_TYPE 0xA380 #define INTEL_PCH_ICP_DEVICE_ID_TYPE 0x3480 +#define INTEL_PCH_ICP2_DEVICE_ID_TYPE 0x3880 #define INTEL_PCH_MCC_DEVICE_ID_TYPE 0x4B00 #define INTEL_PCH_TGP_DEVICE_ID_TYPE 0xA080 #define INTEL_PCH_TGP2_DEVICE_ID_TYPE 0x4380 #define INTEL_PCH_JSP_DEVICE_ID_TYPE 0x4D80 -#define INTEL_PCH_JSP2_DEVICE_ID_TYPE 0x3880 #define INTEL_PCH_ADP_DEVICE_ID_TYPE 0x7A80 #define INTEL_PCH_ADP2_DEVICE_ID_TYPE 0x5180 #define INTEL_PCH_ADP3_DEVICE_ID_TYPE 0x7A00 diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 71f7fba2c9e2..9333f732cda8 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3698,8 +3698,7 @@ skl_setup_sagv_block_time(struct drm_i915_private *dev_priv) MISSING_CASE(DISPLAY_VER(dev_priv)); } - /* Default to an unusable block time */ - dev_priv->sagv_block_time_us = -1; + dev_priv->sagv_block_time_us = 0; } /* @@ -5645,7 +5644,7 @@ static void skl_compute_plane_wm(const struct intel_crtc_state *crtc_state, result->min_ddb_alloc = max(min_ddb_alloc, blocks) + 1; result->enable = true; - if (DISPLAY_VER(dev_priv) < 12) + if (DISPLAY_VER(dev_priv) < 12 && dev_priv->sagv_block_time_us) result->can_sagv = latency >= dev_priv->sagv_block_time_us; } @@ -5678,7 +5677,10 @@ static void tgl_compute_sagv_wm(const struct intel_crtc_state *crtc_state, struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); struct skl_wm_level *sagv_wm = &plane_wm->sagv.wm0; struct skl_wm_level *levels = plane_wm->wm; - unsigned int latency = dev_priv->wm.skl_latency[0] + dev_priv->sagv_block_time_us; + unsigned int latency = 0; + + if (dev_priv->sagv_block_time_us) + latency = dev_priv->sagv_block_time_us + dev_priv->wm.skl_latency[0]; skl_compute_plane_wm(crtc_state, plane, 0, latency, wm_params, &levels[0], diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c index a8aba0141ce7..06cb1a59b9bc 100644 --- a/drivers/gpu/drm/imx/parallel-display.c +++ b/drivers/gpu/drm/imx/parallel-display.c @@ -217,14 +217,6 @@ static int imx_pd_bridge_atomic_check(struct drm_bridge *bridge, if (!imx_pd_format_supported(bus_fmt)) return -EINVAL; - if (bus_flags & - ~(DRM_BUS_FLAG_DE_LOW | DRM_BUS_FLAG_DE_HIGH | - DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE | - DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)) { - dev_warn(imxpd->dev, "invalid bus_flags (%x)\n", bus_flags); - return -EINVAL; - } - bridge_state->output_bus_cfg.flags = bus_flags; bridge_state->input_bus_cfg.flags = bus_flags; imx_crtc_state->bus_flags = bus_flags; diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index dcf44cb00821..ac52b49bf901 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -1371,11 +1371,6 @@ static int ingenic_drm_bind_with_components(struct device *dev) return ingenic_drm_bind(dev, true); } -static int compare_of(struct device *dev, void *data) -{ - return dev->of_node == data; -} - static void ingenic_drm_unbind(struct device *dev) { struct ingenic_drm *priv = dev_get_drvdata(dev); @@ -1409,7 +1404,7 @@ static int ingenic_drm_probe(struct platform_device *pdev) if (!np) return ingenic_drm_bind(dev, false); - drm_of_component_match_add(dev, &match, compare_of, np); + drm_of_component_match_add(dev, &match, component_compare_of, np); of_node_put(np); return component_master_add_with_match(dev, &ingenic_master_ops, match); diff --git a/drivers/gpu/drm/mcde/mcde_drv.c b/drivers/gpu/drm/mcde/mcde_drv.c index 0b2910e69b42..e601baa87e55 100644 --- a/drivers/gpu/drm/mcde/mcde_drv.c +++ b/drivers/gpu/drm/mcde/mcde_drv.c @@ -265,11 +265,6 @@ static struct platform_driver *const mcde_component_drivers[] = { &mcde_dsi_driver, }; -static int mcde_compare_dev(struct device *dev, void *data) -{ - return dev == data; -} - static int mcde_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -399,7 +394,7 @@ static int mcde_probe(struct platform_device *pdev) while ((d = platform_find_device_by_driver(p, drv))) { put_device(p); - component_match_add(dev, &match, mcde_compare_dev, d); + component_match_add(dev, &match, component_compare_dev, d); p = d; } put_device(p); diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 2146299e5f52..17cd9b932298 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -11,6 +11,7 @@ #include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/platform_device.h> +#include <linux/pm_runtime.h> #include <linux/soc/mediatek/mtk-cmdq.h> #include "mtk_disp_drv.h" @@ -414,9 +415,13 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev) return ret; } + pm_runtime_enable(dev); + ret = component_add(dev, &mtk_disp_ovl_component_ops); - if (ret) + if (ret) { + pm_runtime_disable(dev); dev_err(dev, "Failed to add component: %d\n", ret); + } return ret; } @@ -424,6 +429,7 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev) static int mtk_disp_ovl_remove(struct platform_device *pdev) { component_del(&pdev->dev, &mtk_disp_ovl_component_ops); + pm_runtime_disable(&pdev->dev); return 0; } diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c index d41a3970b944..662e91d9d45f 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c @@ -9,6 +9,7 @@ #include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/platform_device.h> +#include <linux/pm_runtime.h> #include <linux/soc/mediatek/mtk-cmdq.h> #include "mtk_disp_drv.h" @@ -327,9 +328,13 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev) platform_set_drvdata(pdev, priv); + pm_runtime_enable(dev); + ret = component_add(dev, &mtk_disp_rdma_component_ops); - if (ret) + if (ret) { + pm_runtime_disable(dev); dev_err(dev, "Failed to add component: %d\n", ret); + } return ret; } @@ -338,6 +343,8 @@ static int mtk_disp_rdma_remove(struct platform_device *pdev) { component_del(&pdev->dev, &mtk_disp_rdma_component_ops); + pm_runtime_disable(&pdev->dev); + return 0; } diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index 8cc0a1283d7c..ede435d2c1ef 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -12,7 +12,6 @@ #include <linux/soc/mediatek/mtk-mutex.h> #include <asm/barrier.h> -#include <soc/mediatek/smi.h> #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> @@ -663,15 +662,15 @@ static void mtk_drm_crtc_atomic_enable(struct drm_crtc *crtc, DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id); - ret = mtk_smi_larb_get(comp->larb_dev); - if (ret) { - DRM_ERROR("Failed to get larb: %d\n", ret); + ret = pm_runtime_resume_and_get(comp->dev); + if (ret < 0) { + DRM_DEV_ERROR(comp->dev, "Failed to enable power domain: %d\n", ret); return; } ret = mtk_crtc_ddp_hw_init(mtk_crtc); if (ret) { - mtk_smi_larb_put(comp->larb_dev); + pm_runtime_put(comp->dev); return; } @@ -684,7 +683,7 @@ static void mtk_drm_crtc_atomic_disable(struct drm_crtc *crtc, { struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0]; - int i; + int i, ret; DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id); if (!mtk_crtc->enabled) @@ -714,7 +713,9 @@ static void mtk_drm_crtc_atomic_disable(struct drm_crtc *crtc, drm_crtc_vblank_off(crtc); mtk_crtc_ddp_hw_fini(mtk_crtc); - mtk_smi_larb_put(comp->larb_dev); + ret = pm_runtime_put(comp->dev); + if (ret < 0) + DRM_DEV_ERROR(comp->dev, "Failed to disable power domain: %d\n", ret); mtk_crtc->enabled = false; } diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c index b4b682bc1991..2e99aee13dfe 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c @@ -447,37 +447,15 @@ unsigned int mtk_drm_find_possible_crtc_by_comp(struct drm_device *drm, return ret; } -static int mtk_ddp_get_larb_dev(struct device_node *node, struct mtk_ddp_comp *comp, - struct device *dev) -{ - struct device_node *larb_node; - struct platform_device *larb_pdev; - - larb_node = of_parse_phandle(node, "mediatek,larb", 0); - if (!larb_node) { - dev_err(dev, "Missing mediadek,larb phandle in %pOF node\n", node); - return -EINVAL; - } - - larb_pdev = of_find_device_by_node(larb_node); - if (!larb_pdev) { - dev_warn(dev, "Waiting for larb device %pOF\n", larb_node); - of_node_put(larb_node); - return -EPROBE_DEFER; - } - of_node_put(larb_node); - comp->larb_dev = &larb_pdev->dev; - - return 0; -} - int mtk_ddp_comp_init(struct device_node *node, struct mtk_ddp_comp *comp, enum mtk_ddp_comp_id comp_id) { struct platform_device *comp_pdev; enum mtk_ddp_comp_type type; struct mtk_ddp_comp_dev *priv; +#if IS_REACHABLE(CONFIG_MTK_CMDQ) int ret; +#endif if (comp_id < 0 || comp_id >= DDP_COMPONENT_ID_MAX) return -EINVAL; @@ -493,16 +471,6 @@ int mtk_ddp_comp_init(struct device_node *node, struct mtk_ddp_comp *comp, } comp->dev = &comp_pdev->dev; - /* Only DMA capable components need the LARB property */ - if (type == MTK_DISP_OVL || - type == MTK_DISP_OVL_2L || - type == MTK_DISP_RDMA || - type == MTK_DISP_WDMA) { - ret = mtk_ddp_get_larb_dev(node, comp, comp->dev); - if (ret) - return ret; - } - if (type == MTK_DISP_AAL || type == MTK_DISP_BLS || type == MTK_DISP_CCORR || diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h index 4c6a98662305..ad267bb8fc9b 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h @@ -71,7 +71,6 @@ struct mtk_ddp_comp_funcs { struct mtk_ddp_comp { struct device *dev; int irq; - struct device *larb_dev; enum mtk_ddp_comp_id id; const struct mtk_ddp_comp_funcs *funcs; }; diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index dd029307be7d..247c6ff277ef 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -372,11 +372,6 @@ static const struct drm_driver mtk_drm_driver = { .minor = DRIVER_MINOR, }; -static int compare_of(struct device *dev, void *data) -{ - return dev->of_node == data; -} - static int mtk_drm_bind(struct device *dev) { struct mtk_drm_private *private = dev_get_drvdata(dev); @@ -617,7 +612,7 @@ static int mtk_drm_probe(struct platform_device *pdev) comp_type == MTK_DSI) { dev_info(dev, "Adding component match for %pOF\n", node); - drm_of_component_match_add(dev, &match, compare_of, + drm_of_component_match_add(dev, &match, component_compare_of, node); } @@ -648,11 +643,8 @@ err_pm: pm_runtime_disable(dev); err_node: of_node_put(private->mutex_node); - for (i = 0; i < DDP_COMPONENT_ID_MAX; i++) { + for (i = 0; i < DDP_COMPONENT_ID_MAX; i++) of_node_put(private->comp_node[i]); - if (private->ddp_comp[i].larb_dev) - put_device(private->ddp_comp[i].larb_dev); - } return ret; } diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c index 93a7a033a3e8..edae79f41153 100644 --- a/drivers/gpu/drm/meson/meson_drv.c +++ b/drivers/gpu/drm/meson/meson_drv.c @@ -425,14 +425,6 @@ static int __maybe_unused meson_drv_pm_resume(struct device *dev) return drm_mode_config_helper_resume(priv->drm); } -static int compare_of(struct device *dev, void *data) -{ - DRM_DEBUG_DRIVER("Comparing of node %pOF with %pOF\n", - dev->of_node, data); - - return dev->of_node == data; -} - static void meson_drv_shutdown(struct platform_device *pdev) { struct meson_drm *priv = dev_get_drvdata(&pdev->dev); @@ -475,7 +467,7 @@ static int meson_drv_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "parent %pOF remote match add %pOF parent %s\n", np, remote, dev_name(&pdev->dev)); - component_match_add(&pdev->dev, &match, compare_of, remote); + component_match_add(&pdev->dev, &match, component_compare_of, remote); of_node_put(remote); diff --git a/drivers/gpu/drm/mgag200/mgag200_pll.c b/drivers/gpu/drm/mgag200/mgag200_pll.c index e9ae22b4f813..52be08b744ad 100644 --- a/drivers/gpu/drm/mgag200/mgag200_pll.c +++ b/drivers/gpu/drm/mgag200/mgag200_pll.c @@ -404,9 +404,9 @@ mgag200_pixpll_update_g200wb(struct mgag200_pll *pixpll, const struct mgag200_pl udelay(50); /* program pixel pll register */ - WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn); - WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm); - WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp); + WREG_DAC(MGA1064_WB_PIX_PLLC_N, xpixpllcn); + WREG_DAC(MGA1064_WB_PIX_PLLC_M, xpixpllcm); + WREG_DAC(MGA1064_WB_PIX_PLLC_P, xpixpllcp); udelay(50); diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 61c81af23ba7..affa95eb05fc 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -1050,15 +1050,6 @@ static const struct dev_pm_ops msm_pm_ops = { */ /* - * NOTE: duplication of the same code as exynos or imx (or probably any other). - * so probably some room for some helpers - */ -static int compare_of(struct device *dev, void *data) -{ - return dev->of_node == data; -} - -/* * Identify what components need to be added by parsing what remote-endpoints * our MDP output ports are connected to. In the case of LVDS on MDP4, there * is no external component that we need to add since LVDS is within MDP4 @@ -1115,7 +1106,7 @@ static int add_components_mdp(struct device *mdp_dev, if (of_device_is_available(intf)) drm_of_component_match_add(master_dev, matchptr, - compare_of, intf); + component_compare_of, intf); of_node_put(intf); } @@ -1161,7 +1152,7 @@ static int add_display_components(struct platform_device *pdev, put_device(mdp_dev); /* add the MDP component itself */ - drm_of_component_match_add(dev, matchptr, compare_of, + drm_of_component_match_add(dev, matchptr, component_compare_of, mdp_dev->of_node); break; case KMS_MDP4: @@ -1200,7 +1191,7 @@ static int add_gpu_components(struct device *dev, return 0; if (of_device_is_available(np)) - drm_of_component_match_add(dev, matchptr, compare_of, np); + drm_of_component_match_add(dev, matchptr, component_compare_of, np); of_node_put(np); diff --git a/drivers/gpu/drm/nouveau/include/nvfw/hs.h b/drivers/gpu/drm/nouveau/include/nvfw/hs.h index 64d0d32200c2..b53bbc4cd130 100644 --- a/drivers/gpu/drm/nouveau/include/nvfw/hs.h +++ b/drivers/gpu/drm/nouveau/include/nvfw/hs.h @@ -23,7 +23,7 @@ struct nvfw_hs_load_header { u32 data_dma_base; u32 data_size; u32 num_apps; - u32 apps[0]; + u32 apps[]; }; const struct nvfw_hs_load_header * diff --git a/drivers/gpu/drm/nouveau/nouveau_dmem.c b/drivers/gpu/drm/nouveau/nouveau_dmem.c index 3828aafd3ac4..7ba66ad68a8a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dmem.c +++ b/drivers/gpu/drm/nouveau/nouveau_dmem.c @@ -39,6 +39,8 @@ #include <linux/sched/mm.h> #include <linux/hmm.h> +#include <linux/memremap.h> +#include <linux/migrate.h> /* * FIXME: this is ugly right now we are using TTM to allocate vram and we pin @@ -324,7 +326,6 @@ nouveau_dmem_page_alloc_locked(struct nouveau_drm *drm) return NULL; } - get_page(page); lock_page(page); return page; } diff --git a/drivers/gpu/drm/nouveau/nouveau_svm.c b/drivers/gpu/drm/nouveau/nouveau_svm.c index 46a5a1016e37..31a5b81ee9fc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_svm.c +++ b/drivers/gpu/drm/nouveau/nouveau_svm.c @@ -35,6 +35,7 @@ #include <linux/sched/mm.h> #include <linux/sort.h> #include <linux/hmm.h> +#include <linux/memremap.h> #include <linux/rmap.h> struct nouveau_svm { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c index d0d52c1d4aee..992cc285f2fe 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c @@ -133,7 +133,7 @@ nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev) * or equal to the system's PAGE_SIZE, with a preference if * both are equal. */ - pgsize_bitmap = tdev->iommu.domain->ops->pgsize_bitmap; + pgsize_bitmap = tdev->iommu.domain->pgsize_bitmap; if (pgsize_bitmap & PAGE_SIZE) { tdev->iommu.pgshift = PAGE_SHIFT; } else { diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c b/drivers/gpu/drm/omapdrm/dss/dss.c index 69b3e15b9356..0399f3390a0a 100644 --- a/drivers/gpu/drm/omapdrm/dss/dss.c +++ b/drivers/gpu/drm/omapdrm/dss/dss.c @@ -1344,12 +1344,6 @@ static const struct component_master_ops dss_component_ops = { .unbind = dss_unbind, }; -static int dss_component_compare(struct device *dev, void *data) -{ - struct device *child = data; - return dev == child; -} - struct dss_component_match_data { struct device *dev; struct component_match **match; @@ -1379,7 +1373,7 @@ static int dss_add_child_component(struct device *dev, void *data) return device_for_each_child(dev, cmatch, dss_add_child_component); - component_match_add(cmatch->dev, match, dss_component_compare, dev); + component_match_add(cmatch->dev, match, component_compare_dev, dev); return 0; } diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index bb2e47229c68..ddf5f38e8731 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -107,6 +107,7 @@ config DRM_PANEL_EDP select VIDEOMODE_HELPERS select DRM_DP_AUX_BUS select DRM_DP_HELPER + select DRM_KMS_HELPER help DRM panel driver for dumb eDP panels that need at most a regulator and a GPIO to be powered up. Optionally a backlight can be attached so diff --git a/drivers/gpu/drm/panel/panel-abt-y030xx067a.c b/drivers/gpu/drm/panel/panel-abt-y030xx067a.c index f043b484055b..ed626fdc08e8 100644 --- a/drivers/gpu/drm/panel/panel-abt-y030xx067a.c +++ b/drivers/gpu/drm/panel/panel-abt-y030xx067a.c @@ -293,15 +293,13 @@ static int y030xx067a_probe(struct spi_device *spi) return 0; } -static int y030xx067a_remove(struct spi_device *spi) +static void y030xx067a_remove(struct spi_device *spi) { struct y030xx067a *priv = spi_get_drvdata(spi); drm_panel_remove(&priv->panel); drm_panel_disable(&priv->panel); drm_panel_unprepare(&priv->panel); - - return 0; } static const struct drm_display_mode y030xx067a_modes[] = { diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9322.c b/drivers/gpu/drm/panel/panel-ilitek-ili9322.c index 8e84df9a0033..3dfafa585127 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9322.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9322.c @@ -896,14 +896,12 @@ static int ili9322_probe(struct spi_device *spi) return 0; } -static int ili9322_remove(struct spi_device *spi) +static void ili9322_remove(struct spi_device *spi) { struct ili9322 *ili = spi_get_drvdata(spi); ili9322_power_off(ili); drm_panel_remove(&ili->panel); - - return 0; } /* diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c index 2c3378a259b1..a07ef26234e5 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c @@ -728,7 +728,7 @@ static int ili9341_probe(struct spi_device *spi) return -1; } -static int ili9341_remove(struct spi_device *spi) +static void ili9341_remove(struct spi_device *spi) { const struct spi_device_id *id = spi_get_device_id(spi); struct ili9341 *ili = spi_get_drvdata(spi); @@ -741,7 +741,6 @@ static int ili9341_remove(struct spi_device *spi) drm_dev_unplug(drm); drm_atomic_helper_shutdown(drm); } - return 0; } static void ili9341_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/panel/panel-innolux-ej030na.c b/drivers/gpu/drm/panel/panel-innolux-ej030na.c index c558de3f99be..e3b1daa0cb72 100644 --- a/drivers/gpu/drm/panel/panel-innolux-ej030na.c +++ b/drivers/gpu/drm/panel/panel-innolux-ej030na.c @@ -219,15 +219,13 @@ static int ej030na_probe(struct spi_device *spi) return 0; } -static int ej030na_remove(struct spi_device *spi) +static void ej030na_remove(struct spi_device *spi) { struct ej030na *priv = spi_get_drvdata(spi); drm_panel_remove(&priv->panel); drm_panel_disable(&priv->panel); drm_panel_unprepare(&priv->panel); - - return 0; } static const struct drm_display_mode ej030na_modes[] = { diff --git a/drivers/gpu/drm/panel/panel-lg-lb035q02.c b/drivers/gpu/drm/panel/panel-lg-lb035q02.c index f3183b68704f..9d0d4faa3f58 100644 --- a/drivers/gpu/drm/panel/panel-lg-lb035q02.c +++ b/drivers/gpu/drm/panel/panel-lg-lb035q02.c @@ -203,14 +203,12 @@ static int lb035q02_probe(struct spi_device *spi) return 0; } -static int lb035q02_remove(struct spi_device *spi) +static void lb035q02_remove(struct spi_device *spi) { struct lb035q02_device *lcd = spi_get_drvdata(spi); drm_panel_remove(&lcd->panel); drm_panel_disable(&lcd->panel); - - return 0; } static const struct of_device_id lb035q02_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-lg-lg4573.c b/drivers/gpu/drm/panel/panel-lg-lg4573.c index 8e5160af1de5..cf246d15b7b6 100644 --- a/drivers/gpu/drm/panel/panel-lg-lg4573.c +++ b/drivers/gpu/drm/panel/panel-lg-lg4573.c @@ -266,14 +266,12 @@ static int lg4573_probe(struct spi_device *spi) return 0; } -static int lg4573_remove(struct spi_device *spi) +static void lg4573_remove(struct spi_device *spi) { struct lg4573 *ctx = spi_get_drvdata(spi); lg4573_display_off(ctx); drm_panel_remove(&ctx->panel); - - return 0; } static const struct of_device_id lg4573_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-nec-nl8048hl11.c b/drivers/gpu/drm/panel/panel-nec-nl8048hl11.c index 6e5ab1debc8b..81c5c541a351 100644 --- a/drivers/gpu/drm/panel/panel-nec-nl8048hl11.c +++ b/drivers/gpu/drm/panel/panel-nec-nl8048hl11.c @@ -212,15 +212,13 @@ static int nl8048_probe(struct spi_device *spi) return 0; } -static int nl8048_remove(struct spi_device *spi) +static void nl8048_remove(struct spi_device *spi) { struct nl8048_panel *lcd = spi_get_drvdata(spi); drm_panel_remove(&lcd->panel); drm_panel_disable(&lcd->panel); drm_panel_unprepare(&lcd->panel); - - return 0; } static const struct of_device_id nl8048_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-novatek-nt39016.c b/drivers/gpu/drm/panel/panel-novatek-nt39016.c index d036853db865..f58cfb10b58a 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt39016.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt39016.c @@ -292,7 +292,7 @@ static int nt39016_probe(struct spi_device *spi) return 0; } -static int nt39016_remove(struct spi_device *spi) +static void nt39016_remove(struct spi_device *spi) { struct nt39016 *panel = spi_get_drvdata(spi); @@ -300,8 +300,6 @@ static int nt39016_remove(struct spi_device *spi) nt39016_disable(&panel->drm_panel); nt39016_unprepare(&panel->drm_panel); - - return 0; } static const struct drm_display_mode kd035g6_display_modes[] = { diff --git a/drivers/gpu/drm/panel/panel-samsung-db7430.c b/drivers/gpu/drm/panel/panel-samsung-db7430.c index ead479719f00..04640c5256a8 100644 --- a/drivers/gpu/drm/panel/panel-samsung-db7430.c +++ b/drivers/gpu/drm/panel/panel-samsung-db7430.c @@ -314,12 +314,11 @@ static int db7430_probe(struct spi_device *spi) return 0; } -static int db7430_remove(struct spi_device *spi) +static void db7430_remove(struct spi_device *spi) { struct db7430 *db = spi_get_drvdata(spi); drm_panel_remove(&db->panel); - return 0; } /* diff --git a/drivers/gpu/drm/panel/panel-samsung-ld9040.c b/drivers/gpu/drm/panel/panel-samsung-ld9040.c index c4b388850a13..01eb211f32f7 100644 --- a/drivers/gpu/drm/panel/panel-samsung-ld9040.c +++ b/drivers/gpu/drm/panel/panel-samsung-ld9040.c @@ -358,14 +358,12 @@ static int ld9040_probe(struct spi_device *spi) return 0; } -static int ld9040_remove(struct spi_device *spi) +static void ld9040_remove(struct spi_device *spi) { struct ld9040 *ctx = spi_get_drvdata(spi); ld9040_power_off(ctx); drm_panel_remove(&ctx->panel); - - return 0; } static const struct of_device_id ld9040_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-samsung-s6d27a1.c b/drivers/gpu/drm/panel/panel-samsung-s6d27a1.c index 1696ceb36aa0..2adb223a895c 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6d27a1.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6d27a1.c @@ -291,12 +291,11 @@ static int s6d27a1_probe(struct spi_device *spi) return 0; } -static int s6d27a1_remove(struct spi_device *spi) +static void s6d27a1_remove(struct spi_device *spi) { struct s6d27a1 *ctx = spi_get_drvdata(spi); drm_panel_remove(&ctx->panel); - return 0; } static const struct of_device_id s6d27a1_match[] = { diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c index c178d962b0d5..d99afcc672ca 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c @@ -62,10 +62,9 @@ static int s6e63m0_spi_probe(struct spi_device *spi) s6e63m0_spi_dcs_write, false); } -static int s6e63m0_spi_remove(struct spi_device *spi) +static void s6e63m0_spi_remove(struct spi_device *spi) { s6e63m0_remove(&spi->dev); - return 0; } static const struct of_device_id s6e63m0_spi_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index c09eb5ad65fc..a34f4198a534 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -2017,7 +2017,7 @@ static const struct display_timing innolux_g070y2_l01_timing = { static const struct panel_desc innolux_g070y2_l01 = { .timings = &innolux_g070y2_l01_timing, .num_timings = 1, - .bpc = 6, + .bpc = 8, .size = { .width = 152, .height = 91, diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7789v.c b/drivers/gpu/drm/panel/panel-sitronix-st7789v.c index 61e565524542..bbc4569cbcdc 100644 --- a/drivers/gpu/drm/panel/panel-sitronix-st7789v.c +++ b/drivers/gpu/drm/panel/panel-sitronix-st7789v.c @@ -387,13 +387,11 @@ static int st7789v_probe(struct spi_device *spi) return 0; } -static int st7789v_remove(struct spi_device *spi) +static void st7789v_remove(struct spi_device *spi) { struct st7789v *ctx = spi_get_drvdata(spi); drm_panel_remove(&ctx->panel); - - return 0; } static const struct of_device_id st7789v_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-sony-acx565akm.c b/drivers/gpu/drm/panel/panel-sony-acx565akm.c index ba0b3ead150f..0d7541a33f87 100644 --- a/drivers/gpu/drm/panel/panel-sony-acx565akm.c +++ b/drivers/gpu/drm/panel/panel-sony-acx565akm.c @@ -655,7 +655,7 @@ static int acx565akm_probe(struct spi_device *spi) return 0; } -static int acx565akm_remove(struct spi_device *spi) +static void acx565akm_remove(struct spi_device *spi) { struct acx565akm_panel *lcd = spi_get_drvdata(spi); @@ -666,8 +666,6 @@ static int acx565akm_remove(struct spi_device *spi) drm_panel_disable(&lcd->panel); drm_panel_unprepare(&lcd->panel); - - return 0; } static const struct of_device_id acx565akm_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-tpo-td028ttec1.c b/drivers/gpu/drm/panel/panel-tpo-td028ttec1.c index ba0c00d1a001..4dbf8b88f264 100644 --- a/drivers/gpu/drm/panel/panel-tpo-td028ttec1.c +++ b/drivers/gpu/drm/panel/panel-tpo-td028ttec1.c @@ -350,15 +350,13 @@ static int td028ttec1_probe(struct spi_device *spi) return 0; } -static int td028ttec1_remove(struct spi_device *spi) +static void td028ttec1_remove(struct spi_device *spi) { struct td028ttec1_panel *lcd = spi_get_drvdata(spi); drm_panel_remove(&lcd->panel); drm_panel_disable(&lcd->panel); drm_panel_unprepare(&lcd->panel); - - return 0; } static const struct of_device_id td028ttec1_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-tpo-td043mtea1.c b/drivers/gpu/drm/panel/panel-tpo-td043mtea1.c index 1866cdb8f9c1..cf4609bb9b1d 100644 --- a/drivers/gpu/drm/panel/panel-tpo-td043mtea1.c +++ b/drivers/gpu/drm/panel/panel-tpo-td043mtea1.c @@ -463,7 +463,7 @@ static int td043mtea1_probe(struct spi_device *spi) return 0; } -static int td043mtea1_remove(struct spi_device *spi) +static void td043mtea1_remove(struct spi_device *spi) { struct td043mtea1_panel *lcd = spi_get_drvdata(spi); @@ -472,8 +472,6 @@ static int td043mtea1_remove(struct spi_device *spi) drm_panel_unprepare(&lcd->panel); sysfs_remove_group(&spi->dev.kobj, &td043mtea1_attr_group); - - return 0; } static const struct of_device_id td043mtea1_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-tpo-tpg110.c b/drivers/gpu/drm/panel/panel-tpo-tpg110.c index e3791dad6830..0b1f5a11a055 100644 --- a/drivers/gpu/drm/panel/panel-tpo-tpg110.c +++ b/drivers/gpu/drm/panel/panel-tpo-tpg110.c @@ -450,12 +450,11 @@ static int tpg110_probe(struct spi_device *spi) return 0; } -static int tpg110_remove(struct spi_device *spi) +static void tpg110_remove(struct spi_device *spi) { struct tpg110 *tpg = spi_get_drvdata(spi); drm_panel_remove(&tpg->panel); - return 0; } static const struct of_device_id tpg110_match[] = { diff --git a/drivers/gpu/drm/panel/panel-widechips-ws2401.c b/drivers/gpu/drm/panel/panel-widechips-ws2401.c index 8bc976f54b80..236f3cb2b594 100644 --- a/drivers/gpu/drm/panel/panel-widechips-ws2401.c +++ b/drivers/gpu/drm/panel/panel-widechips-ws2401.c @@ -407,12 +407,11 @@ static int ws2401_probe(struct spi_device *spi) return 0; } -static int ws2401_remove(struct spi_device *spi) +static void ws2401_remove(struct spi_device *spi) { struct ws2401 *ws = spi_get_drvdata(spi); drm_panel_remove(&ws->panel); - return 0; } /* diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c index 4740cc14beb8..d3e6c93739bf 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c @@ -586,6 +586,13 @@ static bool cdn_dp_check_link_status(struct cdn_dp_device *dp) return drm_dp_channel_eq_ok(link_status, min(port->lanes, sink_lanes)); } +static void cdn_dp_audio_handle_plugged_change(struct cdn_dp_device *dp, + bool plugged) +{ + if (dp->codec_dev) + dp->plugged_cb(dp->codec_dev, plugged); +} + static void cdn_dp_encoder_enable(struct drm_encoder *encoder) { struct cdn_dp_device *dp = encoder_to_dp(encoder); @@ -641,6 +648,9 @@ static void cdn_dp_encoder_enable(struct drm_encoder *encoder) DRM_DEV_ERROR(dp->dev, "Failed to valid video %d\n", ret); goto out; } + + cdn_dp_audio_handle_plugged_change(dp, true); + out: mutex_unlock(&dp->lock); } @@ -651,6 +661,8 @@ static void cdn_dp_encoder_disable(struct drm_encoder *encoder) int ret; mutex_lock(&dp->lock); + cdn_dp_audio_handle_plugged_change(dp, false); + if (dp->active) { ret = cdn_dp_disable(dp); if (ret) { @@ -846,11 +858,27 @@ static int cdn_dp_audio_get_eld(struct device *dev, void *data, return 0; } +static int cdn_dp_audio_hook_plugged_cb(struct device *dev, void *data, + hdmi_codec_plugged_cb fn, + struct device *codec_dev) +{ + struct cdn_dp_device *dp = dev_get_drvdata(dev); + + mutex_lock(&dp->lock); + dp->plugged_cb = fn; + dp->codec_dev = codec_dev; + cdn_dp_audio_handle_plugged_change(dp, dp->connected); + mutex_unlock(&dp->lock); + + return 0; +} + static const struct hdmi_codec_ops audio_codec_ops = { .hw_params = cdn_dp_audio_hw_params, .audio_shutdown = cdn_dp_audio_shutdown, .mute_stream = cdn_dp_audio_mute_stream, .get_eld = cdn_dp_audio_get_eld, + .hook_plugged_cb = cdn_dp_audio_hook_plugged_cb, .no_capture_mute = 1, }; diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h b/drivers/gpu/drm/rockchip/cdn-dp-core.h index 0d044146f4e9..6d0c5032ef3a 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-core.h +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h @@ -10,6 +10,7 @@ #include <drm/dp/drm_dp_helper.h> #include <drm/drm_panel.h> #include <drm/drm_probe_helper.h> +#include <sound/hdmi-codec.h> #include "rockchip_drm_drv.h" @@ -101,5 +102,8 @@ struct cdn_dp_device { u8 dpcd[DP_RECEIVER_CAP_SIZE]; bool sink_has_audio; + + hdmi_codec_plugged_cb plugged_cb; + struct device *codec_dev; }; #endif /* _CDN_DP_CORE_H */ diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index ac190e2b1f7a..4eaeb430c83a 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -290,11 +290,6 @@ int rockchip_drm_endpoint_is_subdriver(struct device_node *ep) return false; } -static int compare_dev(struct device *dev, void *data) -{ - return dev == (struct device *)data; -} - static void rockchip_drm_match_remove(struct device *dev) { struct device_link *link; @@ -321,7 +316,7 @@ static struct component_match *rockchip_drm_match_add(struct device *dev) break; device_link_add(dev, d, DL_FLAG_STATELESS); - component_match_add(dev, &match, compare_dev, d); + component_match_add(dev, &match, component_compare_dev, d); } while (true); } diff --git a/drivers/gpu/drm/selftests/test-drm_plane_helper.c b/drivers/gpu/drm/selftests/test-drm_plane_helper.c index ceebeede55ea..b61273e9c403 100644 --- a/drivers/gpu/drm/selftests/test-drm_plane_helper.c +++ b/drivers/gpu/drm/selftests/test-drm_plane_helper.c @@ -77,7 +77,7 @@ int igt_check_plane_state(void *ignored) { int ret; - const struct drm_crtc_state crtc_state = { + static const struct drm_crtc_state crtc_state = { .crtc = ZERO_SIZE_PTR, .enable = true, .active = true, @@ -87,14 +87,14 @@ int igt_check_plane_state(void *ignored) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, }; - struct drm_plane plane = { + static struct drm_plane plane = { .dev = NULL }; - struct drm_framebuffer fb = { + static struct drm_framebuffer fb = { .width = 2048, .height = 2048 }; - struct drm_plane_state plane_state = { + static struct drm_plane_state plane_state = { .plane = &plane, .crtc = ZERO_SIZE_PTR, .fb = &fb, diff --git a/drivers/gpu/drm/sprd/sprd_drm.c b/drivers/gpu/drm/sprd/sprd_drm.c index a60ecdd67d98..b8fc1c6a0cb8 100644 --- a/drivers/gpu/drm/sprd/sprd_drm.c +++ b/drivers/gpu/drm/sprd/sprd_drm.c @@ -133,14 +133,9 @@ static const struct component_master_ops drm_component_ops = { .unbind = sprd_drm_unbind, }; -static int compare_of(struct device *dev, void *data) -{ - return dev->of_node == data; -} - static int sprd_drm_probe(struct platform_device *pdev) { - return drm_of_component_probe(&pdev->dev, compare_of, &drm_component_ops); + return drm_of_component_probe(&pdev->dev, component_compare_of, &drm_component_ops); } static int sprd_drm_remove(struct platform_device *pdev) diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c index 860b2230aa08..d858209cf8de 100644 --- a/drivers/gpu/drm/sti/sti_drv.c +++ b/drivers/gpu/drm/sti/sti_drv.c @@ -144,11 +144,6 @@ static const struct drm_driver sti_driver = { .minor = DRIVER_MINOR, }; -static int compare_of(struct device *dev, void *data) -{ - return dev->of_node == data; -} - static int sti_init(struct drm_device *ddev) { struct sti_private *private; @@ -244,7 +239,7 @@ static int sti_platform_probe(struct platform_device *pdev) child_np = of_get_next_available_child(node, NULL); while (child_np) { - drm_of_component_match_add(dev, &match, compare_of, + drm_of_component_match_add(dev, &match, component_compare_of, child_np); child_np = of_get_next_available_child(node, child_np); } diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index a3fd441dd9ad..6a9ba8a77c77 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c @@ -202,15 +202,6 @@ static bool sun4i_drv_node_is_tcon_top(struct device_node *node) !!of_match_node(sun8i_tcon_top_of_table, node); } -static int compare_of(struct device *dev, void *data) -{ - DRM_DEBUG_DRIVER("Comparing of node %pOF with %pOF\n", - dev->of_node, - data); - - return dev->of_node == data; -} - /* * The encoder drivers use drm_of_find_possible_crtcs to get upstream * crtcs from the device tree using of_graph. For the results to be @@ -330,7 +321,7 @@ static int sun4i_drv_add_endpoints(struct device *dev, of_device_is_available(node))) { /* Add current component */ DRM_DEBUG_DRIVER("Adding component %pOF\n", node); - drm_of_component_match_add(dev, match, compare_of, node); + drm_of_component_match_add(dev, match, component_compare_of, node); count++; } diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h index 145833a9d82d..5b3fbee18671 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.h +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h @@ -111,10 +111,10 @@ /* format 13 is semi-planar YUV411 VUVU */ #define SUN8I_MIXER_FBFMT_YUV411 14 /* format 15 doesn't exist */ -/* format 16 is P010 YVU */ -#define SUN8I_MIXER_FBFMT_P010_YUV 17 -/* format 18 is P210 YVU */ -#define SUN8I_MIXER_FBFMT_P210_YUV 19 +#define SUN8I_MIXER_FBFMT_P010_YUV 16 +/* format 17 is P010 YVU */ +#define SUN8I_MIXER_FBFMT_P210_YUV 18 +/* format 19 is P210 YVU */ /* format 20 is packed YVU444 10-bit */ /* format 21 is packed YUV444 10-bit */ diff --git a/drivers/gpu/drm/tiny/hx8357d.c b/drivers/gpu/drm/tiny/hx8357d.c index 9b33c05732aa..ebb025543f8d 100644 --- a/drivers/gpu/drm/tiny/hx8357d.c +++ b/drivers/gpu/drm/tiny/hx8357d.c @@ -263,14 +263,12 @@ static int hx8357d_probe(struct spi_device *spi) return 0; } -static int hx8357d_remove(struct spi_device *spi) +static void hx8357d_remove(struct spi_device *spi) { struct drm_device *drm = spi_get_drvdata(spi); drm_dev_unplug(drm); drm_atomic_helper_shutdown(drm); - - return 0; } static void hx8357d_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/tiny/ili9163.c b/drivers/gpu/drm/tiny/ili9163.c index bcc181351236..fc8ed245b0bc 100644 --- a/drivers/gpu/drm/tiny/ili9163.c +++ b/drivers/gpu/drm/tiny/ili9163.c @@ -193,14 +193,12 @@ static int ili9163_probe(struct spi_device *spi) return 0; } -static int ili9163_remove(struct spi_device *spi) +static void ili9163_remove(struct spi_device *spi) { struct drm_device *drm = spi_get_drvdata(spi); drm_dev_unplug(drm); drm_atomic_helper_shutdown(drm); - - return 0; } static void ili9163_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/tiny/ili9225.c b/drivers/gpu/drm/tiny/ili9225.c index 976d3209f164..cc92eb9f2a07 100644 --- a/drivers/gpu/drm/tiny/ili9225.c +++ b/drivers/gpu/drm/tiny/ili9225.c @@ -411,14 +411,12 @@ static int ili9225_probe(struct spi_device *spi) return 0; } -static int ili9225_remove(struct spi_device *spi) +static void ili9225_remove(struct spi_device *spi) { struct drm_device *drm = spi_get_drvdata(spi); drm_dev_unplug(drm); drm_atomic_helper_shutdown(drm); - - return 0; } static void ili9225_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/tiny/ili9341.c b/drivers/gpu/drm/tiny/ili9341.c index 37e0c33399c8..5b8cc770ee7b 100644 --- a/drivers/gpu/drm/tiny/ili9341.c +++ b/drivers/gpu/drm/tiny/ili9341.c @@ -225,14 +225,12 @@ static int ili9341_probe(struct spi_device *spi) return 0; } -static int ili9341_remove(struct spi_device *spi) +static void ili9341_remove(struct spi_device *spi) { struct drm_device *drm = spi_get_drvdata(spi); drm_dev_unplug(drm); drm_atomic_helper_shutdown(drm); - - return 0; } static void ili9341_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/tiny/ili9486.c b/drivers/gpu/drm/tiny/ili9486.c index e9a63f4b2993..6d655e18e0aa 100644 --- a/drivers/gpu/drm/tiny/ili9486.c +++ b/drivers/gpu/drm/tiny/ili9486.c @@ -243,14 +243,12 @@ static int ili9486_probe(struct spi_device *spi) return 0; } -static int ili9486_remove(struct spi_device *spi) +static void ili9486_remove(struct spi_device *spi) { struct drm_device *drm = spi_get_drvdata(spi); drm_dev_unplug(drm); drm_atomic_helper_shutdown(drm); - - return 0; } static void ili9486_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/tiny/mi0283qt.c b/drivers/gpu/drm/tiny/mi0283qt.c index 023de49e7a8e..5e060f6910bb 100644 --- a/drivers/gpu/drm/tiny/mi0283qt.c +++ b/drivers/gpu/drm/tiny/mi0283qt.c @@ -233,14 +233,12 @@ static int mi0283qt_probe(struct spi_device *spi) return 0; } -static int mi0283qt_remove(struct spi_device *spi) +static void mi0283qt_remove(struct spi_device *spi) { struct drm_device *drm = spi_get_drvdata(spi); drm_dev_unplug(drm); drm_atomic_helper_shutdown(drm); - - return 0; } static void mi0283qt_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/tiny/panel-mipi-dbi.c b/drivers/gpu/drm/tiny/panel-mipi-dbi.c index 7f8c6c51387f..c759ff9c2c87 100644 --- a/drivers/gpu/drm/tiny/panel-mipi-dbi.c +++ b/drivers/gpu/drm/tiny/panel-mipi-dbi.c @@ -336,14 +336,12 @@ static int panel_mipi_dbi_spi_probe(struct spi_device *spi) return 0; } -static int panel_mipi_dbi_spi_remove(struct spi_device *spi) +static void panel_mipi_dbi_spi_remove(struct spi_device *spi) { struct drm_device *drm = spi_get_drvdata(spi); drm_dev_unplug(drm); drm_atomic_helper_shutdown(drm); - - return 0; } static void panel_mipi_dbi_spi_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/tiny/repaper.c b/drivers/gpu/drm/tiny/repaper.c index 5c74e236b16d..37b6bb90e46e 100644 --- a/drivers/gpu/drm/tiny/repaper.c +++ b/drivers/gpu/drm/tiny/repaper.c @@ -1118,14 +1118,12 @@ static int repaper_probe(struct spi_device *spi) return 0; } -static int repaper_remove(struct spi_device *spi) +static void repaper_remove(struct spi_device *spi) { struct drm_device *drm = spi_get_drvdata(spi); drm_dev_unplug(drm); drm_atomic_helper_shutdown(drm); - - return 0; } static void repaper_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/tiny/st7586.c b/drivers/gpu/drm/tiny/st7586.c index 51b9b9fb3ead..3f38faa1cd8c 100644 --- a/drivers/gpu/drm/tiny/st7586.c +++ b/drivers/gpu/drm/tiny/st7586.c @@ -360,14 +360,12 @@ static int st7586_probe(struct spi_device *spi) return 0; } -static int st7586_remove(struct spi_device *spi) +static void st7586_remove(struct spi_device *spi) { struct drm_device *drm = spi_get_drvdata(spi); drm_dev_unplug(drm); drm_atomic_helper_shutdown(drm); - - return 0; } static void st7586_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/tiny/st7735r.c b/drivers/gpu/drm/tiny/st7735r.c index fc40dd10efa8..29d618093e94 100644 --- a/drivers/gpu/drm/tiny/st7735r.c +++ b/drivers/gpu/drm/tiny/st7735r.c @@ -247,14 +247,12 @@ static int st7735r_probe(struct spi_device *spi) return 0; } -static int st7735r_remove(struct spi_device *spi) +static void st7735r_remove(struct spi_device *spi) { struct drm_device *drm = spi_get_drvdata(spi); drm_dev_unplug(drm); drm_atomic_helper_shutdown(drm); - - return 0; } static void st7735r_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/ttm/ttm_range_manager.c b/drivers/gpu/drm/ttm/ttm_range_manager.c index 8cd4f3fb9f79..d91666721dc6 100644 --- a/drivers/gpu/drm/ttm/ttm_range_manager.c +++ b/drivers/gpu/drm/ttm/ttm_range_manager.c @@ -89,7 +89,7 @@ static int ttm_range_man_alloc(struct ttm_resource_manager *man, spin_unlock(&rman->lock); if (unlikely(ret)) { - ttm_resource_fini(man, *res); + ttm_resource_fini(man, &node->base); kfree(node); return ret; } diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index a03053c8e22c..162bc18e7497 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -189,11 +189,6 @@ static struct drm_driver vc4_drm_driver = { .patchlevel = DRIVER_PATCHLEVEL, }; -static int compare_dev(struct device *dev, void *data) -{ - return dev == data; -} - static void vc4_match_add_drivers(struct device *dev, struct component_match **match, struct platform_driver *const *drivers, @@ -207,7 +202,7 @@ static void vc4_match_add_drivers(struct device *dev, while ((d = platform_find_device_by_driver(p, drv))) { put_device(p); - component_match_add(dev, match, compare_dev, d); + component_match_add(dev, match, component_compare_dev, d); p = d; } put_device(p); diff --git a/drivers/gpu/drm/xen/xen_drm_front_evtchnl.c b/drivers/gpu/drm/xen/xen_drm_front_evtchnl.c index e10d95dddb99..08b526eeec16 100644 --- a/drivers/gpu/drm/xen/xen_drm_front_evtchnl.c +++ b/drivers/gpu/drm/xen/xen_drm_front_evtchnl.c @@ -148,7 +148,7 @@ static void evtchnl_free(struct xen_drm_front_info *front_info, /* end access and free the page */ if (evtchnl->gref != GRANT_INVALID_REF) - gnttab_end_foreign_access(evtchnl->gref, 0, page); + gnttab_end_foreign_access(evtchnl->gref, page); memset(evtchnl, 0, sizeof(*evtchnl)); } diff --git a/drivers/gpu/ipu-v3/ipu-csi.c b/drivers/gpu/ipu-v3/ipu-csi.c index a9639d098893..778bc26d3ba5 100644 --- a/drivers/gpu/ipu-v3/ipu-csi.c +++ b/drivers/gpu/ipu-v3/ipu-csi.c @@ -357,11 +357,11 @@ static int fill_csi_bus_cfg(struct ipu_csi_bus_config *csicfg, switch (mbus_cfg->type) { case V4L2_MBUS_PARALLEL: csicfg->ext_vsync = 1; - csicfg->vsync_pol = (mbus_cfg->flags & + csicfg->vsync_pol = (mbus_cfg->bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW) ? 1 : 0; - csicfg->hsync_pol = (mbus_cfg->flags & + csicfg->hsync_pol = (mbus_cfg->bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW) ? 1 : 0; - csicfg->pixclk_pol = (mbus_cfg->flags & + csicfg->pixclk_pol = (mbus_cfg->bus.parallel.flags & V4L2_MBUS_PCLK_SAMPLE_FALLING) ? 1 : 0; csicfg->clk_mode = IPU_CSI_CLK_MODE_GATED_CLK; break; diff --git a/drivers/gpu/vga/Kconfig b/drivers/gpu/vga/Kconfig index 1ad4c4ef0b5e..eb8b14ab22c3 100644 --- a/drivers/gpu/vga/Kconfig +++ b/drivers/gpu/vga/Kconfig @@ -1,23 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only -config VGA_ARB - bool "VGA Arbitration" if EXPERT - default y - depends on (PCI && !S390) - help - Some "legacy" VGA devices implemented on PCI typically have the same - hard-decoded addresses as they did on ISA. When multiple PCI devices - are accessed at same time they need some kind of coordination. Please - see Documentation/gpu/vgaarbiter.rst for more details. Select this to - enable VGA arbiter. - -config VGA_ARB_MAX_GPUS - int "Maximum number of GPUs" - default 16 - depends on VGA_ARB - help - Reserves space in the kernel to maintain resource locking for - multiple GPUS. The overhead for each GPU is very small. - config VGA_SWITCHEROO bool "Laptop Hybrid Graphics - GPU switching support" depends on X86 diff --git a/drivers/gpu/vga/Makefile b/drivers/gpu/vga/Makefile index e92064442d60..9800620deda3 100644 --- a/drivers/gpu/vga/Makefile +++ b/drivers/gpu/vga/Makefile @@ -1,3 +1,2 @@ # SPDX-License-Identifier: GPL-2.0-only -obj-$(CONFIG_VGA_ARB) += vgaarb.o obj-$(CONFIG_VGA_SWITCHEROO) += vga_switcheroo.o diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c deleted file mode 100644 index 569930552957..000000000000 --- a/drivers/gpu/vga/vgaarb.c +++ /dev/null @@ -1,1567 +0,0 @@ -/* - * vgaarb.c: Implements the VGA arbitration. For details refer to - * Documentation/gpu/vgaarbiter.rst - * - * - * (C) Copyright 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org> - * (C) Copyright 2007 Paulo R. Zanoni <przanoni@gmail.com> - * (C) Copyright 2007, 2009 Tiago Vignatti <vignatti@freedesktop.org> - * - * 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 (including the next - * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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. - * - */ - -#define pr_fmt(fmt) "vgaarb: " fmt - -#define vgaarb_dbg(dev, fmt, arg...) dev_dbg(dev, "vgaarb: " fmt, ##arg) -#define vgaarb_info(dev, fmt, arg...) dev_info(dev, "vgaarb: " fmt, ##arg) -#define vgaarb_err(dev, fmt, arg...) dev_err(dev, "vgaarb: " fmt, ##arg) - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/list.h> -#include <linux/sched/signal.h> -#include <linux/wait.h> -#include <linux/spinlock.h> -#include <linux/poll.h> -#include <linux/miscdevice.h> -#include <linux/slab.h> -#include <linux/screen_info.h> -#include <linux/vt.h> -#include <linux/console.h> -#include <linux/acpi.h> - -#include <linux/uaccess.h> - -#include <linux/vgaarb.h> - -static void vga_arbiter_notify_clients(void); -/* - * We keep a list of all vga devices in the system to speed - * up the various operations of the arbiter - */ -struct vga_device { - struct list_head list; - struct pci_dev *pdev; - unsigned int decodes; /* what does it decodes */ - unsigned int owns; /* what does it owns */ - unsigned int locks; /* what does it locks */ - unsigned int io_lock_cnt; /* legacy IO lock count */ - unsigned int mem_lock_cnt; /* legacy MEM lock count */ - unsigned int io_norm_cnt; /* normal IO count */ - unsigned int mem_norm_cnt; /* normal MEM count */ - bool bridge_has_one_vga; - unsigned int (*set_decode)(struct pci_dev *pdev, bool decode); -}; - -static LIST_HEAD(vga_list); -static int vga_count, vga_decode_count; -static bool vga_arbiter_used; -static DEFINE_SPINLOCK(vga_lock); -static DECLARE_WAIT_QUEUE_HEAD(vga_wait_queue); - - -static const char *vga_iostate_to_str(unsigned int iostate) -{ - /* Ignore VGA_RSRC_IO and VGA_RSRC_MEM */ - iostate &= VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM; - switch (iostate) { - case VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM: - return "io+mem"; - case VGA_RSRC_LEGACY_IO: - return "io"; - case VGA_RSRC_LEGACY_MEM: - return "mem"; - } - return "none"; -} - -static int vga_str_to_iostate(char *buf, int str_size, int *io_state) -{ - /* we could in theory hand out locks on IO and mem - * separately to userspace but it can cause deadlocks */ - if (strncmp(buf, "none", 4) == 0) { - *io_state = VGA_RSRC_NONE; - return 1; - } - - /* XXX We're not chekcing the str_size! */ - if (strncmp(buf, "io+mem", 6) == 0) - goto both; - else if (strncmp(buf, "io", 2) == 0) - goto both; - else if (strncmp(buf, "mem", 3) == 0) - goto both; - return 0; -both: - *io_state = VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM; - return 1; -} - -/* this is only used a cookie - it should not be dereferenced */ -static struct pci_dev *vga_default; - -static void vga_arb_device_card_gone(struct pci_dev *pdev); - -/* Find somebody in our list */ -static struct vga_device *vgadev_find(struct pci_dev *pdev) -{ - struct vga_device *vgadev; - - list_for_each_entry(vgadev, &vga_list, list) - if (pdev == vgadev->pdev) - return vgadev; - return NULL; -} - -/** - * vga_default_device - return the default VGA device, for vgacon - * - * This can be defined by the platform. The default implementation - * is rather dumb and will probably only work properly on single - * vga card setups and/or x86 platforms. - * - * If your VGA default device is not PCI, you'll have to return - * NULL here. In this case, I assume it will not conflict with - * any PCI card. If this is not true, I'll have to define two archs - * hooks for enabling/disabling the VGA default device if that is - * possible. This may be a problem with real _ISA_ VGA cards, in - * addition to a PCI one. I don't know at this point how to deal - * with that card. Can theirs IOs be disabled at all ? If not, then - * I suppose it's a matter of having the proper arch hook telling - * us about it, so we basically never allow anybody to succeed a - * vga_get()... - */ -struct pci_dev *vga_default_device(void) -{ - return vga_default; -} -EXPORT_SYMBOL_GPL(vga_default_device); - -void vga_set_default_device(struct pci_dev *pdev) -{ - if (vga_default == pdev) - return; - - pci_dev_put(vga_default); - vga_default = pci_dev_get(pdev); -} - -/** - * vga_remove_vgacon - deactivete vga console - * - * Unbind and unregister vgacon in case pdev is the default vga - * device. Can be called by gpu drivers on initialization to make - * sure vga register access done by vgacon will not disturb the - * device. - * - * @pdev: pci device. - */ -#if !defined(CONFIG_VGA_CONSOLE) -int vga_remove_vgacon(struct pci_dev *pdev) -{ - return 0; -} -#elif !defined(CONFIG_DUMMY_CONSOLE) -int vga_remove_vgacon(struct pci_dev *pdev) -{ - return -ENODEV; -} -#else -int vga_remove_vgacon(struct pci_dev *pdev) -{ - int ret = 0; - - if (pdev != vga_default) - return 0; - vgaarb_info(&pdev->dev, "deactivate vga console\n"); - - console_lock(); - if (con_is_bound(&vga_con)) - ret = do_take_over_console(&dummy_con, 0, - MAX_NR_CONSOLES - 1, 1); - if (ret == 0) { - ret = do_unregister_con_driver(&vga_con); - - /* Ignore "already unregistered". */ - if (ret == -ENODEV) - ret = 0; - } - console_unlock(); - - return ret; -} -#endif -EXPORT_SYMBOL(vga_remove_vgacon); - -/* If we don't ever use VGA arb we should avoid - turning off anything anywhere due to old X servers getting - confused about the boot device not being VGA */ -static void vga_check_first_use(void) -{ - /* we should inform all GPUs in the system that - * VGA arb has occurred and to try and disable resources - * if they can */ - if (!vga_arbiter_used) { - vga_arbiter_used = true; - vga_arbiter_notify_clients(); - } -} - -static struct vga_device *__vga_tryget(struct vga_device *vgadev, - unsigned int rsrc) -{ - struct device *dev = &vgadev->pdev->dev; - unsigned int wants, legacy_wants, match; - struct vga_device *conflict; - unsigned int pci_bits; - u32 flags = 0; - - /* Account for "normal" resources to lock. If we decode the legacy, - * counterpart, we need to request it as well - */ - if ((rsrc & VGA_RSRC_NORMAL_IO) && - (vgadev->decodes & VGA_RSRC_LEGACY_IO)) - rsrc |= VGA_RSRC_LEGACY_IO; - if ((rsrc & VGA_RSRC_NORMAL_MEM) && - (vgadev->decodes & VGA_RSRC_LEGACY_MEM)) - rsrc |= VGA_RSRC_LEGACY_MEM; - - vgaarb_dbg(dev, "%s: %d\n", __func__, rsrc); - vgaarb_dbg(dev, "%s: owns: %d\n", __func__, vgadev->owns); - - /* Check what resources we need to acquire */ - wants = rsrc & ~vgadev->owns; - - /* We already own everything, just mark locked & bye bye */ - if (wants == 0) - goto lock_them; - - /* We don't need to request a legacy resource, we just enable - * appropriate decoding and go - */ - legacy_wants = wants & VGA_RSRC_LEGACY_MASK; - if (legacy_wants == 0) - goto enable_them; - - /* Ok, we don't, let's find out how we need to kick off */ - list_for_each_entry(conflict, &vga_list, list) { - unsigned int lwants = legacy_wants; - unsigned int change_bridge = 0; - - /* Don't conflict with myself */ - if (vgadev == conflict) - continue; - - /* We have a possible conflict. before we go further, we must - * check if we sit on the same bus as the conflicting device. - * if we don't, then we must tie both IO and MEM resources - * together since there is only a single bit controlling - * VGA forwarding on P2P bridges - */ - if (vgadev->pdev->bus != conflict->pdev->bus) { - change_bridge = 1; - lwants = VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM; - } - - /* Check if the guy has a lock on the resource. If he does, - * return the conflicting entry - */ - if (conflict->locks & lwants) - return conflict; - - /* Ok, now check if it owns the resource we want. We can - * lock resources that are not decoded, therefore a device - * can own resources it doesn't decode. - */ - match = lwants & conflict->owns; - if (!match) - continue; - - /* looks like he doesn't have a lock, we can steal - * them from him - */ - - flags = 0; - pci_bits = 0; - - /* If we can't control legacy resources via the bridge, we - * also need to disable normal decoding. - */ - if (!conflict->bridge_has_one_vga) { - if ((match & conflict->decodes) & VGA_RSRC_LEGACY_MEM) - pci_bits |= PCI_COMMAND_MEMORY; - if ((match & conflict->decodes) & VGA_RSRC_LEGACY_IO) - pci_bits |= PCI_COMMAND_IO; - - if (pci_bits) - flags |= PCI_VGA_STATE_CHANGE_DECODES; - } - - if (change_bridge) - flags |= PCI_VGA_STATE_CHANGE_BRIDGE; - - pci_set_vga_state(conflict->pdev, false, pci_bits, flags); - conflict->owns &= ~match; - - /* If we disabled normal decoding, reflect it in owns */ - if (pci_bits & PCI_COMMAND_MEMORY) - conflict->owns &= ~VGA_RSRC_NORMAL_MEM; - if (pci_bits & PCI_COMMAND_IO) - conflict->owns &= ~VGA_RSRC_NORMAL_IO; - } - -enable_them: - /* ok dude, we got it, everybody conflicting has been disabled, let's - * enable us. Mark any bits in "owns" regardless of whether we - * decoded them. We can lock resources we don't decode, therefore - * we must track them via "owns". - */ - flags = 0; - pci_bits = 0; - - if (!vgadev->bridge_has_one_vga) { - flags |= PCI_VGA_STATE_CHANGE_DECODES; - if (wants & (VGA_RSRC_LEGACY_MEM|VGA_RSRC_NORMAL_MEM)) - pci_bits |= PCI_COMMAND_MEMORY; - if (wants & (VGA_RSRC_LEGACY_IO|VGA_RSRC_NORMAL_IO)) - pci_bits |= PCI_COMMAND_IO; - } - if (wants & VGA_RSRC_LEGACY_MASK) - flags |= PCI_VGA_STATE_CHANGE_BRIDGE; - - pci_set_vga_state(vgadev->pdev, true, pci_bits, flags); - - vgadev->owns |= wants; -lock_them: - vgadev->locks |= (rsrc & VGA_RSRC_LEGACY_MASK); - if (rsrc & VGA_RSRC_LEGACY_IO) - vgadev->io_lock_cnt++; - if (rsrc & VGA_RSRC_LEGACY_MEM) - vgadev->mem_lock_cnt++; - if (rsrc & VGA_RSRC_NORMAL_IO) - vgadev->io_norm_cnt++; - if (rsrc & VGA_RSRC_NORMAL_MEM) - vgadev->mem_norm_cnt++; - - return NULL; -} - -static void __vga_put(struct vga_device *vgadev, unsigned int rsrc) -{ - struct device *dev = &vgadev->pdev->dev; - unsigned int old_locks = vgadev->locks; - - vgaarb_dbg(dev, "%s\n", __func__); - - /* Update our counters, and account for equivalent legacy resources - * if we decode them - */ - if ((rsrc & VGA_RSRC_NORMAL_IO) && vgadev->io_norm_cnt > 0) { - vgadev->io_norm_cnt--; - if (vgadev->decodes & VGA_RSRC_LEGACY_IO) - rsrc |= VGA_RSRC_LEGACY_IO; - } - if ((rsrc & VGA_RSRC_NORMAL_MEM) && vgadev->mem_norm_cnt > 0) { - vgadev->mem_norm_cnt--; - if (vgadev->decodes & VGA_RSRC_LEGACY_MEM) - rsrc |= VGA_RSRC_LEGACY_MEM; - } - if ((rsrc & VGA_RSRC_LEGACY_IO) && vgadev->io_lock_cnt > 0) - vgadev->io_lock_cnt--; - if ((rsrc & VGA_RSRC_LEGACY_MEM) && vgadev->mem_lock_cnt > 0) - vgadev->mem_lock_cnt--; - - /* Just clear lock bits, we do lazy operations so we don't really - * have to bother about anything else at this point - */ - if (vgadev->io_lock_cnt == 0) - vgadev->locks &= ~VGA_RSRC_LEGACY_IO; - if (vgadev->mem_lock_cnt == 0) - vgadev->locks &= ~VGA_RSRC_LEGACY_MEM; - - /* Kick the wait queue in case somebody was waiting if we actually - * released something - */ - if (old_locks != vgadev->locks) - wake_up_all(&vga_wait_queue); -} - -/** - * vga_get - acquire & locks VGA resources - * @pdev: pci device of the VGA card or NULL for the system default - * @rsrc: bit mask of resources to acquire and lock - * @interruptible: blocking should be interruptible by signals ? - * - * This function acquires VGA resources for the given card and mark those - * resources locked. If the resource requested are "normal" (and not legacy) - * resources, the arbiter will first check whether the card is doing legacy - * decoding for that type of resource. If yes, the lock is "converted" into a - * legacy resource lock. - * - * The arbiter will first look for all VGA cards that might conflict and disable - * their IOs and/or Memory access, including VGA forwarding on P2P bridges if - * necessary, so that the requested resources can be used. Then, the card is - * marked as locking these resources and the IO and/or Memory accesses are - * enabled on the card (including VGA forwarding on parent P2P bridges if any). - * - * This function will block if some conflicting card is already locking one of - * the required resources (or any resource on a different bus segment, since P2P - * bridges don't differentiate VGA memory and IO afaik). You can indicate - * whether this blocking should be interruptible by a signal (for userland - * interface) or not. - * - * Must not be called at interrupt time or in atomic context. If the card - * already owns the resources, the function succeeds. Nested calls are - * supported (a per-resource counter is maintained) - * - * On success, release the VGA resource again with vga_put(). - * - * Returns: - * - * 0 on success, negative error code on failure. - */ -int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible) -{ - struct vga_device *vgadev, *conflict; - unsigned long flags; - wait_queue_entry_t wait; - int rc = 0; - - vga_check_first_use(); - /* The one who calls us should check for this, but lets be sure... */ - if (pdev == NULL) - pdev = vga_default_device(); - if (pdev == NULL) - return 0; - - for (;;) { - spin_lock_irqsave(&vga_lock, flags); - vgadev = vgadev_find(pdev); - if (vgadev == NULL) { - spin_unlock_irqrestore(&vga_lock, flags); - rc = -ENODEV; - break; - } - conflict = __vga_tryget(vgadev, rsrc); - spin_unlock_irqrestore(&vga_lock, flags); - if (conflict == NULL) - break; - - - /* We have a conflict, we wait until somebody kicks the - * work queue. Currently we have one work queue that we - * kick each time some resources are released, but it would - * be fairly easy to have a per device one so that we only - * need to attach to the conflicting device - */ - init_waitqueue_entry(&wait, current); - add_wait_queue(&vga_wait_queue, &wait); - set_current_state(interruptible ? - TASK_INTERRUPTIBLE : - TASK_UNINTERRUPTIBLE); - if (interruptible && signal_pending(current)) { - __set_current_state(TASK_RUNNING); - remove_wait_queue(&vga_wait_queue, &wait); - rc = -ERESTARTSYS; - break; - } - schedule(); - remove_wait_queue(&vga_wait_queue, &wait); - } - return rc; -} -EXPORT_SYMBOL(vga_get); - -/** - * vga_tryget - try to acquire & lock legacy VGA resources - * @pdev: pci devivce of VGA card or NULL for system default - * @rsrc: bit mask of resources to acquire and lock - * - * This function performs the same operation as vga_get(), but will return an - * error (-EBUSY) instead of blocking if the resources are already locked by - * another card. It can be called in any context - * - * On success, release the VGA resource again with vga_put(). - * - * Returns: - * - * 0 on success, negative error code on failure. - */ -static int vga_tryget(struct pci_dev *pdev, unsigned int rsrc) -{ - struct vga_device *vgadev; - unsigned long flags; - int rc = 0; - - vga_check_first_use(); - - /* The one who calls us should check for this, but lets be sure... */ - if (pdev == NULL) - pdev = vga_default_device(); - if (pdev == NULL) - return 0; - spin_lock_irqsave(&vga_lock, flags); - vgadev = vgadev_find(pdev); - if (vgadev == NULL) { - rc = -ENODEV; - goto bail; - } - if (__vga_tryget(vgadev, rsrc)) - rc = -EBUSY; -bail: - spin_unlock_irqrestore(&vga_lock, flags); - return rc; -} - -/** - * vga_put - release lock on legacy VGA resources - * @pdev: pci device of VGA card or NULL for system default - * @rsrc: but mask of resource to release - * - * This fuction releases resources previously locked by vga_get() or - * vga_tryget(). The resources aren't disabled right away, so that a subsequence - * vga_get() on the same card will succeed immediately. Resources have a - * counter, so locks are only released if the counter reaches 0. - */ -void vga_put(struct pci_dev *pdev, unsigned int rsrc) -{ - struct vga_device *vgadev; - unsigned long flags; - - /* The one who calls us should check for this, but lets be sure... */ - if (pdev == NULL) - pdev = vga_default_device(); - if (pdev == NULL) - return; - spin_lock_irqsave(&vga_lock, flags); - vgadev = vgadev_find(pdev); - if (vgadev == NULL) - goto bail; - __vga_put(vgadev, rsrc); -bail: - spin_unlock_irqrestore(&vga_lock, flags); -} -EXPORT_SYMBOL(vga_put); - -/* - * Rules for using a bridge to control a VGA descendant decoding: if a bridge - * has only one VGA descendant then it can be used to control the VGA routing - * for that device. It should always use the bridge closest to the device to - * control it. If a bridge has a direct VGA descendant, but also have a sub- - * bridge VGA descendant then we cannot use that bridge to control the direct - * VGA descendant. So for every device we register, we need to iterate all - * its parent bridges so we can invalidate any devices using them properly. - */ -static void vga_arbiter_check_bridge_sharing(struct vga_device *vgadev) -{ - struct vga_device *same_bridge_vgadev; - struct pci_bus *new_bus, *bus; - struct pci_dev *new_bridge, *bridge; - - vgadev->bridge_has_one_vga = true; - - if (list_empty(&vga_list)) - return; - - /* okay iterate the new devices bridge hierarachy */ - new_bus = vgadev->pdev->bus; - while (new_bus) { - new_bridge = new_bus->self; - - /* go through list of devices already registered */ - list_for_each_entry(same_bridge_vgadev, &vga_list, list) { - bus = same_bridge_vgadev->pdev->bus; - bridge = bus->self; - - /* see if the share a bridge with this device */ - if (new_bridge == bridge) { - /* - * If their direct parent bridge is the same - * as any bridge of this device then it can't - * be used for that device. - */ - same_bridge_vgadev->bridge_has_one_vga = false; - } - - /* - * Now iterate the previous devices bridge hierarchy. - * If the new devices parent bridge is in the other - * devices hierarchy then we can't use it to control - * this device - */ - while (bus) { - bridge = bus->self; - - if (bridge && bridge == vgadev->pdev->bus->self) - vgadev->bridge_has_one_vga = false; - - bus = bus->parent; - } - } - new_bus = new_bus->parent; - } -} - -/* - * Currently, we assume that the "initial" setup of the system is - * not sane, that is we come up with conflicting devices and let - * the arbiter's client decides if devices decodes or not legacy - * things. - */ -static bool vga_arbiter_add_pci_device(struct pci_dev *pdev) -{ - struct vga_device *vgadev; - unsigned long flags; - struct pci_bus *bus; - struct pci_dev *bridge; - u16 cmd; - - /* Only deal with VGA class devices */ - if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA) - return false; - - /* Allocate structure */ - vgadev = kzalloc(sizeof(struct vga_device), GFP_KERNEL); - if (vgadev == NULL) { - vgaarb_err(&pdev->dev, "failed to allocate VGA arbiter data\n"); - /* - * What to do on allocation failure ? For now, let's just do - * nothing, I'm not sure there is anything saner to be done. - */ - return false; - } - - /* Take lock & check for duplicates */ - spin_lock_irqsave(&vga_lock, flags); - if (vgadev_find(pdev) != NULL) { - BUG_ON(1); - goto fail; - } - vgadev->pdev = pdev; - - /* By default, assume we decode everything */ - vgadev->decodes = VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM | - VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; - - /* by default mark it as decoding */ - vga_decode_count++; - /* Mark that we "own" resources based on our enables, we will - * clear that below if the bridge isn't forwarding - */ - pci_read_config_word(pdev, PCI_COMMAND, &cmd); - if (cmd & PCI_COMMAND_IO) - vgadev->owns |= VGA_RSRC_LEGACY_IO; - if (cmd & PCI_COMMAND_MEMORY) - vgadev->owns |= VGA_RSRC_LEGACY_MEM; - - /* Check if VGA cycles can get down to us */ - bus = pdev->bus; - while (bus) { - bridge = bus->self; - if (bridge) { - u16 l; - - pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &l); - if (!(l & PCI_BRIDGE_CTL_VGA)) { - vgadev->owns = 0; - break; - } - } - bus = bus->parent; - } - - /* Deal with VGA default device. Use first enabled one - * by default if arch doesn't have it's own hook - */ - if (vga_default == NULL && - ((vgadev->owns & VGA_RSRC_LEGACY_MASK) == VGA_RSRC_LEGACY_MASK)) { - vgaarb_info(&pdev->dev, "setting as boot VGA device\n"); - vga_set_default_device(pdev); - } - - vga_arbiter_check_bridge_sharing(vgadev); - - /* Add to the list */ - list_add_tail(&vgadev->list, &vga_list); - vga_count++; - vgaarb_info(&pdev->dev, "VGA device added: decodes=%s,owns=%s,locks=%s\n", - vga_iostate_to_str(vgadev->decodes), - vga_iostate_to_str(vgadev->owns), - vga_iostate_to_str(vgadev->locks)); - - spin_unlock_irqrestore(&vga_lock, flags); - return true; -fail: - spin_unlock_irqrestore(&vga_lock, flags); - kfree(vgadev); - return false; -} - -static bool vga_arbiter_del_pci_device(struct pci_dev *pdev) -{ - struct vga_device *vgadev; - unsigned long flags; - bool ret = true; - - spin_lock_irqsave(&vga_lock, flags); - vgadev = vgadev_find(pdev); - if (vgadev == NULL) { - ret = false; - goto bail; - } - - if (vga_default == pdev) - vga_set_default_device(NULL); - - if (vgadev->decodes & (VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM)) - vga_decode_count--; - - /* Remove entry from list */ - list_del(&vgadev->list); - vga_count--; - /* Notify userland driver that the device is gone so it discards - * it's copies of the pci_dev pointer - */ - vga_arb_device_card_gone(pdev); - - /* Wake up all possible waiters */ - wake_up_all(&vga_wait_queue); -bail: - spin_unlock_irqrestore(&vga_lock, flags); - kfree(vgadev); - return ret; -} - -/* this is called with the lock */ -static inline void vga_update_device_decodes(struct vga_device *vgadev, - int new_decodes) -{ - struct device *dev = &vgadev->pdev->dev; - int old_decodes, decodes_removed, decodes_unlocked; - - old_decodes = vgadev->decodes; - decodes_removed = ~new_decodes & old_decodes; - decodes_unlocked = vgadev->locks & decodes_removed; - vgadev->decodes = new_decodes; - - vgaarb_info(dev, "changed VGA decodes: olddecodes=%s,decodes=%s:owns=%s\n", - vga_iostate_to_str(old_decodes), - vga_iostate_to_str(vgadev->decodes), - vga_iostate_to_str(vgadev->owns)); - - /* if we removed locked decodes, lock count goes to zero, and release */ - if (decodes_unlocked) { - if (decodes_unlocked & VGA_RSRC_LEGACY_IO) - vgadev->io_lock_cnt = 0; - if (decodes_unlocked & VGA_RSRC_LEGACY_MEM) - vgadev->mem_lock_cnt = 0; - __vga_put(vgadev, decodes_unlocked); - } - - /* change decodes counter */ - if (old_decodes & VGA_RSRC_LEGACY_MASK && - !(new_decodes & VGA_RSRC_LEGACY_MASK)) - vga_decode_count--; - if (!(old_decodes & VGA_RSRC_LEGACY_MASK) && - new_decodes & VGA_RSRC_LEGACY_MASK) - vga_decode_count++; - vgaarb_dbg(dev, "decoding count now is: %d\n", vga_decode_count); -} - -static void __vga_set_legacy_decoding(struct pci_dev *pdev, - unsigned int decodes, - bool userspace) -{ - struct vga_device *vgadev; - unsigned long flags; - - decodes &= VGA_RSRC_LEGACY_MASK; - - spin_lock_irqsave(&vga_lock, flags); - vgadev = vgadev_find(pdev); - if (vgadev == NULL) - goto bail; - - /* don't let userspace futz with kernel driver decodes */ - if (userspace && vgadev->set_decode) - goto bail; - - /* update the device decodes + counter */ - vga_update_device_decodes(vgadev, decodes); - - /* XXX if somebody is going from "doesn't decode" to "decodes" state - * here, additional care must be taken as we may have pending owner - * ship of non-legacy region ... - */ -bail: - spin_unlock_irqrestore(&vga_lock, flags); -} - -/** - * vga_set_legacy_decoding - * @pdev: pci device of the VGA card - * @decodes: bit mask of what legacy regions the card decodes - * - * Indicates to the arbiter if the card decodes legacy VGA IOs, legacy VGA - * Memory, both, or none. All cards default to both, the card driver (fbdev for - * example) should tell the arbiter if it has disabled legacy decoding, so the - * card can be left out of the arbitration process (and can be safe to take - * interrupts at any time. - */ -void vga_set_legacy_decoding(struct pci_dev *pdev, unsigned int decodes) -{ - __vga_set_legacy_decoding(pdev, decodes, false); -} -EXPORT_SYMBOL(vga_set_legacy_decoding); - -/** - * vga_client_register - register or unregister a VGA arbitration client - * @pdev: pci device of the VGA client - * @set_decode: vga decode change callback - * - * Clients have two callback mechanisms they can use. - * - * @set_decode callback: If a client can disable its GPU VGA resource, it - * will get a callback from this to set the encode/decode state. - * - * Rationale: we cannot disable VGA decode resources unconditionally some single - * GPU laptops seem to require ACPI or BIOS access to the VGA registers to - * control things like backlights etc. Hopefully newer multi-GPU laptops do - * something saner, and desktops won't have any special ACPI for this. The - * driver will get a callback when VGA arbitration is first used by userspace - * since some older X servers have issues. - * - * This function does not check whether a client for @pdev has been registered - * already. - * - * To unregister just call vga_client_unregister(). - * - * Returns: 0 on success, -1 on failure - */ -int vga_client_register(struct pci_dev *pdev, - unsigned int (*set_decode)(struct pci_dev *pdev, bool decode)) -{ - int ret = -ENODEV; - struct vga_device *vgadev; - unsigned long flags; - - spin_lock_irqsave(&vga_lock, flags); - vgadev = vgadev_find(pdev); - if (!vgadev) - goto bail; - - vgadev->set_decode = set_decode; - ret = 0; - -bail: - spin_unlock_irqrestore(&vga_lock, flags); - return ret; - -} -EXPORT_SYMBOL(vga_client_register); - -/* - * Char driver implementation - * - * Semantics is: - * - * open : open user instance of the arbitrer. by default, it's - * attached to the default VGA device of the system. - * - * close : close user instance, release locks - * - * read : return a string indicating the status of the target. - * an IO state string is of the form {io,mem,io+mem,none}, - * mc and ic are respectively mem and io lock counts (for - * debugging/diagnostic only). "decodes" indicate what the - * card currently decodes, "owns" indicates what is currently - * enabled on it, and "locks" indicates what is locked by this - * card. If the card is unplugged, we get "invalid" then for - * card_ID and an -ENODEV error is returned for any command - * until a new card is targeted - * - * "<card_ID>,decodes=<io_state>,owns=<io_state>,locks=<io_state> (ic,mc)" - * - * write : write a command to the arbiter. List of commands is: - * - * target <card_ID> : switch target to card <card_ID> (see below) - * lock <io_state> : acquires locks on target ("none" is invalid io_state) - * trylock <io_state> : non-blocking acquire locks on target - * unlock <io_state> : release locks on target - * unlock all : release all locks on target held by this user - * decodes <io_state> : set the legacy decoding attributes for the card - * - * poll : event if something change on any card (not just the target) - * - * card_ID is of the form "PCI:domain:bus:dev.fn". It can be set to "default" - * to go back to the system default card (TODO: not implemented yet). - * Currently, only PCI is supported as a prefix, but the userland API may - * support other bus types in the future, even if the current kernel - * implementation doesn't. - * - * Note about locks: - * - * The driver keeps track of which user has what locks on which card. It - * supports stacking, like the kernel one. This complexifies the implementation - * a bit, but makes the arbiter more tolerant to userspace problems and able - * to properly cleanup in all cases when a process dies. - * Currently, a max of 16 cards simultaneously can have locks issued from - * userspace for a given user (file descriptor instance) of the arbiter. - * - * If the device is hot-unplugged, there is a hook inside the module to notify - * they being added/removed in the system and automatically added/removed in - * the arbiter. - */ - -#define MAX_USER_CARDS CONFIG_VGA_ARB_MAX_GPUS -#define PCI_INVALID_CARD ((struct pci_dev *)-1UL) - -/* - * Each user has an array of these, tracking which cards have locks - */ -struct vga_arb_user_card { - struct pci_dev *pdev; - unsigned int mem_cnt; - unsigned int io_cnt; -}; - -struct vga_arb_private { - struct list_head list; - struct pci_dev *target; - struct vga_arb_user_card cards[MAX_USER_CARDS]; - spinlock_t lock; -}; - -static LIST_HEAD(vga_user_list); -static DEFINE_SPINLOCK(vga_user_lock); - - -/* - * This function gets a string in the format: "PCI:domain:bus:dev.fn" and - * returns the respective values. If the string is not in this format, - * it returns 0. - */ -static int vga_pci_str_to_vars(char *buf, int count, unsigned int *domain, - unsigned int *bus, unsigned int *devfn) -{ - int n; - unsigned int slot, func; - - - n = sscanf(buf, "PCI:%x:%x:%x.%x", domain, bus, &slot, &func); - if (n != 4) - return 0; - - *devfn = PCI_DEVFN(slot, func); - - return 1; -} - -static ssize_t vga_arb_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - struct vga_arb_private *priv = file->private_data; - struct vga_device *vgadev; - struct pci_dev *pdev; - unsigned long flags; - size_t len; - int rc; - char *lbuf; - - lbuf = kmalloc(1024, GFP_KERNEL); - if (lbuf == NULL) - return -ENOMEM; - - /* Shields against vga_arb_device_card_gone (pci_dev going - * away), and allows access to vga list - */ - spin_lock_irqsave(&vga_lock, flags); - - /* If we are targeting the default, use it */ - pdev = priv->target; - if (pdev == NULL || pdev == PCI_INVALID_CARD) { - spin_unlock_irqrestore(&vga_lock, flags); - len = sprintf(lbuf, "invalid"); - goto done; - } - - /* Find card vgadev structure */ - vgadev = vgadev_find(pdev); - if (vgadev == NULL) { - /* Wow, it's not in the list, that shouldn't happen, - * let's fix us up and return invalid card - */ - if (pdev == priv->target) - vga_arb_device_card_gone(pdev); - spin_unlock_irqrestore(&vga_lock, flags); - len = sprintf(lbuf, "invalid"); - goto done; - } - - /* Fill the buffer with infos */ - len = snprintf(lbuf, 1024, - "count:%d,PCI:%s,decodes=%s,owns=%s,locks=%s(%d:%d)\n", - vga_decode_count, pci_name(pdev), - vga_iostate_to_str(vgadev->decodes), - vga_iostate_to_str(vgadev->owns), - vga_iostate_to_str(vgadev->locks), - vgadev->io_lock_cnt, vgadev->mem_lock_cnt); - - spin_unlock_irqrestore(&vga_lock, flags); -done: - - /* Copy that to user */ - if (len > count) - len = count; - rc = copy_to_user(buf, lbuf, len); - kfree(lbuf); - if (rc) - return -EFAULT; - return len; -} - -/* - * TODO: To avoid parsing inside kernel and to improve the speed we may - * consider use ioctl here - */ -static ssize_t vga_arb_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - struct vga_arb_private *priv = file->private_data; - struct vga_arb_user_card *uc = NULL; - struct pci_dev *pdev; - - unsigned int io_state; - - char kbuf[64], *curr_pos; - size_t remaining = count; - - int ret_val; - int i; - - if (count >= sizeof(kbuf)) - return -EINVAL; - if (copy_from_user(kbuf, buf, count)) - return -EFAULT; - curr_pos = kbuf; - kbuf[count] = '\0'; /* Just to make sure... */ - - if (strncmp(curr_pos, "lock ", 5) == 0) { - curr_pos += 5; - remaining -= 5; - - pr_debug("client 0x%p called 'lock'\n", priv); - - if (!vga_str_to_iostate(curr_pos, remaining, &io_state)) { - ret_val = -EPROTO; - goto done; - } - if (io_state == VGA_RSRC_NONE) { - ret_val = -EPROTO; - goto done; - } - - pdev = priv->target; - if (priv->target == NULL) { - ret_val = -ENODEV; - goto done; - } - - vga_get_uninterruptible(pdev, io_state); - - /* Update the client's locks lists... */ - for (i = 0; i < MAX_USER_CARDS; i++) { - if (priv->cards[i].pdev == pdev) { - if (io_state & VGA_RSRC_LEGACY_IO) - priv->cards[i].io_cnt++; - if (io_state & VGA_RSRC_LEGACY_MEM) - priv->cards[i].mem_cnt++; - break; - } - } - - ret_val = count; - goto done; - } else if (strncmp(curr_pos, "unlock ", 7) == 0) { - curr_pos += 7; - remaining -= 7; - - pr_debug("client 0x%p called 'unlock'\n", priv); - - if (strncmp(curr_pos, "all", 3) == 0) - io_state = VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM; - else { - if (!vga_str_to_iostate - (curr_pos, remaining, &io_state)) { - ret_val = -EPROTO; - goto done; - } - /* TODO: Add this? - if (io_state == VGA_RSRC_NONE) { - ret_val = -EPROTO; - goto done; - } - */ - } - - pdev = priv->target; - if (priv->target == NULL) { - ret_val = -ENODEV; - goto done; - } - for (i = 0; i < MAX_USER_CARDS; i++) { - if (priv->cards[i].pdev == pdev) - uc = &priv->cards[i]; - } - - if (!uc) { - ret_val = -EINVAL; - goto done; - } - - if (io_state & VGA_RSRC_LEGACY_IO && uc->io_cnt == 0) { - ret_val = -EINVAL; - goto done; - } - - if (io_state & VGA_RSRC_LEGACY_MEM && uc->mem_cnt == 0) { - ret_val = -EINVAL; - goto done; - } - - vga_put(pdev, io_state); - - if (io_state & VGA_RSRC_LEGACY_IO) - uc->io_cnt--; - if (io_state & VGA_RSRC_LEGACY_MEM) - uc->mem_cnt--; - - ret_val = count; - goto done; - } else if (strncmp(curr_pos, "trylock ", 8) == 0) { - curr_pos += 8; - remaining -= 8; - - pr_debug("client 0x%p called 'trylock'\n", priv); - - if (!vga_str_to_iostate(curr_pos, remaining, &io_state)) { - ret_val = -EPROTO; - goto done; - } - /* TODO: Add this? - if (io_state == VGA_RSRC_NONE) { - ret_val = -EPROTO; - goto done; - } - */ - - pdev = priv->target; - if (priv->target == NULL) { - ret_val = -ENODEV; - goto done; - } - - if (vga_tryget(pdev, io_state)) { - /* Update the client's locks lists... */ - for (i = 0; i < MAX_USER_CARDS; i++) { - if (priv->cards[i].pdev == pdev) { - if (io_state & VGA_RSRC_LEGACY_IO) - priv->cards[i].io_cnt++; - if (io_state & VGA_RSRC_LEGACY_MEM) - priv->cards[i].mem_cnt++; - break; - } - } - ret_val = count; - goto done; - } else { - ret_val = -EBUSY; - goto done; - } - - } else if (strncmp(curr_pos, "target ", 7) == 0) { - unsigned int domain, bus, devfn; - struct vga_device *vgadev; - - curr_pos += 7; - remaining -= 7; - pr_debug("client 0x%p called 'target'\n", priv); - /* if target is default */ - if (!strncmp(curr_pos, "default", 7)) - pdev = pci_dev_get(vga_default_device()); - else { - if (!vga_pci_str_to_vars(curr_pos, remaining, - &domain, &bus, &devfn)) { - ret_val = -EPROTO; - goto done; - } - pdev = pci_get_domain_bus_and_slot(domain, bus, devfn); - if (!pdev) { - pr_debug("invalid PCI address %04x:%02x:%02x.%x\n", - domain, bus, PCI_SLOT(devfn), - PCI_FUNC(devfn)); - ret_val = -ENODEV; - goto done; - } - - pr_debug("%s ==> %04x:%02x:%02x.%x pdev %p\n", curr_pos, - domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), - pdev); - } - - vgadev = vgadev_find(pdev); - pr_debug("vgadev %p\n", vgadev); - if (vgadev == NULL) { - if (pdev) { - vgaarb_dbg(&pdev->dev, "not a VGA device\n"); - pci_dev_put(pdev); - } - - ret_val = -ENODEV; - goto done; - } - - priv->target = pdev; - for (i = 0; i < MAX_USER_CARDS; i++) { - if (priv->cards[i].pdev == pdev) - break; - if (priv->cards[i].pdev == NULL) { - priv->cards[i].pdev = pdev; - priv->cards[i].io_cnt = 0; - priv->cards[i].mem_cnt = 0; - break; - } - } - if (i == MAX_USER_CARDS) { - vgaarb_dbg(&pdev->dev, "maximum user cards (%d) number reached, ignoring this one!\n", - MAX_USER_CARDS); - pci_dev_put(pdev); - /* XXX: which value to return? */ - ret_val = -ENOMEM; - goto done; - } - - ret_val = count; - pci_dev_put(pdev); - goto done; - - - } else if (strncmp(curr_pos, "decodes ", 8) == 0) { - curr_pos += 8; - remaining -= 8; - pr_debug("client 0x%p called 'decodes'\n", priv); - - if (!vga_str_to_iostate(curr_pos, remaining, &io_state)) { - ret_val = -EPROTO; - goto done; - } - pdev = priv->target; - if (priv->target == NULL) { - ret_val = -ENODEV; - goto done; - } - - __vga_set_legacy_decoding(pdev, io_state, true); - ret_val = count; - goto done; - } - /* If we got here, the message written is not part of the protocol! */ - return -EPROTO; - -done: - return ret_val; -} - -static __poll_t vga_arb_fpoll(struct file *file, poll_table *wait) -{ - pr_debug("%s\n", __func__); - - poll_wait(file, &vga_wait_queue, wait); - return EPOLLIN; -} - -static int vga_arb_open(struct inode *inode, struct file *file) -{ - struct vga_arb_private *priv; - unsigned long flags; - - pr_debug("%s\n", __func__); - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (priv == NULL) - return -ENOMEM; - spin_lock_init(&priv->lock); - file->private_data = priv; - - spin_lock_irqsave(&vga_user_lock, flags); - list_add(&priv->list, &vga_user_list); - spin_unlock_irqrestore(&vga_user_lock, flags); - - /* Set the client' lists of locks */ - priv->target = vga_default_device(); /* Maybe this is still null! */ - priv->cards[0].pdev = priv->target; - priv->cards[0].io_cnt = 0; - priv->cards[0].mem_cnt = 0; - - - return 0; -} - -static int vga_arb_release(struct inode *inode, struct file *file) -{ - struct vga_arb_private *priv = file->private_data; - struct vga_arb_user_card *uc; - unsigned long flags; - int i; - - pr_debug("%s\n", __func__); - - spin_lock_irqsave(&vga_user_lock, flags); - list_del(&priv->list); - for (i = 0; i < MAX_USER_CARDS; i++) { - uc = &priv->cards[i]; - if (uc->pdev == NULL) - continue; - vgaarb_dbg(&uc->pdev->dev, "uc->io_cnt == %d, uc->mem_cnt == %d\n", - uc->io_cnt, uc->mem_cnt); - while (uc->io_cnt--) - vga_put(uc->pdev, VGA_RSRC_LEGACY_IO); - while (uc->mem_cnt--) - vga_put(uc->pdev, VGA_RSRC_LEGACY_MEM); - } - spin_unlock_irqrestore(&vga_user_lock, flags); - - kfree(priv); - - return 0; -} - -static void vga_arb_device_card_gone(struct pci_dev *pdev) -{ -} - -/* - * callback any registered clients to let them know we have a - * change in VGA cards - */ -static void vga_arbiter_notify_clients(void) -{ - struct vga_device *vgadev; - unsigned long flags; - uint32_t new_decodes; - bool new_state; - - if (!vga_arbiter_used) - return; - - spin_lock_irqsave(&vga_lock, flags); - list_for_each_entry(vgadev, &vga_list, list) { - if (vga_count > 1) - new_state = false; - else - new_state = true; - if (vgadev->set_decode) { - new_decodes = vgadev->set_decode(vgadev->pdev, - new_state); - vga_update_device_decodes(vgadev, new_decodes); - } - } - spin_unlock_irqrestore(&vga_lock, flags); -} - -static int pci_notify(struct notifier_block *nb, unsigned long action, - void *data) -{ - struct device *dev = data; - struct pci_dev *pdev = to_pci_dev(dev); - bool notify = false; - - vgaarb_dbg(dev, "%s\n", __func__); - - /* For now we're only intereted in devices added and removed. I didn't - * test this thing here, so someone needs to double check for the - * cases of hotplugable vga cards. */ - if (action == BUS_NOTIFY_ADD_DEVICE) - notify = vga_arbiter_add_pci_device(pdev); - else if (action == BUS_NOTIFY_DEL_DEVICE) - notify = vga_arbiter_del_pci_device(pdev); - - if (notify) - vga_arbiter_notify_clients(); - return 0; -} - -static struct notifier_block pci_notifier = { - .notifier_call = pci_notify, -}; - -static const struct file_operations vga_arb_device_fops = { - .read = vga_arb_read, - .write = vga_arb_write, - .poll = vga_arb_fpoll, - .open = vga_arb_open, - .release = vga_arb_release, - .llseek = noop_llseek, -}; - -static struct miscdevice vga_arb_device = { - MISC_DYNAMIC_MINOR, "vga_arbiter", &vga_arb_device_fops -}; - -#if defined(CONFIG_ACPI) -static bool vga_arb_integrated_gpu(struct device *dev) -{ - struct acpi_device *adev = ACPI_COMPANION(dev); - - return adev && !strcmp(acpi_device_hid(adev), ACPI_VIDEO_HID); -} -#else -static bool vga_arb_integrated_gpu(struct device *dev) -{ - return false; -} -#endif - -static void __init vga_arb_select_default_device(void) -{ - struct pci_dev *pdev, *found = NULL; - struct vga_device *vgadev; - -#if defined(CONFIG_X86) || defined(CONFIG_IA64) - u64 base = screen_info.lfb_base; - u64 size = screen_info.lfb_size; - u64 limit; - resource_size_t start, end; - unsigned long flags; - int i; - - if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE) - base |= (u64)screen_info.ext_lfb_base << 32; - - limit = base + size; - - list_for_each_entry(vgadev, &vga_list, list) { - struct device *dev = &vgadev->pdev->dev; - /* - * Override vga_arbiter_add_pci_device()'s I/O based detection - * as it may take the wrong device (e.g. on Apple system under - * EFI). - * - * Select the device owning the boot framebuffer if there is - * one. - */ - - /* Does firmware framebuffer belong to us? */ - for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { - flags = pci_resource_flags(vgadev->pdev, i); - - if ((flags & IORESOURCE_MEM) == 0) - continue; - - start = pci_resource_start(vgadev->pdev, i); - end = pci_resource_end(vgadev->pdev, i); - - if (!start || !end) - continue; - - if (base < start || limit >= end) - continue; - - if (!vga_default_device()) - vgaarb_info(dev, "setting as boot device\n"); - else if (vgadev->pdev != vga_default_device()) - vgaarb_info(dev, "overriding boot device\n"); - vga_set_default_device(vgadev->pdev); - } - } -#endif - - if (!vga_default_device()) { - list_for_each_entry_reverse(vgadev, &vga_list, list) { - struct device *dev = &vgadev->pdev->dev; - u16 cmd; - - pdev = vgadev->pdev; - pci_read_config_word(pdev, PCI_COMMAND, &cmd); - if (cmd & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { - found = pdev; - if (vga_arb_integrated_gpu(dev)) - break; - } - } - } - - if (found) { - vgaarb_info(&found->dev, "setting as boot device (VGA legacy resources not available)\n"); - vga_set_default_device(found); - return; - } - - if (!vga_default_device()) { - vgadev = list_first_entry_or_null(&vga_list, - struct vga_device, list); - if (vgadev) { - struct device *dev = &vgadev->pdev->dev; - vgaarb_info(dev, "setting as boot device (VGA legacy resources not available)\n"); - vga_set_default_device(vgadev->pdev); - } - } -} - -static int __init vga_arb_device_init(void) -{ - int rc; - struct pci_dev *pdev; - struct vga_device *vgadev; - - rc = misc_register(&vga_arb_device); - if (rc < 0) - pr_err("error %d registering device\n", rc); - - bus_register_notifier(&pci_bus_type, &pci_notifier); - - /* We add all PCI devices satisfying VGA class in the arbiter by - * default */ - pdev = NULL; - while ((pdev = - pci_get_subsys(PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, - PCI_ANY_ID, pdev)) != NULL) - vga_arbiter_add_pci_device(pdev); - - list_for_each_entry(vgadev, &vga_list, list) { - struct device *dev = &vgadev->pdev->dev; - - if (vgadev->bridge_has_one_vga) - vgaarb_info(dev, "bridge control possible\n"); - else - vgaarb_info(dev, "no bridge control possible\n"); - } - - vga_arb_select_default_device(); - - pr_info("loaded\n"); - return rc; -} -subsys_initcall(vga_arb_device_init); |