diff options
Diffstat (limited to 'drivers/gpu/drm')
26 files changed, 355 insertions, 460 deletions
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511.h b/drivers/gpu/drm/bridge/adv7511/adv7511.h index ea271f62b214..ec0b7f3d889c 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511.h +++ b/drivers/gpu/drm/bridge/adv7511/adv7511.h @@ -401,7 +401,7 @@ struct adv7511 { #ifdef CONFIG_DRM_I2C_ADV7511_CEC int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511); -void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1); +int adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1); #else static inline int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511) { diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c b/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c index 44451a9658a3..2e9c88a2b5ed 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c @@ -119,7 +119,7 @@ static void adv7511_cec_rx(struct adv7511 *adv7511, int rx_buf) cec_received_msg(adv7511->cec_adap, &msg); } -void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1) +int adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1) { unsigned int offset = adv7511->info->reg_cec_offset; const u32 irq_tx_mask = ADV7511_INT1_CEC_TX_READY | @@ -131,16 +131,19 @@ void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1) unsigned int rx_status; int rx_order[3] = { -1, -1, -1 }; int i; + int irq_status = IRQ_NONE; - if (irq1 & irq_tx_mask) + if (irq1 & irq_tx_mask) { adv_cec_tx_raw_status(adv7511, irq1); + irq_status = IRQ_HANDLED; + } if (!(irq1 & irq_rx_mask)) - return; + return irq_status; if (regmap_read(adv7511->regmap_cec, ADV7511_REG_CEC_RX_STATUS + offset, &rx_status)) - return; + return irq_status; /* * ADV7511_REG_CEC_RX_STATUS[5:0] contains the reception order of RX @@ -172,6 +175,8 @@ void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1) adv7511_cec_rx(adv7511, rx_buf); } + + return IRQ_HANDLED; } static int adv7511_cec_adap_enable(struct cec_adapter *adap, bool enable) diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c index 3cd130965e9d..eb5919b38263 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c @@ -469,6 +469,8 @@ static int adv7511_irq_process(struct adv7511 *adv7511, bool process_hpd) { unsigned int irq0, irq1; int ret; + int cec_status = IRQ_NONE; + int irq_status = IRQ_NONE; ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(0), &irq0); if (ret < 0) @@ -478,29 +480,31 @@ static int adv7511_irq_process(struct adv7511 *adv7511, bool process_hpd) if (ret < 0) return ret; - /* If there is no IRQ to handle, exit indicating no IRQ data */ - if (!(irq0 & (ADV7511_INT0_HPD | ADV7511_INT0_EDID_READY)) && - !(irq1 & ADV7511_INT1_DDC_ERROR)) - return -ENODATA; - regmap_write(adv7511->regmap, ADV7511_REG_INT(0), irq0); regmap_write(adv7511->regmap, ADV7511_REG_INT(1), irq1); - if (process_hpd && irq0 & ADV7511_INT0_HPD && adv7511->bridge.encoder) + if (process_hpd && irq0 & ADV7511_INT0_HPD && adv7511->bridge.encoder) { schedule_work(&adv7511->hpd_work); + irq_status = IRQ_HANDLED; + } if (irq0 & ADV7511_INT0_EDID_READY || irq1 & ADV7511_INT1_DDC_ERROR) { adv7511->edid_read = true; if (adv7511->i2c_main->irq) wake_up_all(&adv7511->wq); + irq_status = IRQ_HANDLED; } #ifdef CONFIG_DRM_I2C_ADV7511_CEC - adv7511_cec_irq_process(adv7511, irq1); + cec_status = adv7511_cec_irq_process(adv7511, irq1); #endif - return 0; + /* If there is no IRQ to handle, exit indicating no IRQ data */ + if (irq_status == IRQ_HANDLED || cec_status == IRQ_HANDLED) + return IRQ_HANDLED; + + return IRQ_NONE; } static irqreturn_t adv7511_irq_handler(int irq, void *devid) @@ -509,7 +513,7 @@ static irqreturn_t adv7511_irq_handler(int irq, void *devid) int ret; ret = adv7511_irq_process(adv7511, true); - return ret < 0 ? IRQ_NONE : IRQ_HANDLED; + return ret < 0 ? IRQ_NONE : ret; } /* ----------------------------------------------------------------------------- diff --git a/drivers/gpu/drm/display/drm_dp_aux_bus.c b/drivers/gpu/drm/display/drm_dp_aux_bus.c index 5afc26be9d2a..d810529ebfb6 100644 --- a/drivers/gpu/drm/display/drm_dp_aux_bus.c +++ b/drivers/gpu/drm/display/drm_dp_aux_bus.c @@ -36,7 +36,7 @@ struct dp_aux_ep_device_with_data { * * Return: True if this driver matches this device; false otherwise. */ -static int dp_aux_ep_match(struct device *dev, struct device_driver *drv) +static int dp_aux_ep_match(struct device *dev, const struct device_driver *drv) { return !!of_match_device(drv->of_match_table, dev); } diff --git a/drivers/gpu/drm/drm_fbdev_ttm.c b/drivers/gpu/drm/drm_fbdev_ttm.c index bb7898cd7dc6..119ffb28aaf9 100644 --- a/drivers/gpu/drm/drm_fbdev_ttm.c +++ b/drivers/gpu/drm/drm_fbdev_ttm.c @@ -84,7 +84,8 @@ static int drm_fbdev_ttm_helper_fb_probe(struct drm_fb_helper *fb_helper, sizes->surface_width, sizes->surface_height, sizes->surface_bpp); - format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); + format = drm_driver_legacy_fb_format(dev, sizes->surface_bpp, + sizes->surface_depth); buffer = drm_client_framebuffer_create(client, sizes->surface_width, sizes->surface_height, format); if (IS_ERR(buffer)) diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index a471c46f5ca6..969cfd5a01ae 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -48,7 +48,7 @@ * subset of the MIPI DCS command set. */ -static int mipi_dsi_device_match(struct device *dev, struct device_driver *drv) +static int mipi_dsi_device_match(struct device *dev, const struct device_driver *drv) { struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev); diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c index 3d127127e7cb..3f84d7527793 100644 --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c @@ -420,13 +420,20 @@ static const struct dmi_system_id orientation_data[] = { DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Galaxy Book 10.6"), }, .driver_data = (void *)&lcd1280x1920_rightside_up, - }, { /* Valve Steam Deck */ + }, { /* Valve Steam Deck (Jupiter) */ .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Valve"), DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Jupiter"), DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "1"), }, .driver_data = (void *)&lcd800x1280_rightside_up, + }, { /* Valve Steam Deck (Galileo) */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Valve"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Galileo"), + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "1"), + }, + .driver_data = (void *)&lcd800x1280_rightside_up, }, { /* VIOS LTH17 */ .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "VIOS"), diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c index f08a6803dc18..3adc2c9ab72d 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c +++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c @@ -311,6 +311,9 @@ static int cdv_intel_lvds_get_modes(struct drm_connector *connector) if (mode_dev->panel_fixed_mode != NULL) { struct drm_display_mode *mode = drm_mode_duplicate(dev, mode_dev->panel_fixed_mode); + if (!mode) + return 0; + drm_mode_probed_add(connector, mode); return 1; } diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c index 8486de230ec9..8d1be94a443b 100644 --- a/drivers/gpu/drm/gma500/psb_intel_lvds.c +++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c @@ -504,6 +504,9 @@ static int psb_intel_lvds_get_modes(struct drm_connector *connector) if (mode_dev->panel_fixed_mode != NULL) { struct drm_display_mode *mode = drm_mode_duplicate(dev, mode_dev->panel_fixed_mode); + if (!mode) + return 0; + drm_mode_probed_add(connector, mode); return 1; } diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 090724fa766c..d54162ce0f99 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -340,7 +340,7 @@ static int eb_create(struct i915_execbuffer *eb) * Without a 1:1 association between relocation handles and * the execobject[] index, we instead create a hashtable. * We size it dynamically based on available memory, starting - * first with 1:1 assocative hash and scaling back until + * first with 1:1 associative hash and scaling back until * the allocation succeeds. * * Later on we use a positive lut_size to indicate we are diff --git a/drivers/gpu/drm/imagination/pvr_drv.c b/drivers/gpu/drm/imagination/pvr_drv.c index 5c3b2d58d766..1a0cb7aa9cea 100644 --- a/drivers/gpu/drm/imagination/pvr_drv.c +++ b/drivers/gpu/drm/imagination/pvr_drv.c @@ -1451,8 +1451,7 @@ err_context_fini: return err; } -static int -pvr_remove(struct platform_device *plat_dev) +static void pvr_remove(struct platform_device *plat_dev) { struct drm_device *drm_dev = platform_get_drvdata(plat_dev); struct pvr_device *pvr_dev = to_pvr_device(drm_dev); @@ -1469,8 +1468,6 @@ pvr_remove(struct platform_device *plat_dev) pvr_watchdog_fini(pvr_dev); pvr_queue_device_fini(pvr_dev); pvr_context_device_fini(pvr_dev); - - return 0; } static const struct of_device_id dt_match[] = { @@ -1485,7 +1482,7 @@ static const struct dev_pm_ops pvr_pm_ops = { static struct platform_driver pvr_driver = { .probe = pvr_probe, - .remove = pvr_remove, + .remove_new = pvr_remove, .driver = { .name = PVR_DRIVER_NAME, .pm = &pvr_pm_ops, diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c index 17a5cca007e2..4bd0baa2a4f5 100644 --- a/drivers/gpu/drm/meson/meson_drv.c +++ b/drivers/gpu/drm/meson/meson_drv.c @@ -250,29 +250,20 @@ static int meson_drv_bind_master(struct device *dev, bool has_components) if (ret) goto free_drm; ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_vd1_0); - if (ret) { - meson_canvas_free(priv->canvas, priv->canvas_id_osd1); - goto free_drm; - } + if (ret) + goto free_canvas_osd1; ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_vd1_1); - if (ret) { - meson_canvas_free(priv->canvas, priv->canvas_id_osd1); - meson_canvas_free(priv->canvas, priv->canvas_id_vd1_0); - goto free_drm; - } + if (ret) + goto free_canvas_vd1_0; ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_vd1_2); - if (ret) { - meson_canvas_free(priv->canvas, priv->canvas_id_osd1); - meson_canvas_free(priv->canvas, priv->canvas_id_vd1_0); - meson_canvas_free(priv->canvas, priv->canvas_id_vd1_1); - goto free_drm; - } + if (ret) + goto free_canvas_vd1_1; priv->vsync_irq = platform_get_irq(pdev, 0); ret = drm_vblank_init(drm, 1); if (ret) - goto free_drm; + goto free_canvas_vd1_2; /* Assign limits per soc revision/package */ for (i = 0 ; i < ARRAY_SIZE(meson_drm_soc_attrs) ; ++i) { @@ -288,11 +279,11 @@ static int meson_drv_bind_master(struct device *dev, bool has_components) */ ret = drm_aperture_remove_framebuffers(&meson_driver); if (ret) - goto free_drm; + goto free_canvas_vd1_2; ret = drmm_mode_config_init(drm); if (ret) - goto free_drm; + goto free_canvas_vd1_2; drm->mode_config.max_width = 3840; drm->mode_config.max_height = 2160; drm->mode_config.funcs = &meson_mode_config_funcs; @@ -307,7 +298,7 @@ static int meson_drv_bind_master(struct device *dev, bool has_components) if (priv->afbcd.ops) { ret = priv->afbcd.ops->init(priv); if (ret) - goto free_drm; + goto free_canvas_vd1_2; } /* Encoder Initialization */ @@ -371,6 +362,14 @@ uninstall_irq: exit_afbcd: if (priv->afbcd.ops) priv->afbcd.ops->exit(priv); +free_canvas_vd1_2: + meson_canvas_free(priv->canvas, priv->canvas_id_vd1_2); +free_canvas_vd1_1: + meson_canvas_free(priv->canvas, priv->canvas_id_vd1_1); +free_canvas_vd1_0: + meson_canvas_free(priv->canvas, priv->canvas_id_vd1_0); +free_canvas_osd1: + meson_canvas_free(priv->canvas, priv->canvas_id_osd1); free_drm: drm_dev_put(drm); diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c index d5512037c38b..2a94e82316f9 100644 --- a/drivers/gpu/drm/msm/msm_iommu.c +++ b/drivers/gpu/drm/msm/msm_iommu.c @@ -407,10 +407,13 @@ struct msm_mmu *msm_iommu_new(struct device *dev, unsigned long quirks) struct msm_iommu *iommu; int ret; - domain = iommu_domain_alloc(dev->bus); - if (!domain) + if (!device_iommu_mapped(dev)) return NULL; + domain = iommu_paging_domain_alloc(dev); + if (IS_ERR(domain)) + return ERR_CAST(domain); + iommu_set_pgtable_quirks(domain, quirks); iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 938832a6af15..b06aa473102b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -1001,6 +1001,9 @@ nouveau_connector_get_modes(struct drm_connector *connector) struct drm_display_mode *mode; mode = drm_mode_duplicate(dev, nv_connector->native_mode); + if (!mode) + return 0; + drm_mode_probed_add(connector, mode); ret = 1; } diff --git a/drivers/gpu/drm/panthor/panthor_drv.c b/drivers/gpu/drm/panthor/panthor_drv.c index b8a84f26b3ef..b5e7b919f241 100644 --- a/drivers/gpu/drm/panthor/panthor_drv.c +++ b/drivers/gpu/drm/panthor/panthor_drv.c @@ -86,15 +86,15 @@ panthor_get_uobj_array(const struct drm_panthor_obj_array *in, u32 min_stride, int ret = 0; void *out_alloc; + if (!in->count) + return NULL; + /* User stride must be at least the minimum object size, otherwise it might * lack useful information. */ if (in->stride < min_stride) return ERR_PTR(-EINVAL); - if (!in->count) - return NULL; - out_alloc = kvmalloc_array(in->count, obj_size, GFP_KERNEL); if (!out_alloc) return ERR_PTR(-ENOMEM); diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c index 42929e147107..463bcd3cf00f 100644 --- a/drivers/gpu/drm/panthor/panthor_sched.c +++ b/drivers/gpu/drm/panthor/panthor_sched.c @@ -459,6 +459,16 @@ struct panthor_queue { atomic64_t seqno; /** + * @last_fence: Fence of the last submitted job. + * + * We return this fence when we get an empty command stream. + * This way, we are guaranteed that all earlier jobs have completed + * when drm_sched_job::s_fence::finished without having to feed + * the CS ring buffer with a dummy job that only signals the fence. + */ + struct dma_fence *last_fence; + + /** * @in_flight_jobs: List containing all in-flight jobs. * * Used to keep track and signal panthor_job::done_fence when the @@ -829,6 +839,9 @@ static void group_free_queue(struct panthor_group *group, struct panthor_queue * panthor_kernel_bo_destroy(queue->ringbuf); panthor_kernel_bo_destroy(queue->iface.mem); + /* Release the last_fence we were holding, if any. */ + dma_fence_put(queue->fence_ctx.last_fence); + kfree(queue); } @@ -2784,9 +2797,6 @@ static void group_sync_upd_work(struct work_struct *work) spin_lock(&queue->fence_ctx.lock); list_for_each_entry_safe(job, job_tmp, &queue->fence_ctx.in_flight_jobs, node) { - if (!job->call_info.size) - continue; - if (syncobj->seqno < job->done_fence->seqno) break; @@ -2865,11 +2875,14 @@ queue_run_job(struct drm_sched_job *sched_job) static_assert(sizeof(call_instrs) % 64 == 0, "call_instrs is not aligned on a cacheline"); - /* Stream size is zero, nothing to do => return a NULL fence and let - * drm_sched signal the parent. + /* Stream size is zero, nothing to do except making sure all previously + * submitted jobs are done before we signal the + * drm_sched_job::s_fence::finished fence. */ - if (!job->call_info.size) - return NULL; + if (!job->call_info.size) { + job->done_fence = dma_fence_get(queue->fence_ctx.last_fence); + return dma_fence_get(job->done_fence); + } ret = pm_runtime_resume_and_get(ptdev->base.dev); if (drm_WARN_ON(&ptdev->base, ret)) @@ -2929,6 +2942,10 @@ queue_run_job(struct drm_sched_job *sched_job) panthor_devfreq_record_busy(sched->ptdev); } + /* Update the last fence. */ + dma_fence_put(queue->fence_ctx.last_fence); + queue->fence_ctx.last_fence = dma_fence_get(job->done_fence); + done_fence = dma_fence_get(job->done_fence); out_unlock: @@ -3379,10 +3396,15 @@ panthor_job_create(struct panthor_file *pfile, goto err_put_job; } - job->done_fence = kzalloc(sizeof(*job->done_fence), GFP_KERNEL); - if (!job->done_fence) { - ret = -ENOMEM; - goto err_put_job; + /* Empty command streams don't need a fence, they'll pick the one from + * the previously submitted job. + */ + if (job->call_info.size) { + job->done_fence = kzalloc(sizeof(*job->done_fence), GFP_KERNEL); + if (!job->done_fence) { + ret = -ENOMEM; + goto err_put_job; + } } ret = drm_sched_job_init(&job->base, diff --git a/drivers/gpu/drm/stm/lvds.c b/drivers/gpu/drm/stm/lvds.c index bfc8cb13fbc5..2fa2c81784e9 100644 --- a/drivers/gpu/drm/stm/lvds.c +++ b/drivers/gpu/drm/stm/lvds.c @@ -1186,15 +1186,13 @@ err_lvds_probe: return ret; } -static int lvds_remove(struct platform_device *pdev) +static void lvds_remove(struct platform_device *pdev) { struct stm_lvds *lvds = platform_get_drvdata(pdev); lvds_pixel_clk_unregister(lvds); drm_bridge_remove(&lvds->lvds_bridge); - - return 0; } static const struct of_device_id lvds_dt_ids[] = { diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 6396dece0db1..2427be8bc97f 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -346,6 +346,7 @@ static void ttm_bo_release(struct kref *kref) if (!dma_resv_test_signaled(bo->base.resv, DMA_RESV_USAGE_BOOKKEEP) || (want_init_on_free() && (bo->ttm != NULL)) || + bo->type == ttm_bo_type_sg || !dma_resv_trylock(bo->base.resv)) { /* The BO is not idle, resurrect it for delayed destroy */ ttm_bo_flush_all_fences(bo); diff --git a/drivers/gpu/drm/vboxvideo/vbox_main.c b/drivers/gpu/drm/vboxvideo/vbox_main.c index 42c2d8a99509..d4ade9325401 100644 --- a/drivers/gpu/drm/vboxvideo/vbox_main.c +++ b/drivers/gpu/drm/vboxvideo/vbox_main.c @@ -42,12 +42,11 @@ static int vbox_accel_init(struct vbox_private *vbox) /* Take a command buffer for each screen from the end of usable VRAM. */ vbox->available_vram_size -= vbox->num_crtcs * VBVA_MIN_BUFFER_SIZE; - vbox->vbva_buffers = pci_iomap_range(pdev, 0, - vbox->available_vram_size, - vbox->num_crtcs * - VBVA_MIN_BUFFER_SIZE); - if (!vbox->vbva_buffers) - return -ENOMEM; + vbox->vbva_buffers = pcim_iomap_range( + pdev, 0, vbox->available_vram_size, + vbox->num_crtcs * VBVA_MIN_BUFFER_SIZE); + if (IS_ERR(vbox->vbva_buffers)) + return PTR_ERR(vbox->vbva_buffers); for (i = 0; i < vbox->num_crtcs; ++i) { vbva_setup_buffer_context(&vbox->vbva_info[i], @@ -116,11 +115,10 @@ int vbox_hw_init(struct vbox_private *vbox) DRM_INFO("VRAM %08x\n", vbox->full_vram_size); /* Map guest-heap at end of vram */ - vbox->guest_heap = - pci_iomap_range(pdev, 0, GUEST_HEAP_OFFSET(vbox), - GUEST_HEAP_SIZE); - if (!vbox->guest_heap) - return -ENOMEM; + vbox->guest_heap = pcim_iomap_range(pdev, 0, + GUEST_HEAP_OFFSET(vbox), GUEST_HEAP_SIZE); + if (IS_ERR(vbox->guest_heap)) + return PTR_ERR(vbox->guest_heap); /* Create guest-heap mem-pool use 2^4 = 16 byte chunks */ vbox->guest_pool = devm_gen_pool_create(vbox->ddev.dev, 4, -1, diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c index 5a3b5aaed1f3..7dfb2006c561 100644 --- a/drivers/gpu/drm/virtio/virtgpu_kms.c +++ b/drivers/gpu/drm/virtio/virtgpu_kms.c @@ -116,11 +116,10 @@ static void virtio_gpu_get_capsets(struct virtio_gpu_device *vgdev, int virtio_gpu_init(struct virtio_device *vdev, struct drm_device *dev) { - static vq_callback_t *callbacks[] = { - virtio_gpu_ctrl_ack, virtio_gpu_cursor_ack + struct virtqueue_info vqs_info[] = { + { "control", virtio_gpu_ctrl_ack }, + { "cursor", virtio_gpu_cursor_ack }, }; - static const char * const names[] = { "control", "cursor" }; - struct virtio_gpu_device *vgdev; /* this will expand later */ struct virtqueue *vqs[2]; @@ -207,7 +206,7 @@ int virtio_gpu_init(struct virtio_device *vdev, struct drm_device *dev) DRM_INFO("features: %ccontext_init\n", vgdev->has_context_init ? '+' : '-'); - ret = virtio_find_vqs(vgdev->vdev, 2, vqs, callbacks, names, NULL); + ret = virtio_find_vqs(vgdev->vdev, 2, vqs, vqs_info, NULL); if (ret) { DRM_ERROR("failed to find virt queues\n"); goto err_vqs; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c index 2651fe0ef518..1f15990d3934 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c @@ -48,8 +48,6 @@ #define RETRIES 3 -#define VMW_HYPERVISOR_MAGIC 0x564D5868 - #define VMW_PORT_CMD_MSG 30 #define VMW_PORT_CMD_HB_MSG 0 #define VMW_PORT_CMD_OPEN_CHANNEL (MSG_TYPE_OPEN << 16 | VMW_PORT_CMD_MSG) @@ -104,20 +102,18 @@ static const char* const mksstat_kern_name_desc[MKSSTAT_KERN_COUNT][2] = */ static int vmw_open_channel(struct rpc_channel *channel, unsigned int protocol) { - unsigned long eax, ebx, ecx, edx, si = 0, di = 0; + u32 ecx, edx, esi, edi; - VMW_PORT(VMW_PORT_CMD_OPEN_CHANNEL, - (protocol | GUESTMSG_FLAG_COOKIE), si, di, - 0, - VMW_HYPERVISOR_MAGIC, - eax, ebx, ecx, edx, si, di); + vmware_hypercall6(VMW_PORT_CMD_OPEN_CHANNEL, + (protocol | GUESTMSG_FLAG_COOKIE), 0, + &ecx, &edx, &esi, &edi); if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) return -EINVAL; channel->channel_id = HIGH_WORD(edx); - channel->cookie_high = si; - channel->cookie_low = di; + channel->cookie_high = esi; + channel->cookie_low = edi; return 0; } @@ -133,17 +129,13 @@ static int vmw_open_channel(struct rpc_channel *channel, unsigned int protocol) */ static int vmw_close_channel(struct rpc_channel *channel) { - unsigned long eax, ebx, ecx, edx, si, di; - - /* Set up additional parameters */ - si = channel->cookie_high; - di = channel->cookie_low; + u32 ecx; - VMW_PORT(VMW_PORT_CMD_CLOSE_CHANNEL, - 0, si, di, - channel->channel_id << 16, - VMW_HYPERVISOR_MAGIC, - eax, ebx, ecx, edx, si, di); + vmware_hypercall5(VMW_PORT_CMD_CLOSE_CHANNEL, + 0, channel->channel_id << 16, + channel->cookie_high, + channel->cookie_low, + &ecx); if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) return -EINVAL; @@ -163,24 +155,18 @@ static int vmw_close_channel(struct rpc_channel *channel) static unsigned long vmw_port_hb_out(struct rpc_channel *channel, const char *msg, bool hb) { - unsigned long si, di, eax, ebx, ecx, edx; + u32 ebx, ecx; unsigned long msg_len = strlen(msg); /* HB port can't access encrypted memory. */ if (hb && !cc_platform_has(CC_ATTR_MEM_ENCRYPT)) { - unsigned long bp = channel->cookie_high; - u32 channel_id = (channel->channel_id << 16); - - si = (uintptr_t) msg; - di = channel->cookie_low; - - VMW_PORT_HB_OUT( + vmware_hypercall_hb_out( (MESSAGE_STATUS_SUCCESS << 16) | VMW_PORT_CMD_HB_MSG, - msg_len, si, di, - VMWARE_HYPERVISOR_HB | channel_id | - VMWARE_HYPERVISOR_OUT, - VMW_HYPERVISOR_MAGIC, bp, - eax, ebx, ecx, edx, si, di); + msg_len, + channel->channel_id << 16, + (uintptr_t) msg, channel->cookie_low, + channel->cookie_high, + &ebx); return ebx; } @@ -194,14 +180,13 @@ static unsigned long vmw_port_hb_out(struct rpc_channel *channel, memcpy(&word, msg, bytes); msg_len -= bytes; msg += bytes; - si = channel->cookie_high; - di = channel->cookie_low; - - VMW_PORT(VMW_PORT_CMD_MSG | (MSG_TYPE_SENDPAYLOAD << 16), - word, si, di, - channel->channel_id << 16, - VMW_HYPERVISOR_MAGIC, - eax, ebx, ecx, edx, si, di); + + vmware_hypercall5(VMW_PORT_CMD_MSG | + (MSG_TYPE_SENDPAYLOAD << 16), + word, channel->channel_id << 16, + channel->cookie_high, + channel->cookie_low, + &ecx); } return ecx; @@ -220,22 +205,17 @@ static unsigned long vmw_port_hb_out(struct rpc_channel *channel, static unsigned long vmw_port_hb_in(struct rpc_channel *channel, char *reply, unsigned long reply_len, bool hb) { - unsigned long si, di, eax, ebx, ecx, edx; + u32 ebx, ecx, edx; /* HB port can't access encrypted memory */ if (hb && !cc_platform_has(CC_ATTR_MEM_ENCRYPT)) { - unsigned long bp = channel->cookie_low; - u32 channel_id = (channel->channel_id << 16); - - si = channel->cookie_high; - di = (uintptr_t) reply; - - VMW_PORT_HB_IN( + vmware_hypercall_hb_in( (MESSAGE_STATUS_SUCCESS << 16) | VMW_PORT_CMD_HB_MSG, - reply_len, si, di, - VMWARE_HYPERVISOR_HB | channel_id, - VMW_HYPERVISOR_MAGIC, bp, - eax, ebx, ecx, edx, si, di); + reply_len, + channel->channel_id << 16, + channel->cookie_high, + (uintptr_t) reply, channel->cookie_low, + &ebx); return ebx; } @@ -245,14 +225,13 @@ static unsigned long vmw_port_hb_in(struct rpc_channel *channel, char *reply, while (reply_len) { unsigned int bytes = min_t(unsigned long, reply_len, 4); - si = channel->cookie_high; - di = channel->cookie_low; - - VMW_PORT(VMW_PORT_CMD_MSG | (MSG_TYPE_RECVPAYLOAD << 16), - MESSAGE_STATUS_SUCCESS, si, di, - channel->channel_id << 16, - VMW_HYPERVISOR_MAGIC, - eax, ebx, ecx, edx, si, di); + vmware_hypercall7(VMW_PORT_CMD_MSG | + (MSG_TYPE_RECVPAYLOAD << 16), + MESSAGE_STATUS_SUCCESS, + channel->channel_id << 16, + channel->cookie_high, + channel->cookie_low, + &ebx, &ecx, &edx); if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) break; @@ -276,22 +255,18 @@ static unsigned long vmw_port_hb_in(struct rpc_channel *channel, char *reply, */ static int vmw_send_msg(struct rpc_channel *channel, const char *msg) { - unsigned long eax, ebx, ecx, edx, si, di; + u32 ebx, ecx; size_t msg_len = strlen(msg); int retries = 0; while (retries < RETRIES) { retries++; - /* Set up additional parameters */ - si = channel->cookie_high; - di = channel->cookie_low; - - VMW_PORT(VMW_PORT_CMD_SENDSIZE, - msg_len, si, di, - channel->channel_id << 16, - VMW_HYPERVISOR_MAGIC, - eax, ebx, ecx, edx, si, di); + vmware_hypercall5(VMW_PORT_CMD_SENDSIZE, + msg_len, channel->channel_id << 16, + channel->cookie_high, + channel->cookie_low, + &ecx); if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) { /* Expected success. Give up. */ @@ -329,7 +304,7 @@ STACK_FRAME_NON_STANDARD(vmw_send_msg); static int vmw_recv_msg(struct rpc_channel *channel, void **msg, size_t *msg_len) { - unsigned long eax, ebx, ecx, edx, si, di; + u32 ebx, ecx, edx; char *reply; size_t reply_len; int retries = 0; @@ -341,15 +316,11 @@ static int vmw_recv_msg(struct rpc_channel *channel, void **msg, while (retries < RETRIES) { retries++; - /* Set up additional parameters */ - si = channel->cookie_high; - di = channel->cookie_low; - - VMW_PORT(VMW_PORT_CMD_RECVSIZE, - 0, si, di, - channel->channel_id << 16, - VMW_HYPERVISOR_MAGIC, - eax, ebx, ecx, edx, si, di); + vmware_hypercall7(VMW_PORT_CMD_RECVSIZE, + 0, channel->channel_id << 16, + channel->cookie_high, + channel->cookie_low, + &ebx, &ecx, &edx); if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) { DRM_ERROR("Failed to get reply size for host message.\n"); @@ -384,16 +355,12 @@ static int vmw_recv_msg(struct rpc_channel *channel, void **msg, reply[reply_len] = '\0'; - - /* Ack buffer */ - si = channel->cookie_high; - di = channel->cookie_low; - - VMW_PORT(VMW_PORT_CMD_RECVSTATUS, - MESSAGE_STATUS_SUCCESS, si, di, - channel->channel_id << 16, - VMW_HYPERVISOR_MAGIC, - eax, ebx, ecx, edx, si, di); + vmware_hypercall5(VMW_PORT_CMD_RECVSTATUS, + MESSAGE_STATUS_SUCCESS, + channel->channel_id << 16, + channel->cookie_high, + channel->cookie_low, + &ecx); if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) { kfree(reply); @@ -652,13 +619,7 @@ static inline void reset_ppn_array(PPN64 *arr, size_t size) */ static inline void hypervisor_ppn_reset_all(void) { - unsigned long eax, ebx, ecx, edx, si = 0, di = 0; - - VMW_PORT(VMW_PORT_CMD_MKSGS_RESET, - 0, si, di, - 0, - VMW_HYPERVISOR_MAGIC, - eax, ebx, ecx, edx, si, di); + vmware_hypercall1(VMW_PORT_CMD_MKSGS_RESET, 0); } /** @@ -669,13 +630,7 @@ static inline void hypervisor_ppn_reset_all(void) */ static inline void hypervisor_ppn_add(PPN64 pfn) { - unsigned long eax, ebx, ecx, edx, si = 0, di = 0; - - VMW_PORT(VMW_PORT_CMD_MKSGS_ADD_PPN, - (unsigned long)pfn, si, di, - 0, - VMW_HYPERVISOR_MAGIC, - eax, ebx, ecx, edx, si, di); + vmware_hypercall1(VMW_PORT_CMD_MKSGS_ADD_PPN, (unsigned long)pfn); } /** @@ -686,13 +641,7 @@ static inline void hypervisor_ppn_add(PPN64 pfn) */ static inline void hypervisor_ppn_remove(PPN64 pfn) { - unsigned long eax, ebx, ecx, edx, si = 0, di = 0; - - VMW_PORT(VMW_PORT_CMD_MKSGS_REMOVE_PPN, - (unsigned long)pfn, si, di, - 0, - VMW_HYPERVISOR_MAGIC, - eax, ebx, ecx, edx, si, di); + vmware_hypercall1(VMW_PORT_CMD_MKSGS_REMOVE_PPN, (unsigned long)pfn); } #if IS_ENABLED(CONFIG_DRM_VMWGFX_MKSSTATS) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_msg_arm64.h b/drivers/gpu/drm/vmwgfx/vmwgfx_msg_arm64.h index 4f40167ad61f..3c78e9338b54 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_msg_arm64.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_msg_arm64.h @@ -34,6 +34,8 @@ #define VMWARE_HYPERVISOR_HB BIT(0) #define VMWARE_HYPERVISOR_OUT BIT(1) +#define VMWARE_HYPERVISOR_MAGIC 0x564D5868 + #define X86_IO_MAGIC 0x86 #define X86_IO_W7_SIZE_SHIFT 0 @@ -45,86 +47,158 @@ #define X86_IO_W7_IMM_SHIFT 5 #define X86_IO_W7_IMM_MASK (0xff << X86_IO_W7_IMM_SHIFT) -static inline void vmw_port(unsigned long cmd, unsigned long in_ebx, - unsigned long in_si, unsigned long in_di, - unsigned long flags, unsigned long magic, - unsigned long *eax, unsigned long *ebx, - unsigned long *ecx, unsigned long *edx, - unsigned long *si, unsigned long *di) +static inline +unsigned long vmware_hypercall1(unsigned long cmd, unsigned long in1) { - register u64 x0 asm("x0") = magic; - register u64 x1 asm("x1") = in_ebx; + register u64 x0 asm("x0") = VMWARE_HYPERVISOR_MAGIC; + register u64 x1 asm("x1") = in1; register u64 x2 asm("x2") = cmd; - register u64 x3 asm("x3") = flags | VMWARE_HYPERVISOR_PORT; - register u64 x4 asm("x4") = in_si; - register u64 x5 asm("x5") = in_di; + register u64 x3 asm("x3") = VMWARE_HYPERVISOR_PORT; + register u64 x7 asm("x7") = ((u64)X86_IO_MAGIC << 32) | + X86_IO_W7_WITH | + X86_IO_W7_DIR | + (2 << X86_IO_W7_SIZE_SHIFT); + asm_inline volatile ( + "mrs xzr, mdccsr_el0; " + : "+r" (x0) + : "r" (x1), "r" (x2), "r" (x3), "r" (x7) + : "memory"); + + return x0; +} + +static inline +unsigned long vmware_hypercall5(unsigned long cmd, unsigned long in1, + unsigned long in3, unsigned long in4, + unsigned long in5, u32 *out2) +{ + register u64 x0 asm("x0") = VMWARE_HYPERVISOR_MAGIC; + register u64 x1 asm("x1") = in1; + register u64 x2 asm("x2") = cmd; + register u64 x3 asm("x3") = in3 | VMWARE_HYPERVISOR_PORT; + register u64 x4 asm("x4") = in4; + register u64 x5 asm("x5") = in5; register u64 x7 asm("x7") = ((u64)X86_IO_MAGIC << 32) | X86_IO_W7_WITH | X86_IO_W7_DIR | (2 << X86_IO_W7_SIZE_SHIFT); - asm volatile("mrs xzr, mdccsr_el0 \n\t" - : "+r"(x0), "+r"(x1), "+r"(x2), - "+r"(x3), "+r"(x4), "+r"(x5) - : "r"(x7) - :); - *eax = x0; - *ebx = x1; - *ecx = x2; - *edx = x3; - *si = x4; - *di = x5; + asm_inline volatile ( + "mrs xzr, mdccsr_el0; " + : "+r" (x0), "+r" (x2) + : "r" (x1), "r" (x3), "r" (x4), "r" (x5), "r" (x7) + : "memory"); + + *out2 = x2; + return x0; } -static inline void vmw_port_hb(unsigned long cmd, unsigned long in_ecx, - unsigned long in_si, unsigned long in_di, - unsigned long flags, unsigned long magic, - unsigned long bp, u32 w7dir, - unsigned long *eax, unsigned long *ebx, - unsigned long *ecx, unsigned long *edx, - unsigned long *si, unsigned long *di) +static inline +unsigned long vmware_hypercall6(unsigned long cmd, unsigned long in1, + unsigned long in3, u32 *out2, + u32 *out3, u32 *out4, u32 *out5) { - register u64 x0 asm("x0") = magic; + register u64 x0 asm("x0") = VMWARE_HYPERVISOR_MAGIC; + register u64 x1 asm("x1") = in1; + register u64 x2 asm("x2") = cmd; + register u64 x3 asm("x3") = in3 | VMWARE_HYPERVISOR_PORT; + register u64 x4 asm("x4"); + register u64 x5 asm("x5"); + register u64 x7 asm("x7") = ((u64)X86_IO_MAGIC << 32) | + X86_IO_W7_WITH | + X86_IO_W7_DIR | + (2 << X86_IO_W7_SIZE_SHIFT); + + asm_inline volatile ( + "mrs xzr, mdccsr_el0; " + : "+r" (x0), "+r" (x2), "+r" (x3), "=r" (x4), "=r" (x5) + : "r" (x1), "r" (x7) + : "memory"); + + *out2 = x2; + *out3 = x3; + *out4 = x4; + *out5 = x5; + return x0; +} + +static inline +unsigned long vmware_hypercall7(unsigned long cmd, unsigned long in1, + unsigned long in3, unsigned long in4, + unsigned long in5, u32 *out1, + u32 *out2, u32 *out3) +{ + register u64 x0 asm("x0") = VMWARE_HYPERVISOR_MAGIC; + register u64 x1 asm("x1") = in1; + register u64 x2 asm("x2") = cmd; + register u64 x3 asm("x3") = in3 | VMWARE_HYPERVISOR_PORT; + register u64 x4 asm("x4") = in4; + register u64 x5 asm("x5") = in5; + register u64 x7 asm("x7") = ((u64)X86_IO_MAGIC << 32) | + X86_IO_W7_WITH | + X86_IO_W7_DIR | + (2 << X86_IO_W7_SIZE_SHIFT); + + asm_inline volatile ( + "mrs xzr, mdccsr_el0; " + : "+r" (x0), "+r" (x1), "+r" (x2), "+r" (x3) + : "r" (x4), "r" (x5), "r" (x7) + : "memory"); + + *out1 = x1; + *out2 = x2; + *out3 = x3; + return x0; +} + +static inline +unsigned long vmware_hypercall_hb(unsigned long cmd, unsigned long in2, + unsigned long in3, unsigned long in4, + unsigned long in5, unsigned long in6, + u32 *out1, int dir) +{ + register u64 x0 asm("x0") = VMWARE_HYPERVISOR_MAGIC; register u64 x1 asm("x1") = cmd; - register u64 x2 asm("x2") = in_ecx; - register u64 x3 asm("x3") = flags | VMWARE_HYPERVISOR_PORT_HB; - register u64 x4 asm("x4") = in_si; - register u64 x5 asm("x5") = in_di; - register u64 x6 asm("x6") = bp; + register u64 x2 asm("x2") = in2; + register u64 x3 asm("x3") = in3 | VMWARE_HYPERVISOR_PORT_HB; + register u64 x4 asm("x4") = in4; + register u64 x5 asm("x5") = in5; + register u64 x6 asm("x6") = in6; register u64 x7 asm("x7") = ((u64)X86_IO_MAGIC << 32) | X86_IO_W7_STR | X86_IO_W7_WITH | - w7dir; - - asm volatile("mrs xzr, mdccsr_el0 \n\t" - : "+r"(x0), "+r"(x1), "+r"(x2), - "+r"(x3), "+r"(x4), "+r"(x5) - : "r"(x6), "r"(x7) - :); - *eax = x0; - *ebx = x1; - *ecx = x2; - *edx = x3; - *si = x4; - *di = x5; -} + dir; -#define VMW_PORT(cmd, in_ebx, in_si, in_di, flags, magic, eax, ebx, ecx, edx, \ - si, di) \ - vmw_port(cmd, in_ebx, in_si, in_di, flags, magic, &eax, &ebx, &ecx, \ - &edx, &si, &di) + asm_inline volatile ( + "mrs xzr, mdccsr_el0; " + : "+r" (x0), "+r" (x1) + : "r" (x2), "r" (x3), "r" (x4), "r" (x5), + "r" (x6), "r" (x7) + : "memory"); -#define VMW_PORT_HB_OUT(cmd, in_ecx, in_si, in_di, flags, magic, bp, eax, ebx, \ - ecx, edx, si, di) \ - vmw_port_hb(cmd, in_ecx, in_si, in_di, flags, magic, bp, \ - 0, &eax, &ebx, &ecx, &edx, &si, &di) + *out1 = x1; + return x0; +} -#define VMW_PORT_HB_IN(cmd, in_ecx, in_si, in_di, flags, magic, bp, eax, ebx, \ - ecx, edx, si, di) \ - vmw_port_hb(cmd, in_ecx, in_si, in_di, flags, magic, bp, \ - X86_IO_W7_DIR, &eax, &ebx, &ecx, &edx, &si, &di) +static inline +unsigned long vmware_hypercall_hb_out(unsigned long cmd, unsigned long in2, + unsigned long in3, unsigned long in4, + unsigned long in5, unsigned long in6, + u32 *out1) +{ + return vmware_hypercall_hb(cmd, in2, in3, in4, in5, in6, out1, 0); +} +static inline +unsigned long vmware_hypercall_hb_in(unsigned long cmd, unsigned long in2, + unsigned long in3, unsigned long in4, + unsigned long in5, unsigned long in6, + u32 *out1) +{ + return vmware_hypercall_hb(cmd, in2, in3, in4, in5, in6, out1, + X86_IO_W7_DIR); +} #endif #endif /* _VMWGFX_MSG_ARM64_H */ diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h b/drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h index 23899d743a90..13304d34cc6e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h @@ -37,191 +37,6 @@ #include <asm/vmware.h> -/** - * Hypervisor-specific bi-directional communication channel. Should never - * execute on bare metal hardware. The caller must make sure to check for - * supported hypervisor before using these macros. - * - * The last two parameters are both input and output and must be initialized. - * - * @cmd: [IN] Message Cmd - * @in_ebx: [IN] Message Len, through EBX - * @in_si: [IN] Input argument through SI, set to 0 if not used - * @in_di: [IN] Input argument through DI, set ot 0 if not used - * @flags: [IN] hypercall flags + [channel id] - * @magic: [IN] hypervisor magic value - * @eax: [OUT] value of EAX register - * @ebx: [OUT] e.g. status from an HB message status command - * @ecx: [OUT] e.g. status from a non-HB message status command - * @edx: [OUT] e.g. channel id - * @si: [OUT] - * @di: [OUT] - */ -#define VMW_PORT(cmd, in_ebx, in_si, in_di, \ - flags, magic, \ - eax, ebx, ecx, edx, si, di) \ -({ \ - asm volatile (VMWARE_HYPERCALL : \ - "=a"(eax), \ - "=b"(ebx), \ - "=c"(ecx), \ - "=d"(edx), \ - "=S"(si), \ - "=D"(di) : \ - "a"(magic), \ - "b"(in_ebx), \ - "c"(cmd), \ - "d"(flags), \ - "S"(in_si), \ - "D"(in_di) : \ - "memory"); \ -}) - - -/** - * Hypervisor-specific bi-directional communication channel. Should never - * execute on bare metal hardware. The caller must make sure to check for - * supported hypervisor before using these macros. - * - * The last 3 parameters are both input and output and must be initialized. - * - * @cmd: [IN] Message Cmd - * @in_ecx: [IN] Message Len, through ECX - * @in_si: [IN] Input argument through SI, set to 0 if not used - * @in_di: [IN] Input argument through DI, set to 0 if not used - * @flags: [IN] hypercall flags + [channel id] - * @magic: [IN] hypervisor magic value - * @bp: [IN] - * @eax: [OUT] value of EAX register - * @ebx: [OUT] e.g. status from an HB message status command - * @ecx: [OUT] e.g. status from a non-HB message status command - * @edx: [OUT] e.g. channel id - * @si: [OUT] - * @di: [OUT] - */ -#ifdef __x86_64__ - -#define VMW_PORT_HB_OUT(cmd, in_ecx, in_si, in_di, \ - flags, magic, bp, \ - eax, ebx, ecx, edx, si, di) \ -({ \ - asm volatile ( \ - UNWIND_HINT_SAVE \ - "push %%rbp;" \ - UNWIND_HINT_UNDEFINED \ - "mov %12, %%rbp;" \ - VMWARE_HYPERCALL_HB_OUT \ - "pop %%rbp;" \ - UNWIND_HINT_RESTORE : \ - "=a"(eax), \ - "=b"(ebx), \ - "=c"(ecx), \ - "=d"(edx), \ - "=S"(si), \ - "=D"(di) : \ - "a"(magic), \ - "b"(cmd), \ - "c"(in_ecx), \ - "d"(flags), \ - "S"(in_si), \ - "D"(in_di), \ - "r"(bp) : \ - "memory", "cc"); \ -}) - - -#define VMW_PORT_HB_IN(cmd, in_ecx, in_si, in_di, \ - flags, magic, bp, \ - eax, ebx, ecx, edx, si, di) \ -({ \ - asm volatile ( \ - UNWIND_HINT_SAVE \ - "push %%rbp;" \ - UNWIND_HINT_UNDEFINED \ - "mov %12, %%rbp;" \ - VMWARE_HYPERCALL_HB_IN \ - "pop %%rbp;" \ - UNWIND_HINT_RESTORE : \ - "=a"(eax), \ - "=b"(ebx), \ - "=c"(ecx), \ - "=d"(edx), \ - "=S"(si), \ - "=D"(di) : \ - "a"(magic), \ - "b"(cmd), \ - "c"(in_ecx), \ - "d"(flags), \ - "S"(in_si), \ - "D"(in_di), \ - "r"(bp) : \ - "memory", "cc"); \ -}) - -#elif defined(__i386__) - -/* - * In the 32-bit version of this macro, we store bp in a memory location - * because we've ran out of registers. - * Now we can't reference that memory location while we've modified - * %esp or %ebp, so we first push it on the stack, just before we push - * %ebp, and then when we need it we read it from the stack where we - * just pushed it. - */ -#define VMW_PORT_HB_OUT(cmd, in_ecx, in_si, in_di, \ - flags, magic, bp, \ - eax, ebx, ecx, edx, si, di) \ -({ \ - asm volatile ("push %12;" \ - "push %%ebp;" \ - "mov 0x04(%%esp), %%ebp;" \ - VMWARE_HYPERCALL_HB_OUT \ - "pop %%ebp;" \ - "add $0x04, %%esp;" : \ - "=a"(eax), \ - "=b"(ebx), \ - "=c"(ecx), \ - "=d"(edx), \ - "=S"(si), \ - "=D"(di) : \ - "a"(magic), \ - "b"(cmd), \ - "c"(in_ecx), \ - "d"(flags), \ - "S"(in_si), \ - "D"(in_di), \ - "m"(bp) : \ - "memory", "cc"); \ -}) - - -#define VMW_PORT_HB_IN(cmd, in_ecx, in_si, in_di, \ - flags, magic, bp, \ - eax, ebx, ecx, edx, si, di) \ -({ \ - asm volatile ("push %12;" \ - "push %%ebp;" \ - "mov 0x04(%%esp), %%ebp;" \ - VMWARE_HYPERCALL_HB_IN \ - "pop %%ebp;" \ - "add $0x04, %%esp;" : \ - "=a"(eax), \ - "=b"(ebx), \ - "=c"(ecx), \ - "=d"(edx), \ - "=S"(si), \ - "=D"(di) : \ - "a"(magic), \ - "b"(cmd), \ - "c"(in_ecx), \ - "d"(flags), \ - "S"(in_si), \ - "D"(in_di), \ - "m"(bp) : \ - "memory", "cc"); \ -}) -#endif /* defined(__i386__) */ - #endif /* defined(__i386__) || defined(__x86_64__) */ #endif /* _VMWGFX_MSG_X86_H */ diff --git a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c index 14b8b4278317..990285aa9b26 100644 --- a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c +++ b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c @@ -160,12 +160,16 @@ void intel_hdcp_gsc_fini(struct xe_device *xe) { struct intel_hdcp_gsc_message *hdcp_message = xe->display.hdcp.hdcp_message; + struct i915_hdcp_arbiter *arb = xe->display.hdcp.arbiter; - if (!hdcp_message) - return; + if (hdcp_message) { + xe_bo_unpin_map_no_vm(hdcp_message->hdcp_bo); + kfree(hdcp_message); + xe->display.hdcp.hdcp_message = NULL; + } - xe_bo_unpin_map_no_vm(hdcp_message->hdcp_bo); - kfree(hdcp_message); + kfree(arb); + xe->display.hdcp.arbiter = NULL; } static int xe_gsc_send_sync(struct xe_device *xe, diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c index 65c696966e96..31192d983d9e 100644 --- a/drivers/gpu/drm/xe/xe_bo.c +++ b/drivers/gpu/drm/xe/xe_bo.c @@ -343,7 +343,7 @@ static struct ttm_tt *xe_ttm_tt_create(struct ttm_buffer_object *ttm_bo, struct xe_device *xe = xe_bo_device(bo); struct xe_ttm_tt *tt; unsigned long extra_pages; - enum ttm_caching caching; + enum ttm_caching caching = ttm_cached; int err; tt = kzalloc(sizeof(*tt), GFP_KERNEL); @@ -357,26 +357,35 @@ static struct ttm_tt *xe_ttm_tt_create(struct ttm_buffer_object *ttm_bo, extra_pages = DIV_ROUND_UP(xe_device_ccs_bytes(xe, bo->size), PAGE_SIZE); - switch (bo->cpu_caching) { - case DRM_XE_GEM_CPU_CACHING_WC: - caching = ttm_write_combined; - break; - default: - caching = ttm_cached; - break; - } - - WARN_ON((bo->flags & XE_BO_FLAG_USER) && !bo->cpu_caching); - /* - * Display scanout is always non-coherent with the CPU cache. - * - * For Xe_LPG and beyond, PPGTT PTE lookups are also non-coherent and - * require a CPU:WC mapping. + * DGFX system memory is always WB / ttm_cached, since + * other caching modes are only supported on x86. DGFX + * GPU system memory accesses are always coherent with the + * CPU. */ - if ((!bo->cpu_caching && bo->flags & XE_BO_FLAG_SCANOUT) || - (xe->info.graphics_verx100 >= 1270 && bo->flags & XE_BO_FLAG_PAGETABLE)) - caching = ttm_write_combined; + if (!IS_DGFX(xe)) { + switch (bo->cpu_caching) { + case DRM_XE_GEM_CPU_CACHING_WC: + caching = ttm_write_combined; + break; + default: + caching = ttm_cached; + break; + } + + WARN_ON((bo->flags & XE_BO_FLAG_USER) && !bo->cpu_caching); + + /* + * Display scanout is always non-coherent with the CPU cache. + * + * For Xe_LPG and beyond, PPGTT PTE lookups are also + * non-coherent and require a CPU:WC mapping. + */ + if ((!bo->cpu_caching && bo->flags & XE_BO_FLAG_SCANOUT) || + (xe->info.graphics_verx100 >= 1270 && + bo->flags & XE_BO_FLAG_PAGETABLE)) + caching = ttm_write_combined; + } if (bo->flags & XE_BO_FLAG_NEEDS_UC) { /* diff --git a/drivers/gpu/drm/xe/xe_bo_types.h b/drivers/gpu/drm/xe/xe_bo_types.h index 86422e113d39..10450f1fbbde 100644 --- a/drivers/gpu/drm/xe/xe_bo_types.h +++ b/drivers/gpu/drm/xe/xe_bo_types.h @@ -66,7 +66,8 @@ struct xe_bo { /** * @cpu_caching: CPU caching mode. Currently only used for userspace - * objects. + * objects. Exceptions are system memory on DGFX, which is always + * WB. */ u16 cpu_caching; |