Merge tag 'drm-fixes-2019-08-30' of git://anongit.freedesktop.org/drm/drm
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 30 Aug 2019 15:21:24 +0000 (08:21 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 30 Aug 2019 15:21:24 +0000 (08:21 -0700)
Pull drm fixes from Dave Airlie:
 "Nothing too crazy, there's probably more patches than I'd like at this
  stage, but they are all pretty self contained:

  amdgpu:
   - Fix GFXOFF regression for PCO and RV2
   - Fix missing fence reference
   - Fix VG20 power readings on certain SMU firmware versions
   - Fix dpm level setup for VG20
   - Add an ATPX laptop quirk

  i915:
   - Fix DP MST max BPC property creation after DRM register
   - Fix unused ggtt deballooning and NULL dereference in guest
   - Fix DSC eDP transcoder identification
   - Fix WARN from DMA API debug by setting DMA max segment size

  qxl:
   - Make qxl reservel the vga ports using vgaargb to prevent switching to vga compatibility mode.

  omap:
   - Fix omap port lookup for SDI output

  virtio:
   - Use virtio_max_dma_size to fix an issue with swiotlb.

  komeda:
   - Compiler fixes to komeda.
   - Add missing of_node_get() call in komeda.
   - Reorder the komeda de-init functions"

* tag 'drm-fixes-2019-08-30' of git://anongit.freedesktop.org/drm/drm:
  drm/komeda: Reordered the komeda's de-init functions
  drm/amdgpu: fix GFXOFF on Picasso and Raven2
  drm/amdgpu: Add APTX quirk for Dell Latitude 5495
  drm/amd/powerplay: correct Vega20 dpm level related settings
  drm/i915: Call dma_set_max_seg_size() in i915_driver_hw_probe()
  drm/i915/dp: Fix DSC enable code to use cpu_transcoder instead of encoder->type
  drm/i915: Don't deballoon unused ggtt drm_mm_node in linux guest
  drm/i915: Do not create a new max_bpc prop for MST connectors
  drm/powerplay: Fix Vega20 power reading again
  drm/powerplay: Fix Vega20 Average Power value v4
  drm/amdgpu: fix dma_fence_wait without reference
  drm/komeda: Add missing of_node_get() call
  drm/komeda: Clean warning 'komeda_component_add' might be a candidate for 'gnu_printf'
  drm/komeda: Fix warning -Wunused-but-set-variable
  drm/komeda: Fix error: not allocating enough data 1592 vs 1584
  drm/virtio: use virtio_max_dma_size
  drm/omap: Fix port lookup for SDI output
  drm/qxl: get vga ioports

16 files changed:
drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
drivers/gpu/drm/amd/powerplay/vega20_ppt.c
drivers/gpu/drm/arm/display/komeda/komeda_dev.c
drivers/gpu/drm/arm/display/komeda/komeda_kms.c
drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c
drivers/gpu/drm/i915/display/intel_dp_mst.c
drivers/gpu/drm/i915/display/intel_vdsc.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_vgpu.c
drivers/gpu/drm/omapdrm/dss/output.c
drivers/gpu/drm/qxl/qxl_drv.c
drivers/gpu/drm/virtio/virtgpu_object.c

index 9b384a94d2f34b608108f5b971d0475781787ffa..3e35a8f2c5e553e4c714deff5e838ac1510a2f59 100644 (file)
@@ -574,6 +574,7 @@ static const struct amdgpu_px_quirk amdgpu_px_quirk_list[] = {
        { 0x1002, 0x6900, 0x1002, 0x0124, AMDGPU_PX_QUIRK_FORCE_ATPX },
        { 0x1002, 0x6900, 0x1028, 0x0812, AMDGPU_PX_QUIRK_FORCE_ATPX },
        { 0x1002, 0x6900, 0x1028, 0x0813, AMDGPU_PX_QUIRK_FORCE_ATPX },
+       { 0x1002, 0x699f, 0x1028, 0x0814, AMDGPU_PX_QUIRK_FORCE_ATPX },
        { 0x1002, 0x6900, 0x1025, 0x125A, AMDGPU_PX_QUIRK_FORCE_ATPX },
        { 0x1002, 0x6900, 0x17AA, 0x3806, AMDGPU_PX_QUIRK_FORCE_ATPX },
        { 0, 0, 0, 0, 0 },
index f539a2a927747add782a608796775299128bd184..7398b4850649bd64c45061c10df4f6faec68d31e 100644 (file)
@@ -534,21 +534,24 @@ int amdgpu_ctx_wait_prev_fence(struct amdgpu_ctx *ctx,
                               struct drm_sched_entity *entity)
 {
        struct amdgpu_ctx_entity *centity = to_amdgpu_ctx_entity(entity);
-       unsigned idx = centity->sequence & (amdgpu_sched_jobs - 1);
-       struct dma_fence *other = centity->fences[idx];
+       struct dma_fence *other;
+       unsigned idx;
+       long r;
 
-       if (other) {
-               signed long r;
-               r = dma_fence_wait(other, true);
-               if (r < 0) {
-                       if (r != -ERESTARTSYS)
-                               DRM_ERROR("Error (%ld) waiting for fence!\n", r);
+       spin_lock(&ctx->ring_lock);
+       idx = centity->sequence & (amdgpu_sched_jobs - 1);
+       other = dma_fence_get(centity->fences[idx]);
+       spin_unlock(&ctx->ring_lock);
 
-                       return r;
-               }
-       }
+       if (!other)
+               return 0;
 
-       return 0;
+       r = dma_fence_wait(other, true);
+       if (r < 0 && r != -ERESTARTSYS)
+               DRM_ERROR("Error (%ld) waiting for fence!\n", r);
+
+       dma_fence_put(other);
+       return r;
 }
 
 void amdgpu_ctx_mgr_init(struct amdgpu_ctx_mgr *mgr)
index 4ea67f94cae2417ad0269e187fe7809ca3b200bf..c066e1d3f981da65d7d19f2c9615a121c1aa19f0 100644 (file)
@@ -596,14 +596,14 @@ static void gfx_v9_0_check_if_need_gfxoff(struct amdgpu_device *adev)
        case CHIP_VEGA20:
                break;
        case CHIP_RAVEN:
-               if (adev->rev_id >= 0x8 || adev->pdev->device == 0x15d8)
-                       break;
-               if ((adev->gfx.rlc_fw_version != 106 &&
-                    adev->gfx.rlc_fw_version < 531) ||
-                   (adev->gfx.rlc_fw_version == 53815) ||
-                   (adev->gfx.rlc_feature_version < 1) ||
-                   !adev->gfx.rlc.is_rlc_v2_1)
+               if (!(adev->rev_id >= 0x8 || adev->pdev->device == 0x15d8)
+                       &&((adev->gfx.rlc_fw_version != 106 &&
+                            adev->gfx.rlc_fw_version < 531) ||
+                           (adev->gfx.rlc_fw_version == 53815) ||
+                           (adev->gfx.rlc_feature_version < 1) ||
+                           !adev->gfx.rlc.is_rlc_v2_1))
                        adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
+
                if (adev->pm.pp_feature & PP_GFXOFF_MASK)
                        adev->pg_flags |= AMD_PG_SUPPORT_GFX_PG |
                                AMD_PG_SUPPORT_CP |
index f27c6fbb192ed20133982db6df494893939f482a..90c4e87ac5ada9b09acc99d934df065e04a949d1 100644 (file)
@@ -2101,7 +2101,11 @@ static int vega20_get_gpu_power(struct pp_hwmgr *hwmgr,
        if (ret)
                return ret;
 
-       *query = metrics_table.CurrSocketPower << 8;
+       /* For the 40.46 release, they changed the value name */
+       if (hwmgr->smu_version == 0x282e00)
+               *query = metrics_table.AverageSocketPower << 8;
+       else
+               *query = metrics_table.CurrSocketPower << 8;
 
        return ret;
 }
@@ -2349,12 +2353,16 @@ static int vega20_force_dpm_highest(struct pp_hwmgr *hwmgr)
                data->dpm_table.soc_table.dpm_state.soft_max_level =
                data->dpm_table.soc_table.dpm_levels[soft_level].value;
 
-       ret = vega20_upload_dpm_min_level(hwmgr, 0xFFFFFFFF);
+       ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
+                                                FEATURE_DPM_UCLK_MASK |
+                                                FEATURE_DPM_SOCCLK_MASK);
        PP_ASSERT_WITH_CODE(!ret,
                        "Failed to upload boot level to highest!",
                        return ret);
 
-       ret = vega20_upload_dpm_max_level(hwmgr, 0xFFFFFFFF);
+       ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
+                                                FEATURE_DPM_UCLK_MASK |
+                                                FEATURE_DPM_SOCCLK_MASK);
        PP_ASSERT_WITH_CODE(!ret,
                        "Failed to upload dpm max level to highest!",
                        return ret);
