Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'drm-fixes-2025-06-06' of https://gitlab.freedesktop.org/drm/kernel

Pull more drm fixes from Simona Vetter:
"Another small batch of drm fixes, this time with a different baseline
and hence separate.

Drivers:
- ivpu:
- dma_resv locking
- warning fixes
- reset failure handling
- improve logging
- update fw file names
- fix cmdqueue unregister
- panel-simple: add Evervision VGG644804

Core Changes:
- sysfb: screen_info type check
- video: screen_info for relocated pci fb
- drm/sched: signal fence of killed job
- dummycon: deferred takeover fix"

* tag 'drm-fixes-2025-06-06' of https://gitlab.freedesktop.org/drm/kernel:
sysfb: Fix screen_info type check for VGA
video: screen_info: Relocate framebuffers behind PCI bridges
accel/ivpu: Fix warning in ivpu_gem_bo_free()
accel/ivpu: Trigger device recovery on engine reset/resume failure
accel/ivpu: Use dma_resv_lock() instead of a custom mutex
drm/panel-simple: fix the warnings for the Evervision VGG644804
accel/ivpu: Reorder Doorbell Unregister and Command Queue Destruction
accel/ivpu: Use firmware names from upstream repo
accel/ivpu: Improve buffer object logging
dummycon: Trigger redraw when switching consoles with deferred takeover
drm/scheduler: signal scheduled fence when kill job