@@ -2387,12 +2395,16 @@ static int vega20_force_dpm_lowest(struct pp_hwmgr *hwmgr)
                data->dpm_table.soc_table.dpm_state.soft_max_level =
                data->dpm_table.soc_table.dpm_levels[soft_level].value;
 
-       ret = vega20_upload_dpm_min_level(hwmgr, 0xFFFFFFFF);
+       ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
+                                                FEATURE_DPM_UCLK_MASK |
+                                                FEATURE_DPM_SOCCLK_MASK);
        PP_ASSERT_WITH_CODE(!ret,
                        "Failed to upload boot level to highest!",
                        return ret);
 
-       ret = vega20_upload_dpm_max_level(hwmgr, 0xFFFFFFFF);
+       ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
+                                                FEATURE_DPM_UCLK_MASK |
+                                                FEATURE_DPM_SOCCLK_MASK);
        PP_ASSERT_WITH_CODE(!ret,
                        "Failed to upload dpm max level to highest!",
                        return ret);
@@ -2403,14 +2415,54 @@ static int vega20_force_dpm_lowest(struct pp_hwmgr *hwmgr)
 
 static int vega20_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
 {
+       struct vega20_hwmgr *data =
+                       (struct vega20_hwmgr *)(hwmgr->backend);
+       uint32_t soft_min_level, soft_max_level;
        int ret = 0;
 
-       ret = vega20_upload_dpm_min_level(hwmgr, 0xFFFFFFFF);
+       /* gfxclk soft min/max settings */
+       soft_min_level =
+               vega20_find_lowest_dpm_level(&(data->dpm_table.gfx_table));
+       soft_max_level =
+               vega20_find_highest_dpm_level(&(data->dpm_table.gfx_table));
+
+       data->dpm_table.gfx_table.dpm_state.soft_min_level =
+               data->dpm_table.gfx_table.dpm_levels[soft_min_level].value;
+       data->dpm_table.gfx_table.dpm_state.soft_max_level =
+               data->dpm_table.gfx_table.dpm_levels[soft_max_level].value;
+
+       /* uclk soft min/max settings */
+       soft_min_level =
+               vega20_find_lowest_dpm_level(&(data->dpm_table.mem_table));
+       soft_max_level =
+               vega20_find_highest_dpm_level(&(data->dpm_table.mem_table));
+
+       data->dpm_table.mem_table.dpm_state.soft_min_level =
+               data->dpm_table.mem_table.dpm_levels[soft_min_level].value;
+       data->dpm_table.mem_table.dpm_state.soft_max_level =
+               data->dpm_table.mem_table.dpm_levels[soft_max_level].value;
+
+       /* socclk soft min/max settings */
+       soft_min_level =
+               vega20_find_lowest_dpm_level(&(data->dpm_table.soc_table));
+       soft_max_level =
+               vega20_find_highest_dpm_level(&(data->dpm_table.soc_table));
+
+       data->dpm_table.soc_table.dpm_state.soft_min_level =
+               data->dpm_table.soc_table.dpm_levels[soft_min_level].value;
+       data->dpm_table.soc_table.dpm_state.soft_max_level =
+               data->dpm_table.soc_table.dpm_levels[soft_max_level].value;
+
+       ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
+                                                FEATURE_DPM_UCLK_MASK |
+                                                FEATURE_DPM_SOCCLK_MASK);
        PP_ASSERT_WITH_CODE(!ret,
                        "Failed to upload DPM Bootup Levels!",
                        return ret);
 
-       ret = vega20_upload_dpm_max_level(hwmgr, 0xFFFFFFFF);
+       ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
+                                                FEATURE_DPM_UCLK_MASK |
+                                                FEATURE_DPM_SOCCLK_MASK);
        PP_ASSERT_WITH_CODE(!ret,
                        "Failed to upload DPM Max Levels!",
                        return ret);
index dd6fd1c8bf24e0db3a4d16be0f7817dade68dde5..6a14497257e43b8bc906f42b5d0c68fccdc93e1b 100644 (file)
@@ -3050,6 +3050,7 @@ static int vega20_get_fan_speed_percent(struct smu_context *smu,
 
 static int vega20_get_gpu_power(struct smu_context *smu, uint32_t *value)
 {
+       uint32_t smu_version;
        int ret = 0;
        SmuMetrics_t metrics;
 
@@ -3060,7 +3061,15 @@ static int vega20_get_gpu_power(struct smu_context *smu, uint32_t *value)
        if (ret)
                return ret;
 
-       *value = metrics.CurrSocketPower << 8;
+       ret = smu_get_smc_version(smu, NULL, &smu_version);
+       if (ret)
+               return ret;
+
+       /* For the 40.46 release, they changed the value name */
+       if (smu_version == 0x282e00)
+               *value = metrics.AverageSocketPower << 8;
+       else
+               *value = metrics.CurrSocketPower << 8;
 
        return 0;
 }
index a0eabc134dd6943f482302470caac50778ae07e3..9d4d5075cc647ef6686afba1cac57539bd64e7a6 100644 (file)
@@ -127,7 +127,7 @@ static int komeda_parse_pipe_dt(struct komeda_dev *mdev, struct device_node *np)
        pipe->of_output_port =
                of_graph_get_port_by_id(np, KOMEDA_OF_PORT_OUTPUT);
 
-       pipe->of_node = np;
+       pipe->of_node = of_node_get(np);
 
        return 0;
 }