+158 -95
+6 -6
drivers/accel/ivpu/ivpu_fw.c
··· 55 55 int gen; 56 56 const char *name; 57 57 } fw_names[] = { 58 - { IVPU_HW_IP_37XX, "vpu_37xx.bin" }, 58 + { IVPU_HW_IP_37XX, "intel/vpu/vpu_37xx_v1.bin" }, 59 59 { IVPU_HW_IP_37XX, "intel/vpu/vpu_37xx_v0.0.bin" }, 60 - { IVPU_HW_IP_40XX, "vpu_40xx.bin" }, 60 + { IVPU_HW_IP_40XX, "intel/vpu/vpu_40xx_v1.bin" }, 61 61 { IVPU_HW_IP_40XX, "intel/vpu/vpu_40xx_v0.0.bin" }, 62 - { IVPU_HW_IP_50XX, "vpu_50xx.bin" }, 62 + { IVPU_HW_IP_50XX, "intel/vpu/vpu_50xx_v1.bin" }, 63 63 { IVPU_HW_IP_50XX, "intel/vpu/vpu_50xx_v0.0.bin" }, 64 64 }; 65 65 66 66 /* Production fw_names from the table above */ 67 - MODULE_FIRMWARE("intel/vpu/vpu_37xx_v0.0.bin"); 68 - MODULE_FIRMWARE("intel/vpu/vpu_40xx_v0.0.bin"); 69 - MODULE_FIRMWARE("intel/vpu/vpu_50xx_v0.0.bin"); 67 + MODULE_FIRMWARE("intel/vpu/vpu_37xx_v1.bin"); 68 + MODULE_FIRMWARE("intel/vpu/vpu_40xx_v1.bin"); 69 + MODULE_FIRMWARE("intel/vpu/vpu_50xx_v1.bin"); 70 70 71 71 static int ivpu_fw_request(struct ivpu_device *vdev) 72 72 {
+53 -38
drivers/accel/ivpu/ivpu_gem.c
··· 28 28 { 29 29 ivpu_dbg(vdev, BO, 30 30 "%6s: bo %8p vpu_addr %9llx size %8zu ctx %d has_pages %d dma_mapped %d mmu_mapped %d wc %d imported %d\n", 31 - action, bo, bo->vpu_addr, ivpu_bo_size(bo), bo->ctx ? bo->ctx->id : 0, 31 + action, bo, bo->vpu_addr, ivpu_bo_size(bo), bo->ctx_id, 32 32 (bool)bo->base.pages, (bool)bo->base.sgt, bo->mmu_mapped, bo->base.map_wc, 33 33 (bool)drm_gem_is_imported(&bo->base.base)); 34 + } 35 + 36 + static inline int ivpu_bo_lock(struct ivpu_bo *bo) 37 + { 38 + return dma_resv_lock(bo->base.base.resv, NULL); 39 + } 40 + 41 + static inline void ivpu_bo_unlock(struct ivpu_bo *bo) 42 + { 43 + dma_resv_unlock(bo->base.base.resv); 34 44 } 35 45 36 46 /* ··· 53 43 int __must_check ivpu_bo_pin(struct ivpu_bo *bo) 54 44 { 55 45 struct ivpu_device *vdev = ivpu_bo_to_vdev(bo); 46 + struct sg_table *sgt; 56 47 int ret = 0; 57 48 58 - mutex_lock(&bo->lock); 59 - 60 49 ivpu_dbg_bo(vdev, bo, "pin"); 61 - drm_WARN_ON(&vdev->drm, !bo->ctx); 50 + 51 + sgt = drm_gem_shmem_get_pages_sgt(&bo->base); 52 + if (IS_ERR(sgt)) { 53 + ret = PTR_ERR(sgt); 54 + ivpu_err(vdev, "Failed to map BO in IOMMU: %d\n", ret); 55 + return ret; 56 + } 57 + 58 + ivpu_bo_lock(bo); 62 59 63 60 if (!bo->mmu_mapped) { 64 - struct sg_table *sgt = drm_gem_shmem_get_pages_sgt(&bo->base); 65 - 66 - if (IS_ERR(sgt)) { 67 - ret = PTR_ERR(sgt); 68 - ivpu_err(vdev, "Failed to map BO in IOMMU: %d\n", ret); 69 - goto unlock; 70 - } 71 - 61 + drm_WARN_ON(&vdev->drm, !bo->ctx); 72 62 ret = ivpu_mmu_context_map_sgt(vdev, bo->ctx, bo->vpu_addr, sgt, 73 63 ivpu_bo_is_snooped(bo)); 74 64 if (ret) { ··· 79 69 } 80 70 81 71 unlock: 82 - mutex_unlock(&bo->lock); 72 + ivpu_bo_unlock(bo); 83 73 84 74 return ret; 85 75 } ··· 94 84 if (!drm_dev_enter(&vdev->drm, &idx)) 95 85 return -ENODEV; 96 86 97 - mutex_lock(&bo->lock); 87 + ivpu_bo_lock(bo); 98 88 99 89 ret = ivpu_mmu_context_insert_node(ctx, range, ivpu_bo_size(bo), &bo->mm_node); 100 90 if (!ret) { ··· 104 94 ivpu_err(vdev, "Failed to add BO to context %u: %d\n", ctx->id, ret); 105 95 } 106 96 107 - ivpu_dbg_bo(vdev, bo, "alloc"); 108 - 109 - mutex_unlock(&bo->lock); 97 + ivpu_bo_unlock(bo); 110 98 111 99 drm_dev_exit(idx); 112 100 ··· 115 107 { 116 108 struct ivpu_device *vdev = ivpu_bo_to_vdev(bo); 117 109 118 - lockdep_assert(lockdep_is_held(&bo->lock) || !kref_read(&bo->base.base.refcount)); 110 + lockdep_assert(dma_resv_held(bo->base.base.resv) || !kref_read(&bo->base.base.refcount)); 119 111 120 112 if (bo->mmu_mapped) { 121 113 drm_WARN_ON(&vdev->drm, !bo->ctx); ··· 133 125 if (drm_gem_is_imported(&bo->base.base)) 134 126 return; 135 127 136 - dma_resv_lock(bo->base.base.resv, NULL); 137 128 if (bo->base.sgt) { 138 129 dma_unmap_sgtable(vdev->drm.dev, bo->base.sgt, DMA_BIDIRECTIONAL, 0); 139 130 sg_free_table(bo->base.sgt); 140 131 kfree(bo->base.sgt); 141 132 bo->base.sgt = NULL; 142 133 } 143 - dma_resv_unlock(bo->base.base.resv); 144 134 } 145 135 146 136 void ivpu_bo_unbind_all_bos_from_context(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx) ··· 150 144 151 145 mutex_lock(&vdev->bo_list_lock); 152 146 list_for_each_entry(bo, &vdev->bo_list, bo_list_node) { 153 - mutex_lock(&bo->lock); 147 + ivpu_bo_lock(bo); 154 148 if (bo->ctx == ctx) { 155 149 ivpu_dbg_bo(vdev, bo, "unbind"); 156 150 ivpu_bo_unbind_locked(bo); 157 151 } 158 - mutex_unlock(&bo->lock); 152 + ivpu_bo_unlock(bo); 159 153 } 160 154 mutex_unlock(&vdev->bo_list_lock); 161 155 } ··· 175 169 bo->base.pages_mark_dirty_on_put = true; /* VPU can dirty a BO anytime */ 176 170 177 171 INIT_LIST_HEAD(&bo->bo_list_node); 178 - mutex_init(&bo->lock); 179 172 180 173 return &bo->base.base; 181 174 } ··· 220 215 return ERR_PTR(ret); 221 216 } 222 217 223 - static struct ivpu_bo *ivpu_bo_alloc(struct ivpu_device *vdev, u64 size, u32 flags) 218 + static struct ivpu_bo *ivpu_bo_alloc(struct ivpu_device *vdev, u64 size, u32 flags, u32 ctx_id) 224 219 { 225 220 struct drm_gem_shmem_object *shmem; 226 221 struct ivpu_bo *bo; ··· 238 233 return ERR_CAST(shmem); 239 234 240 235 bo = to_ivpu_bo(&shmem->base); 236 + bo->ctx_id = ctx_id; 241 237 bo->base.map_wc = flags & DRM_IVPU_BO_WC; 242 238 bo->flags = flags; 243 239 244 240 mutex_lock(&vdev->bo_list_lock); 245 241 list_add_tail(&bo->bo_list_node, &vdev->bo_list); 246 242 mutex_unlock(&vdev->bo_list_lock); 243 + 244 + ivpu_dbg_bo(vdev, bo, "alloc"); 247 245 248 246 return bo; 249 247 } ··· 285 277 list_del(&bo->bo_list_node); 286 278 mutex_unlock(&vdev->bo_list_lock); 287 279 288 - drm_WARN_ON(&vdev->drm, !dma_resv_test_signaled(obj->resv, DMA_RESV_USAGE_READ)); 280 + drm_WARN_ON(&vdev->drm, !drm_gem_is_imported(&bo->base.base) && 281 + !dma_resv_test_signaled(obj->resv, DMA_RESV_USAGE_READ)); 282 + drm_WARN_ON(&vdev->drm, ivpu_bo_size(bo) == 0); 283 + drm_WARN_ON(&vdev->drm, bo->base.vaddr); 289 284 290 285 ivpu_bo_unbind_locked(bo); 291 - mutex_destroy(&bo->lock); 286 + drm_WARN_ON(&vdev->drm, bo->mmu_mapped); 287 + drm_WARN_ON(&vdev->drm, bo->ctx); 292 288 293 289 drm_WARN_ON(obj->dev, refcount_read(&bo->base.pages_use_count) > 1); 294 290 drm_gem_shmem_free(&bo->base); ··· 326 314 if (size == 0) 327 315 return -EINVAL; 328 316 329 - bo = ivpu_bo_alloc(vdev, size, args->flags); 317 + bo = ivpu_bo_alloc(vdev, size, args->flags, file_priv->ctx.id); 330 318 if (IS_ERR(bo)) { 331 319 ivpu_err(vdev, "Failed to allocate BO: %pe (ctx %u size %llu flags 0x%x)", 332 320 bo, file_priv->ctx.id, args->size, args->flags); ··· 334 322 } 335 323 336 324 ret = drm_gem_handle_create(file, &bo->base.base, &args->handle); 337 - if (!ret) 325 + if (ret) 326 + ivpu_err(vdev, "Failed to create handle for BO: %pe (ctx %u size %llu flags 0x%x)", 327 + bo, file_priv->ctx.id, args->size, args->flags); 328 + else 338 329 args->vpu_addr = bo->vpu_addr; 339 330 340 331 drm_gem_object_put(&bo->base.base); ··· 360 345 drm_WARN_ON(&vdev->drm, !PAGE_ALIGNED(range->end)); 361 346 drm_WARN_ON(&vdev->drm, !PAGE_ALIGNED(size)); 362 347 363 - bo = ivpu_bo_alloc(vdev, size, flags); 348 + bo = ivpu_bo_alloc(vdev, size, flags, IVPU_GLOBAL_CONTEXT_MMU_SSID); 364 349 if (IS_ERR(bo)) { 365 350 ivpu_err(vdev, "Failed to allocate BO: %pe (vpu_addr 0x%llx size %llu flags 0x%x)", 366 351 bo, range->start, size, flags); ··· 376 361 goto err_put; 377 362 378 363 if (flags & DRM_IVPU_BO_MAPPABLE) { 379 - dma_resv_lock(bo->base.base.resv, NULL); 364 + ivpu_bo_lock(bo); 380 365 ret = drm_gem_shmem_vmap_locked(&bo->base, &map); 381 - dma_resv_unlock(bo->base.base.resv); 366 + ivpu_bo_unlock(bo); 382 367 383 368 if (ret) 384 369 goto err_put; ··· 401 386 struct iosys_map map = IOSYS_MAP_INIT_VADDR(bo->base.vaddr); 402 387 403 388 if (bo->flags & DRM_IVPU_BO_MAPPABLE) { 404 - dma_resv_lock(bo->base.base.resv, NULL); 389 + ivpu_bo_lock(bo); 405 390 drm_gem_shmem_vunmap_locked(&bo->base, &map); 406 - dma_resv_unlock(bo->base.base.resv); 391 + ivpu_bo_unlock(bo); 407 392 } 408 393 409 394 drm_gem_object_put(&bo->base.base); ··· 422 407 423 408 bo = to_ivpu_bo(obj); 424 409 425 - mutex_lock(&bo->lock); 410 + ivpu_bo_lock(bo); 426 411 args->flags = bo->flags; 427 412 args->mmap_offset = drm_vma_node_offset_addr(&obj->vma_node); 428 413 args->vpu_addr = bo->vpu_addr; 429 414 args->size = obj->size; 430 - mutex_unlock(&bo->lock); 415 + ivpu_bo_unlock(bo); 431 416 432 417 drm_gem_object_put(obj); 433 418 return ret; ··· 464 449 465 450 static void ivpu_bo_print_info(struct ivpu_bo *bo, struct drm_printer *p) 466 451 { 467 - mutex_lock(&bo->lock); 452 + ivpu_bo_lock(bo); 468 453 469 454 drm_printf(p, "%-9p %-3u 0x%-12llx %-10lu 0x%-8x %-4u", 470 - bo, bo->ctx ? bo->ctx->id : 0, bo->vpu_addr, bo->base.base.size, 455 + bo, bo->ctx_id, bo->vpu_addr, bo->base.base.size, 471 456 bo->flags, kref_read(&bo->base.base.refcount)); 472 457 473 458 if (bo->base.pages) ··· 481 466 482 467 drm_printf(p, "\n"); 483 468 484 - mutex_unlock(&bo->lock); 469 + ivpu_bo_unlock(bo); 485 470 } 486 471 487 472 void ivpu_bo_list(struct drm_device *dev, struct drm_printer *p)
+1 -1
drivers/accel/ivpu/ivpu_gem.h
··· 17 17 struct list_head bo_list_node; 18 18 struct drm_mm_node mm_node; 19 19 20 - struct mutex lock; /* Protects: ctx, mmu_mapped, vpu_addr */ 21 20 u64 vpu_addr; 22 21 u32 flags; 23 22 u32 job_status; /* Valid only for command buffer */ 23 + u32 ctx_id; 24 24 bool mmu_mapped; 25 25 }; 26 26
+8 -6
drivers/accel/ivpu/ivpu_job.c
··· 247 247 if (!cmdq->db_id) 248 248 return 0; 249 249 250 + ret = ivpu_jsm_unregister_db(vdev, cmdq->db_id); 251 + if (!ret) 252 + ivpu_dbg(vdev, JOB, "DB %d unregistered\n", cmdq->db_id); 253 + 250 254 if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_HW) { 251 255 ret = ivpu_jsm_hws_destroy_cmdq(vdev, file_priv->ctx.id, cmdq->id); 252 256 if (!ret) 253 257 ivpu_dbg(vdev, JOB, "Command queue %d destroyed, ctx %d\n", 254 258 cmdq->id, file_priv->ctx.id); 255 259 } 256 - 257 - ret = ivpu_jsm_unregister_db(vdev, cmdq->db_id); 258 - if (!ret) 259 - ivpu_dbg(vdev, JOB, "DB %d unregistered\n", cmdq->db_id); 260 260 261 261 xa_erase(&file_priv->vdev->db_xa, cmdq->db_id); 262 262 cmdq->db_id = 0; ··· 986 986 return; 987 987 988 988 if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_HW) 989 - ivpu_jsm_reset_engine(vdev, 0); 989 + if (ivpu_jsm_reset_engine(vdev, 0)) 990 + return; 990 991 991 992 mutex_lock(&vdev->context_list_lock); 992 993 xa_for_each(&vdev->context_xa, ctx_id, file_priv) { ··· 1010 1009 if (vdev->fw->sched_mode != VPU_SCHEDULING_MODE_HW) 1011 1010 goto runtime_put; 1012 1011 1013 - ivpu_jsm_hws_resume_engine(vdev, 0); 1012 + if (ivpu_jsm_hws_resume_engine(vdev, 0)) 1013 + return; 1014 1014 /* 1015 1015 * In hardware scheduling mode NPU already has stopped processing jobs 1016 1016 * and won't send us any further notifications, thus we have to free job related resources
+7 -2
drivers/accel/ivpu/ivpu_jsm_msg.c
··· 7 7 #include "ivpu_hw.h" 8 8 #include "ivpu_ipc.h" 9 9 #include "ivpu_jsm_msg.h" 10 + #include "ivpu_pm.h" 10 11 #include "vpu_jsm_api.h" 11 12 12 13 const char *ivpu_jsm_msg_type_to_str(enum vpu_ipc_msg_type type) ··· 164 163 165 164 ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_ENGINE_RESET_DONE, &resp, 166 165 VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm); 167 - if (ret) 166 + if (ret) { 168 167 ivpu_err_ratelimited(vdev, "Failed to reset engine %d: %d\n", engine, ret); 168 + ivpu_pm_trigger_recovery(vdev, "Engine reset failed"); 169 + } 169 170 170 171 return ret; 171 172 } ··· 357 354 358 355 ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_HWS_RESUME_ENGINE_DONE, &resp, 359 356 VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm); 360 - if (ret) 357 + if (ret) { 361 358 ivpu_err_ratelimited(vdev, "Failed to resume engine %d: %d\n", engine, ret); 359 + ivpu_pm_trigger_recovery(vdev, "Engine resume failed"); 360 + } 362 361 363 362 return ret; 364 363 }
+18 -8
drivers/firmware/sysfb.c
··· 143 143 { 144 144 struct screen_info *si = &screen_info; 145 145 struct device *parent; 146 + unsigned int type; 146 147 struct simplefb_platform_data mode; 147 148 const char *name; 148 149 bool compatible; ··· 171 170 goto put_device; 172 171 } 173 172 173 + type = screen_info_video_type(si); 174 + 174 175 /* if the FB is incompatible, create a legacy framebuffer device */ 175 - if (si->orig_video_isVGA == VIDEO_TYPE_EFI) 176 - name = "efi-framebuffer"; 177 - else if (si->orig_video_isVGA == VIDEO_TYPE_VLFB) 178 - name = "vesa-framebuffer"; 179 - else if (si->orig_video_isVGA == VIDEO_TYPE_VGAC) 180 - name = "vga-framebuffer"; 181 - else if (si->orig_video_isVGA == VIDEO_TYPE_EGAC) 176 + switch (type) { 177 + case VIDEO_TYPE_EGAC: 182 178 name = "ega-framebuffer"; 183 - else 179 + break; 180 + case VIDEO_TYPE_VGAC: 181 + name = "vga-framebuffer"; 182 + break; 183 + case VIDEO_TYPE_VLFB: 184 + name = "vesa-framebuffer"; 185 + break; 186 + case VIDEO_TYPE_EFI: 187 + name = "efi-framebuffer"; 188 + break; 189 + default: 184 190 name = "platform-framebuffer"; 191 + break; 192 + } 185 193 186 194 pd = platform_device_alloc(name, 0); 187 195 if (!pd) {
+3 -2
drivers/gpu/drm/panel/panel-simple.c
··· 2198 2198 static const struct panel_desc evervision_vgg644804 = { 2199 2199 .timings = &evervision_vgg644804_timing, 2200 2200 .num_timings = 1, 2201 - .bpc = 8, 2201 + .bpc = 6, 2202 2202 .size = { 2203 2203 .width = 115, 2204 2204 .height = 86, 2205 2205 }, 2206 2206 .bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG, 2207 - .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE, 2207 + .bus_flags = DRM_BUS_FLAG_DE_HIGH, 2208 + .connector_type = DRM_MODE_CONNECTOR_LVDS, 2208 2209 }; 2209 2210 2210 2211 static const struct display_timing evervision_vgg804821_timing = {
+1
drivers/gpu/drm/scheduler/sched_entity.c
··· 176 176 { 177 177 struct drm_sched_job *job = container_of(wrk, typeof(*job), work); 178 178 179 + drm_sched_fence_scheduled(job->s_fence, NULL); 179 180 drm_sched_fence_finished(job->s_fence, -ESRCH); 180 181 WARN_ON(job->s_fence->parent); 181 182 job->sched->ops->free_job(job);
+13 -5
drivers/video/console/dummycon.c
··· 85 85 /* Redraw, so that we get putc(s) for output done while blanked */ 86 86 return true; 87 87 } 88 + 89 + static bool dummycon_switch(struct vc_data *vc) 90 + { 91 + /* 92 + * Redraw, so that we get putc(s) for output done while switched 93 + * away. Informs deferred consoles to take over the display. 94 + */ 95 + return true; 96 + } 88 97 #else 89 98 static void dummycon_putc(struct vc_data *vc, u16 c, unsigned int y, 90 99 unsigned int x) { } ··· 101 92 unsigned int ypos, unsigned int xpos) { } 102 93 static bool dummycon_blank(struct vc_data *vc, enum vesa_blank_mode blank, 103 94 bool mode_switch) 95 + { 96 + return false; 97 + } 98 + static bool dummycon_switch(struct vc_data *vc) 104 99 { 105 100 return false; 106 101 } ··· 133 120 static bool dummycon_scroll(struct vc_data *vc, unsigned int top, 134 121 unsigned int bottom, enum con_scroll dir, 135 122 unsigned int lines) 136 - { 137 - return false; 138 - } 139 - 140 - static bool dummycon_switch(struct vc_data *vc) 141 123 { 142 124 return false; 143 125 }
+48 -27
drivers/video/screen_info_pci.c
··· 7 7 8 8 static struct pci_dev *screen_info_lfb_pdev; 9 9 static size_t screen_info_lfb_bar; 10 - static resource_size_t screen_info_lfb_offset; 11 - static struct resource screen_info_lfb_res = DEFINE_RES_MEM(0, 0); 10 + static resource_size_t screen_info_lfb_res_start; // original start of resource 11 + static resource_size_t screen_info_lfb_offset; // framebuffer offset within resource 12 12 13 13 static bool __screen_info_relocation_is_valid(const struct screen_info *si, struct resource *pr) 14 14 { ··· 31 31 if (screen_info_lfb_pdev) { 32 32 struct resource *pr = &screen_info_lfb_pdev->resource[screen_info_lfb_bar]; 33 33 34 - if (pr->start != screen_info_lfb_res.start) { 34 + if (pr->start != screen_info_lfb_res_start) { 35 35 if (__screen_info_relocation_is_valid(si, pr)) { 36 36 /* 37 37 * Only update base if we have an actual ··· 47 47 } 48 48 } 49 49 50 + static int __screen_info_lfb_pci_bus_region(const struct screen_info *si, unsigned int type, 51 + struct pci_bus_region *r) 52 + { 53 + u64 base, size; 54 + 55 + base = __screen_info_lfb_base(si); 56 + if (!base) 57 + return -EINVAL; 58 + 59 + size = __screen_info_lfb_size(si, type); 60 + if (!size) 61 + return -EINVAL; 62 + 63 + r->start = base; 64 + r->end = base + size - 1; 65 + 66 + return 0; 67 + } 68 + 50 69 static void screen_info_fixup_lfb(struct pci_dev *pdev) 51 70 { 52 71 unsigned int type; 53 - struct resource res[SCREEN_INFO_MAX_RESOURCES]; 54 - size_t i, numres; 72 + struct pci_bus_region bus_region; 55 73 int ret; 74 + struct resource r = { 75 + .flags = IORESOURCE_MEM, 76 + }; 77 + const struct resource *pr; 56 78 const struct screen_info *si = &screen_info; 57 79 58 80 if (screen_info_lfb_pdev) 59 81 return; // already found 60 82 61 83 type = screen_info_video_type(si); 62 - if (type != VIDEO_TYPE_EFI) 63 - return; // only applies to EFI 84 + if (!__screen_info_has_lfb(type)) 85 + return; // only applies to EFI; maybe VESA 64 86 65 - ret = screen_info_resources(si, res, ARRAY_SIZE(res)); 87 + ret = __screen_info_lfb_pci_bus_region(si, type, &bus_region); 66 88 if (ret < 0) 67 89 return; 68 - numres = ret; 69 90 70 - for (i = 0; i < numres; ++i) { 71 - struct resource *r = &res[i]; 72 - const struct resource *pr; 91 + /* 92 + * Translate the PCI bus address to resource. Account 93 + * for an offset if the framebuffer is behind a PCI host 94 + * bridge. 95 + */ 96 + pcibios_bus_to_resource(pdev->bus, &r, &bus_region); 73 97 74 - if (!(r->flags & IORESOURCE_MEM)) 75 - continue; 76 - pr = pci_find_resource(pdev, r); 77 - if (!pr) 78 - continue; 98 + pr = pci_find_resource(pdev, &r); 99 + if (!pr) 100 + return; 79 101 80 - /* 81 - * We've found a PCI device with the framebuffer 82 - * resource. Store away the parameters to track 83 - * relocation of the framebuffer aperture. 84 - */ 85 - screen_info_lfb_pdev = pdev; 86 - screen_info_lfb_bar = pr - pdev->resource; 87 - screen_info_lfb_offset = r->start - pr->start; 88 - memcpy(&screen_info_lfb_res, r, sizeof(screen_info_lfb_res)); 89 - } 102 + /* 103 + * We've found a PCI device with the framebuffer 104 + * resource. Store away the parameters to track 105 + * relocation of the framebuffer aperture. 106 + */ 107 + screen_info_lfb_pdev = pdev; 108 + screen_info_lfb_bar = pr - pdev->resource; 109 + screen_info_lfb_offset = r.start - pr->start; 110 + screen_info_lfb_res_start = bus_region.start; 90 111 } 91 112 DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY, 16, 92 113 screen_info_fixup_lfb);