index d50e75f0b2bdce5c5bdf3daa6dcfcdff2f5e0c2a..69d9e26c60c812769164996f68aa299127371053 100644 (file)
@@ -14,8 +14,8 @@
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_irq.h>
-#include <drm/drm_vblank.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
 
 #include "komeda_dev.h"
 #include "komeda_framebuffer.h"
@@ -147,7 +147,6 @@ static int komeda_crtc_normalize_zpos(struct drm_crtc *crtc,
        struct komeda_crtc_state *kcrtc_st = to_kcrtc_st(crtc_st);
        struct komeda_plane_state *kplane_st;
        struct drm_plane_state *plane_st;
-       struct drm_framebuffer *fb;
        struct drm_plane *plane;
        struct list_head zorder_list;
        int order = 0, err;
@@ -173,7 +172,6 @@ static int komeda_crtc_normalize_zpos(struct drm_crtc *crtc,
 
        list_for_each_entry(kplane_st, &zorder_list, zlist_node) {
                plane_st = &kplane_st->base;
-               fb = plane_st->fb;
                plane = plane_st->plane;
 
                plane_st->normalized_zpos = order++;
@@ -206,7 +204,7 @@ static int komeda_kms_check(struct drm_device *dev,
                            struct drm_atomic_state *state)
 {
        struct drm_crtc *crtc;
-       struct drm_crtc_state *old_crtc_st, *new_crtc_st;
+       struct drm_crtc_state *new_crtc_st;
        int i, err;
 
        err = drm_atomic_helper_check_modeset(dev, state);
@@ -217,7 +215,7 @@ static int komeda_kms_check(struct drm_device *dev,
         * so need to add all affected_planes (even unchanged) to
         * drm_atomic_state.
         */
-       for_each_oldnew_crtc_in_state(state, crtc, old_crtc_st, new_crtc_st, i) {
+       for_each_new_crtc_in_state(state, crtc, new_crtc_st, i) {
                err = drm_atomic_add_affected_planes(state, crtc);
                if (err)
                        return err;
@@ -308,11 +306,11 @@ struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev)
                               komeda_kms_irq_handler, IRQF_SHARED,
                               drm->driver->name, drm);
        if (err)
-               goto cleanup_mode_config;
+               goto free_component_binding;
 
        err = mdev->funcs->enable_irq(mdev);
        if (err)
-               goto cleanup_mode_config;
+               goto free_component_binding;
 
        drm->irq_enabled = true;
 
@@ -320,15 +318,21 @@ struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev)
 
        err = drm_dev_register(drm, 0);
        if (err)
-               goto cleanup_mode_config;
+               goto free_interrupts;
 
        return kms;
 
-cleanup_mode_config:
+free_interrupts:
        drm_kms_helper_poll_fini(drm);
        drm->irq_enabled = false;
+       mdev->funcs->disable_irq(mdev);
+free_component_binding:
+       component_unbind_all(mdev->dev, drm);
+cleanup_mode_config:
        drm_mode_config_cleanup(drm);
        komeda_kms_cleanup_private_objs(kms);
+       drm->dev_private = NULL;
+       drm_dev_put(drm);
 free_kms:
        kfree(kms);
        return ERR_PTR(err);
@@ -339,13 +343,14 @@ void komeda_kms_detach(struct komeda_kms_dev *kms)
        struct drm_device *drm = &kms->base;
        struct komeda_dev *mdev = drm->dev_private;
 
-       drm->irq_enabled = false;
-       mdev->funcs->disable_irq(mdev);
        drm_dev_unregister(drm);
        drm_kms_helper_poll_fini(drm);
+       drm_atomic_helper_shutdown(drm);
+       drm->irq_enabled = false;
+       mdev->funcs->disable_irq(mdev);
        component_unbind_all(mdev->dev, drm);
-       komeda_kms_cleanup_private_objs(kms);
        drm_mode_config_cleanup(drm);
+       komeda_kms_cleanup_private_objs(kms);
        drm->dev_private = NULL;
        drm_dev_put(drm);
 }
index a90bcbb3cb23d6fc71a76750d69da9c1324cb098..14b683164544d8c2ea7d8d272f6f5caadaa4427f 100644 (file)
@@ -480,6 +480,7 @@ void komeda_pipeline_dump_register(struct komeda_pipeline *pipe,
                                   struct seq_file *sf);
 
 /* component APIs */
+extern __printf(10, 11)
 struct komeda_component *
 komeda_component_add(struct komeda_pipeline *pipe,
                     size_t comp_sz, u32 id, u32 hw_id,
index 617e1f7b8472e874250bf5a951856df9fa6de36c..2851cac94d8699883dbaa9a4e9b8f202e33da0eb 100644 (file)
@@ -148,7 +148,7 @@ static int komeda_wb_connector_add(struct komeda_kms_dev *kms,
        if (!kcrtc->master->wb_layer)
                return 0;
 
-       kwb_conn = kzalloc(sizeof(*wb_conn), GFP_KERNEL);
+       kwb_conn = kzalloc(sizeof(*kwb_conn), GFP_KERNEL);
        if (!kwb_conn)
                return -ENOMEM;
 
index 60652ebbdf610a1cfda5228147265c77fe30f438..18e4cba767201cffbd550d0a0ea2d3245eaf5c43 100644 (file)
@@ -539,7 +539,15 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
 
        intel_attach_force_audio_property(connector);
        intel_attach_broadcast_rgb_property(connector);
-       drm_connector_attach_max_bpc_property(connector, 6, 12);
+
+       /*
+        * Reuse the prop from the SST connector because we're
+        * not allowed to create new props after device registration.
+        */
+       connector->max_bpc_property =
+               intel_dp->attached_connector->base.max_bpc_property;
+       if (connector->max_bpc_property)
+               drm_connector_attach_max_bpc_property(connector, 6, 12);
 
        return connector;
 
index ffec807b89600e6b3c63e4b222cc5f6cdcbe2317..f413904a3e960ffbc1895ee554846a024994761a 100644 (file)
@@ -541,7 +541,7 @@ static void intel_configure_pps_for_dsc_encoder(struct intel_encoder *encoder,
        pps_val |= DSC_PIC_HEIGHT(vdsc_cfg->pic_height) |
                DSC_PIC_WIDTH(vdsc_cfg->pic_width / num_vdsc_instances);
        DRM_INFO("PPS2 = 0x%08x\n", pps_val);
-       if (encoder->type == INTEL_OUTPUT_EDP) {
+       if (cpu_transcoder == TRANSCODER_EDP) {
                I915_WRITE(DSCA_PICTURE_PARAMETER_SET_2, pps_val);
                /*
                 * If 2 VDSC instances are needed, configure PPS for second
index f62e3397d9363e81185ace4663f14243b3e24855..bac1ee94f63fc0be121cb371cd9e38351494c322 100644 (file)
@@ -1598,6 +1598,12 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
 
        pci_set_master(pdev);
 
+       /*
+        * We don't have a max segment size, so set it to the max so sg's
+        * debugging layer doesn't complain
+        */
+       dma_set_max_seg_size(&pdev->dev, UINT_MAX);
+
        /* overlay on gen2 is broken and can't address above 1G */
        if (IS_GEN(dev_priv, 2)) {
                ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(30));
index 94d3992b599d24a88c473839e831ab81f903427b..724627afdedc2ef70430e2bee94518ad8c0e09c8 100644 (file)
@@ -101,6 +101,9 @@ static struct _balloon_info_ bl_info;
 static void vgt_deballoon_space(struct i915_ggtt *ggtt,
                                struct drm_mm_node *node)
 {
+       if (!drm_mm_node_allocated(node))
+               return;
+
        DRM_DEBUG_DRIVER("deballoon space: range [0x%llx - 0x%llx] %llu KiB.\n",
                         node->start,
                         node->start + node->size,
index de0f882f0f7b07d7b591df64b38f14c4d6a6fac0..14b41de44ebcda9a6c6ebda7de21817b22de2a90 100644 (file)
@@ -4,6 +4,7 @@
  * Author: Archit Taneja <archit@ti.com>
  */
 
+#include <linux/bitops.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -20,7 +21,8 @@ int omapdss_device_init_output(struct omap_dss_device *out)
 {
        struct device_node *remote_node;
 
-       remote_node = of_graph_get_remote_node(out->dev->of_node, 0, 0);
+       remote_node = of_graph_get_remote_node(out->dev->of_node,
+                                              ffs(out->of_ports) - 1, 0);
        if (!remote_node) {
                dev_dbg(out->dev, "failed to find video sink\n");
                return 0;
index f33e349c4ec5b4f48db8edd7b69d11f0e4a3c83a..952201c6d821d719f6520c83462923918ebf31f4 100644 (file)
@@ -59,6 +59,11 @@ module_param_named(num_heads, qxl_num_crtc, int, 0400);
 static struct drm_driver qxl_driver;
 static struct pci_driver qxl_pci_driver;
 
+static bool is_vga(struct pci_dev *pdev)
+{
+       return pdev->class == PCI_CLASS_DISPLAY_VGA << 8;
+}
+
 static int
 qxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
@@ -83,9 +88,17 @@ qxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (ret)
                goto disable_pci;
 
+       if (is_vga(pdev)) {
+               ret = vga_get_interruptible(pdev, VGA_RSRC_LEGACY_IO);
+               if (ret) {
+                       DRM_ERROR("can't get legacy vga ioports\n");
+                       goto disable_pci;
+               }
+       }
+
        ret = qxl_device_init(qdev, &qxl_driver, pdev);
        if (ret)
-               goto disable_pci;
+               goto put_vga;
 
        ret = qxl_modeset_init(qdev);
        if (ret)
@@ -105,6 +118,9 @@ modeset_cleanup:
        qxl_modeset_fini(qdev);
 unload:
        qxl_device_fini(qdev);
+put_vga:
+       if (is_vga(pdev))
+               vga_put(pdev, VGA_RSRC_LEGACY_IO);
 disable_pci:
        pci_disable_device(pdev);
 free_dev:
@@ -122,6 +138,8 @@ qxl_pci_remove(struct pci_dev *pdev)
 
        qxl_modeset_fini(qdev);
        qxl_device_fini(qdev);
+       if (is_vga(pdev))
+               vga_put(pdev, VGA_RSRC_LEGACY_IO);
 
        dev->dev_private = NULL;
        kfree(qdev);
index b2da31310d24c041750b92a96f91ddf8084978c7..09b526518f5a64b75288cc5738ae9ad7e6d0ff12 100644 (file)
@@ -204,6 +204,7 @@ int virtio_gpu_object_get_sg_table(struct virtio_gpu_device *qdev,
                .interruptible = false,
                .no_wait_gpu = false
        };
+       size_t max_segment;
 
        /* wtf swapping */
        if (bo->pages)
@@ -215,8 +216,13 @@ int virtio_gpu_object_get_sg_table(struct virtio_gpu_device *qdev,
        if (!bo->pages)
                goto out;
 
-       ret = sg_alloc_table_from_pages(bo->pages, pages, nr_pages, 0,
-                                       nr_pages << PAGE_SHIFT, GFP_KERNEL);
+       max_segment = virtio_max_dma_size(qdev->vdev);
+       max_segment &= PAGE_MASK;
+       if (max_segment > SCATTERLIST_MAX_SEGMENT)
+               max_segment = SCATTERLIST_MAX_SEGMENT;
+       ret = __sg_alloc_table_from_pages(bo->pages, pages, nr_pages, 0,
+                                         nr_pages << PAGE_SHIFT,
+                                         max_segment, GFP_KERNEL);
        if (ret)
                goto out;
        return 0;