mirror of https://github.com/torvalds/linux.git
drm fixes for 6.17-rc2
bridge: - fix OF-node leak - fix documentation fbdev-emulation: - pass correct format info to drm_helper_mode_fill_fb_struct() panfrost: - print correct RSS size amdgpu: - PSP fix - VRAM reservation fix - CSA fix - Process kill fix i915: - Fix the implementation of wa_18038517565 [fbc] - Do not trigger Frame Change events from frontbuffer flush [psr] xe: - Some more xe_migrate_access_memory fixes (Auld) - Defer buffer object shrinker write-backs and GPU waits (Thomas) - HWMON fix for clamping limits (Karthik) - SRIOV-PF: Set VF LMEM BAR size (Michal) -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEEKbZHaGwW9KfbeusDHTzWXnEhr4FAmifpQsACgkQDHTzWXnE hr63FA//SvXpA51XfZuF1gm6x3oeYuF1xGMLS34ol6EI4YwOQg7wke7IFMe12dMJ X/1kZ48Ju1l9NLyuRQfC7zW1EAqN4HjrB62MdGxFv7+Ap/i5SiOow9zJRSg0a5Mq qRNmyGSw4ch1sVnU4LN1+9rVqpMN/jo5ngEvSlLlUmDtG2Plg9PzqSGIGHGPgStL DEQI9DHUzn1F6lVtvdj/rA1+EzxaPKQ1g/VHMbA8bR46xal4jJ1BOWUI2plG6dcf OxfhNvdqETz7q1YFgbyMUSXaR2VcK9qM/ATSBV/CSYOz51cd11CE12FI+Fywfc0i /Jgt3H1Ociis/x7BfuTaRL3FkVYgzq7UK4KHZVeASJch2AjSl5tyaLx+ghmr4+5i bPgK5rcWof9XvxRHylzKUcJwg+1Tn3r280mwWS/RQuGDEAWkT/8IB7WO+Ol8tJ+v UbSsODl2BkXnumZE7r/dOcYNaJNgRdE5Uvc7+jCnt67Rk1WHBS8BB82Cst285A9h lJdNp+mvN10erfWfLYhEWaFs/E6Us0YyFxKui65ZJftS5ErsQBDKE7Va7MVz5AxM Laa8/K+5Y6c/2WW1Z8Ayiua/KV2Y7b4oWlhUPu6V/rjZrHHYt2sE1KV/bBeBKlPo Q1zjf8ECQW90lK7vLSxPfGID5LMQUhJbmpaEpfyjyU+Q9nYjl9Y= =d48j -----END PGP SIGNATURE----- Merge tag 'drm-fixes-2025-08-16' of https://gitlab.freedesktop.org/drm/kernel Pull drm fixes from Dave Airlie: "Relatively quiet week, usual amdgpu/i915/xe fixes along with a set of fixes for fbdev format info, which fix some regressions seen in with rc1. bridge: - fix OF-node leak - fix documentation fbdev-emulation: - pass correct format info to drm_helper_mode_fill_fb_struct() panfrost: - print correct RSS size amdgpu: - PSP fix - VRAM reservation fix - CSA fix - Process kill fix i915: - Fix the implementation of wa_18038517565 [fbc] - Do not trigger Frame Change events from frontbuffer flush [psr] xe: - Some more xe_migrate_access_memory fixes (Auld) - Defer buffer object shrinker write-backs and GPU waits (Thomas) - HWMON fix for clamping limits (Karthik) - SRIOV-PF: Set VF LMEM BAR size (Michal)" * tag 'drm-fixes-2025-08-16' of https://gitlab.freedesktop.org/drm/kernel: drm/xe/pf: Set VF LMEM BAR size drm/amdgpu: fix task hang from failed job submission during process kill drm/amdgpu: fix incorrect vm flags to map bo drm/amdgpu: fix vram reservation issue drm/amdgpu: Add PSP fw version check for fw reserve GFX command drm/xe/hwmon: Add SW clamp for power limits writes drm/xe: Defer buffer object shrinker write-backs and GPU waits drm/xe/migrate: prevent potential UAF drm/xe/migrate: don't overflow max copy size drm/xe/migrate: prevent infinite recursion drm/i915/psr: Do not trigger Frame Change events from frontbuffer flush drm/i915/fbc: fix the implementation of wa_18038517565 drm/panfrost: Print RSS for tiler heap BO's in debugfs GEMS file drm/radeon: Pass along the format info from .fb_create() to drm_helper_mode_fill_fb_struct() drm/nouveau: Pass along the format info from .fb_create() to drm_helper_mode_fill_fb_struct() drm/omap: Pass along the format info from .fb_create() to drm_helper_mode_fill_fb_struct() drm/bridge: document HDMI CEC callbacks drm/bridge: Describe the newly introduced drm_connector parameter for drm_bridge_detect drm/bridge: fix OF node leak
This commit is contained in:
commit
dfd4b508c8
|
|
@ -1139,6 +1139,9 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
|
|||
}
|
||||
}
|
||||
|
||||
if (!amdgpu_vm_ready(vm))
|
||||
return -EINVAL;
|
||||
|
||||
r = amdgpu_vm_clear_freed(adev, vm, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
|
|
|
|||
|
|
@ -88,8 +88,8 @@ int amdgpu_map_static_csa(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
|||
}
|
||||
|
||||
r = amdgpu_vm_bo_map(adev, *bo_va, csa_addr, 0, size,
|
||||
AMDGPU_PTE_READABLE | AMDGPU_PTE_WRITEABLE |
|
||||
AMDGPU_PTE_EXECUTABLE);
|
||||
AMDGPU_VM_PAGE_READABLE | AMDGPU_VM_PAGE_WRITEABLE |
|
||||
AMDGPU_VM_PAGE_EXECUTABLE);
|
||||
|
||||
if (r) {
|
||||
DRM_ERROR("failed to do bo_map on static CSA, err=%d\n", r);
|
||||
|
|
|
|||
|
|
@ -1039,15 +1039,28 @@ int psp_update_fw_reservation(struct psp_context *psp)
|
|||
{
|
||||
int ret;
|
||||
uint64_t reserv_addr, reserv_addr_ext;
|
||||
uint32_t reserv_size, reserv_size_ext;
|
||||
uint32_t reserv_size, reserv_size_ext, mp0_ip_ver;
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
|
||||
mp0_ip_ver = amdgpu_ip_version(adev, MP0_HWIP, 0);
|
||||
|
||||
if (amdgpu_sriov_vf(psp->adev))
|
||||
return 0;
|
||||
|
||||
if ((amdgpu_ip_version(adev, MP0_HWIP, 0) != IP_VERSION(14, 0, 2)) &&
|
||||
(amdgpu_ip_version(adev, MP0_HWIP, 0) != IP_VERSION(14, 0, 3)))
|
||||
switch (mp0_ip_ver) {
|
||||
case IP_VERSION(14, 0, 2):
|
||||
if (adev->psp.sos.fw_version < 0x3b0e0d)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case IP_VERSION(14, 0, 3):
|
||||
if (adev->psp.sos.fw_version < 0x3a0e14)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = psp_get_fw_reservation_info(psp, GFX_CMD_ID_FB_FW_RESERV_ADDR, &reserv_addr, &reserv_size);
|
||||
if (ret)
|
||||
|
|
|
|||
|
|
@ -654,11 +654,10 @@ int amdgpu_vm_validate(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
|||
* Check if all VM PDs/PTs are ready for updates
|
||||
*
|
||||
* Returns:
|
||||
* True if VM is not evicting.
|
||||
* True if VM is not evicting and all VM entities are not stopped
|
||||
*/
|
||||
bool amdgpu_vm_ready(struct amdgpu_vm *vm)
|
||||
{
|
||||
bool empty;
|
||||
bool ret;
|
||||
|
||||
amdgpu_vm_eviction_lock(vm);
|
||||
|
|
@ -666,10 +665,18 @@ bool amdgpu_vm_ready(struct amdgpu_vm *vm)
|
|||
amdgpu_vm_eviction_unlock(vm);
|
||||
|
||||
spin_lock(&vm->status_lock);
|
||||
empty = list_empty(&vm->evicted);
|
||||
ret &= list_empty(&vm->evicted);
|
||||
spin_unlock(&vm->status_lock);
|
||||
|
||||
return ret && empty;
|
||||
spin_lock(&vm->immediate.lock);
|
||||
ret &= !vm->immediate.stopped;
|
||||
spin_unlock(&vm->immediate.lock);
|
||||
|
||||
spin_lock(&vm->delayed.lock);
|
||||
ret &= !vm->delayed.stopped;
|
||||
spin_unlock(&vm->delayed.lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -648,9 +648,8 @@ static void amdgpu_vram_mgr_del(struct ttm_resource_manager *man,
|
|||
list_for_each_entry(block, &vres->blocks, link)
|
||||
vis_usage += amdgpu_vram_mgr_vis_size(adev, block);
|
||||
|
||||
amdgpu_vram_mgr_do_reserve(man);
|
||||
|
||||
drm_buddy_free_list(mm, &vres->blocks, vres->flags);
|
||||
amdgpu_vram_mgr_do_reserve(man);
|
||||
mutex_unlock(&mgr->lock);
|
||||
|
||||
atomic64_sub(vis_usage, &mgr->vis_usage);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ static void drm_aux_bridge_release(struct device *dev)
|
|||
{
|
||||
struct auxiliary_device *adev = to_auxiliary_dev(dev);
|
||||
|
||||
of_node_put(dev->of_node);
|
||||
ida_free(&drm_aux_bridge_ida, adev->id);
|
||||
|
||||
kfree(adev);
|
||||
|
|
@ -65,6 +66,7 @@ int drm_aux_bridge_register(struct device *parent)
|
|||
|
||||
ret = auxiliary_device_init(adev);
|
||||
if (ret) {
|
||||
of_node_put(adev->dev.of_node);
|
||||
ida_free(&drm_aux_bridge_ida, adev->id);
|
||||
kfree(adev);
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -1227,6 +1227,7 @@ EXPORT_SYMBOL(drm_atomic_bridge_chain_check);
|
|||
/**
|
||||
* drm_bridge_detect - check if anything is attached to the bridge output
|
||||
* @bridge: bridge control structure
|
||||
* @connector: attached connector
|
||||
*
|
||||
* If the bridge supports output detection, as reported by the
|
||||
* DRM_BRIDGE_OP_DETECT bridge ops flag, call &drm_bridge_funcs.detect for the
|
||||
|
|
|
|||
|
|
@ -552,10 +552,6 @@ static void ilk_fbc_deactivate(struct intel_fbc *fbc)
|
|||
if (dpfc_ctl & DPFC_CTL_EN) {
|
||||
dpfc_ctl &= ~DPFC_CTL_EN;
|
||||
intel_de_write(display, ILK_DPFC_CONTROL(fbc->id), dpfc_ctl);
|
||||
|
||||
/* wa_18038517565 Enable DPFC clock gating after FBC disable */
|
||||
if (display->platform.dg2 || DISPLAY_VER(display) >= 14)
|
||||
fbc_compressor_clkgate_disable_wa(fbc, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1710,6 +1706,10 @@ static void __intel_fbc_disable(struct intel_fbc *fbc)
|
|||
|
||||
__intel_fbc_cleanup_cfb(fbc);
|
||||
|
||||
/* wa_18038517565 Enable DPFC clock gating after FBC disable */
|
||||
if (display->platform.dg2 || DISPLAY_VER(display) >= 14)
|
||||
fbc_compressor_clkgate_disable_wa(fbc, false);
|
||||
|
||||
fbc->state.plane = NULL;
|
||||
fbc->flip_pending = false;
|
||||
fbc->busy_bits = 0;
|
||||
|
|
|
|||
|
|
@ -3275,7 +3275,9 @@ static void intel_psr_configure_full_frame_update(struct intel_dp *intel_dp)
|
|||
|
||||
static void _psr_invalidate_handle(struct intel_dp *intel_dp)
|
||||
{
|
||||
if (intel_dp->psr.psr2_sel_fetch_enabled) {
|
||||
struct intel_display *display = to_intel_display(intel_dp);
|
||||
|
||||
if (DISPLAY_VER(display) < 20 && intel_dp->psr.psr2_sel_fetch_enabled) {
|
||||
if (!intel_dp->psr.psr2_sel_fetch_cff_enabled) {
|
||||
intel_dp->psr.psr2_sel_fetch_cff_enabled = true;
|
||||
intel_psr_configure_full_frame_update(intel_dp);
|
||||
|
|
@ -3361,7 +3363,7 @@ static void _psr_flush_handle(struct intel_dp *intel_dp)
|
|||
{
|
||||
struct intel_display *display = to_intel_display(intel_dp);
|
||||
|
||||
if (intel_dp->psr.psr2_sel_fetch_enabled) {
|
||||
if (DISPLAY_VER(display) < 20 && intel_dp->psr.psr2_sel_fetch_enabled) {
|
||||
if (intel_dp->psr.psr2_sel_fetch_cff_enabled) {
|
||||
/* can we turn CFF off? */
|
||||
if (intel_dp->psr.busy_frontbuffer_bits == 0)
|
||||
|
|
@ -3378,11 +3380,13 @@ static void _psr_flush_handle(struct intel_dp *intel_dp)
|
|||
* existing SU configuration
|
||||
*/
|
||||
intel_psr_configure_full_frame_update(intel_dp);
|
||||
|
||||
intel_psr_force_update(intel_dp);
|
||||
} else {
|
||||
intel_psr_exit(intel_dp);
|
||||
}
|
||||
|
||||
intel_psr_force_update(intel_dp);
|
||||
|
||||
if (!intel_dp->psr.psr2_sel_fetch_enabled && !intel_dp->psr.active &&
|
||||
if ((!intel_dp->psr.psr2_sel_fetch_enabled || DISPLAY_VER(display) >= 20) &&
|
||||
!intel_dp->psr.busy_frontbuffer_bits)
|
||||
queue_work(display->wq.unordered, &intel_dp->psr.work);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -253,6 +253,7 @@ nouveau_check_bl_size(struct nouveau_drm *drm, struct nouveau_bo *nvbo,
|
|||
|
||||
int
|
||||
nouveau_framebuffer_new(struct drm_device *dev,
|
||||
const struct drm_format_info *info,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct drm_gem_object *gem,
|
||||
struct drm_framebuffer **pfb)
|
||||
|
|
@ -260,7 +261,6 @@ nouveau_framebuffer_new(struct drm_device *dev,
|
|||
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||
struct nouveau_bo *nvbo = nouveau_gem_object(gem);
|
||||
struct drm_framebuffer *fb;
|
||||
const struct drm_format_info *info;
|
||||
unsigned int height, i;
|
||||
uint32_t tile_mode;
|
||||
uint8_t kind;
|
||||
|
|
@ -295,9 +295,6 @@ nouveau_framebuffer_new(struct drm_device *dev,
|
|||
kind = nvbo->kind;
|
||||
}
|
||||
|
||||
info = drm_get_format_info(dev, mode_cmd->pixel_format,
|
||||
mode_cmd->modifier[0]);
|
||||
|
||||
for (i = 0; i < info->num_planes; i++) {
|
||||
height = drm_format_info_plane_height(info,
|
||||
mode_cmd->height,
|
||||
|
|
@ -321,7 +318,7 @@ nouveau_framebuffer_new(struct drm_device *dev,
|
|||
if (!(fb = *pfb = kzalloc(sizeof(*fb), GFP_KERNEL)))
|
||||
return -ENOMEM;
|
||||
|
||||
drm_helper_mode_fill_fb_struct(dev, fb, NULL, mode_cmd);
|
||||
drm_helper_mode_fill_fb_struct(dev, fb, info, mode_cmd);
|
||||
fb->obj[0] = gem;
|
||||
|
||||
ret = drm_framebuffer_init(dev, fb, &nouveau_framebuffer_funcs);
|
||||
|
|
@ -344,7 +341,7 @@ nouveau_user_framebuffer_create(struct drm_device *dev,
|
|||
if (!gem)
|
||||
return ERR_PTR(-ENOENT);
|
||||
|
||||
ret = nouveau_framebuffer_new(dev, mode_cmd, gem, &fb);
|
||||
ret = nouveau_framebuffer_new(dev, info, mode_cmd, gem, &fb);
|
||||
if (ret == 0)
|
||||
return fb;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,8 +8,11 @@
|
|||
|
||||
#include <drm/drm_framebuffer.h>
|
||||
|
||||
struct drm_format_info;
|
||||
|
||||
int
|
||||
nouveau_framebuffer_new(struct drm_device *dev,
|
||||
const struct drm_format_info *info,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct drm_gem_object *gem,
|
||||
struct drm_framebuffer **pfb);
|
||||
|
|
|
|||
|
|
@ -351,7 +351,7 @@ struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
|
|||
}
|
||||
}
|
||||
|
||||
fb = omap_framebuffer_init(dev, mode_cmd, bos);
|
||||
fb = omap_framebuffer_init(dev, info, mode_cmd, bos);
|
||||
if (IS_ERR(fb))
|
||||
goto error;
|
||||
|
||||
|
|
@ -365,9 +365,9 @@ struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
|
|||
}
|
||||
|
||||
struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
|
||||
const struct drm_format_info *info,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos)
|
||||
{
|
||||
const struct drm_format_info *format = NULL;
|
||||
struct omap_framebuffer *omap_fb = NULL;
|
||||
struct drm_framebuffer *fb = NULL;
|
||||
unsigned int pitch = mode_cmd->pitches[0];
|
||||
|
|
@ -377,15 +377,12 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
|
|||
dev, mode_cmd, mode_cmd->width, mode_cmd->height,
|
||||
(char *)&mode_cmd->pixel_format);
|
||||
|
||||
format = drm_get_format_info(dev, mode_cmd->pixel_format,
|
||||
mode_cmd->modifier[0]);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(formats); i++) {
|
||||
if (formats[i] == mode_cmd->pixel_format)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!format || i == ARRAY_SIZE(formats)) {
|
||||
if (i == ARRAY_SIZE(formats)) {
|
||||
dev_dbg(dev->dev, "unsupported pixel format: %4.4s\n",
|
||||
(char *)&mode_cmd->pixel_format);
|
||||
ret = -EINVAL;
|
||||
|
|
@ -399,7 +396,7 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
|
|||
}
|
||||
|
||||
fb = &omap_fb->base;
|
||||
omap_fb->format = format;
|
||||
omap_fb->format = info;
|
||||
mutex_init(&omap_fb->lock);
|
||||
|
||||
/*
|
||||
|
|
@ -407,23 +404,23 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
|
|||
* that the two planes of multiplane formats need the same number of
|
||||
* bytes per pixel.
|
||||
*/
|
||||
if (format->num_planes == 2 && pitch != mode_cmd->pitches[1]) {
|
||||
if (info->num_planes == 2 && pitch != mode_cmd->pitches[1]) {
|
||||
dev_dbg(dev->dev, "pitches differ between planes 0 and 1\n");
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (pitch % format->cpp[0]) {
|
||||
if (pitch % info->cpp[0]) {
|
||||
dev_dbg(dev->dev,
|
||||
"buffer pitch (%u bytes) is not a multiple of pixel size (%u bytes)\n",
|
||||
pitch, format->cpp[0]);
|
||||
pitch, info->cpp[0]);
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (i = 0; i < format->num_planes; i++) {
|
||||
for (i = 0; i < info->num_planes; i++) {
|
||||
struct plane *plane = &omap_fb->planes[i];
|
||||
unsigned int vsub = i == 0 ? 1 : format->vsub;
|
||||
unsigned int vsub = i == 0 ? 1 : info->vsub;
|
||||
unsigned int size;
|
||||
|
||||
size = pitch * mode_cmd->height / vsub;
|
||||
|
|
@ -440,7 +437,7 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
|
|||
plane->dma_addr = 0;
|
||||
}
|
||||
|
||||
drm_helper_mode_fill_fb_struct(dev, fb, NULL, mode_cmd);
|
||||
drm_helper_mode_fill_fb_struct(dev, fb, info, mode_cmd);
|
||||
|
||||
ret = drm_framebuffer_init(dev, fb, &omap_framebuffer_funcs);
|
||||
if (ret) {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ struct drm_connector;
|
|||
struct drm_device;
|
||||
struct drm_file;
|
||||
struct drm_framebuffer;
|
||||
struct drm_format_info;
|
||||
struct drm_gem_object;
|
||||
struct drm_mode_fb_cmd2;
|
||||
struct drm_plane_state;
|
||||
|
|
@ -23,6 +24,7 @@ struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
|
|||
struct drm_file *file, const struct drm_format_info *info,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd);
|
||||
struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
|
||||
const struct drm_format_info *info,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos);
|
||||
int omap_framebuffer_pin(struct drm_framebuffer *fb);
|
||||
void omap_framebuffer_unpin(struct drm_framebuffer *fb);
|
||||
|
|
|
|||
|
|
@ -197,7 +197,10 @@ int omap_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
fb = omap_framebuffer_init(dev, &mode_cmd, &bo);
|
||||
fb = omap_framebuffer_init(dev,
|
||||
drm_get_format_info(dev, mode_cmd.pixel_format,
|
||||
mode_cmd.modifier[0]),
|
||||
&mode_cmd, &bo);
|
||||
if (IS_ERR(fb)) {
|
||||
dev_err(dev->dev, "failed to allocate fb\n");
|
||||
/* note: if fb creation failed, we can't rely on fb destroy
|
||||
|
|
|
|||
|
|
@ -432,7 +432,7 @@ static void panfrost_gem_debugfs_bo_print(struct panfrost_gem_object *bo,
|
|||
if (!refcount)
|
||||
return;
|
||||
|
||||
resident_size = bo->base.pages ? bo->base.base.size : 0;
|
||||
resident_size = panfrost_gem_rss(&bo->base.base);
|
||||
|
||||
snprintf(creator_info, sizeof(creator_info),
|
||||
"%s/%d", bo->debugfs.creator.process_name, bo->debugfs.creator.tgid);
|
||||
|
|
|
|||
|
|
@ -1297,12 +1297,13 @@ static const struct drm_framebuffer_funcs radeon_fb_funcs = {
|
|||
int
|
||||
radeon_framebuffer_init(struct drm_device *dev,
|
||||
struct drm_framebuffer *fb,
|
||||
const struct drm_format_info *info,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct drm_gem_object *obj)
|
||||
{
|
||||
int ret;
|
||||
fb->obj[0] = obj;
|
||||
drm_helper_mode_fill_fb_struct(dev, fb, NULL, mode_cmd);
|
||||
drm_helper_mode_fill_fb_struct(dev, fb, info, mode_cmd);
|
||||
ret = drm_framebuffer_init(dev, fb, &radeon_fb_funcs);
|
||||
if (ret) {
|
||||
fb->obj[0] = NULL;
|
||||
|
|
@ -1341,7 +1342,7 @@ radeon_user_framebuffer_create(struct drm_device *dev,
|
|||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
ret = radeon_framebuffer_init(dev, fb, mode_cmd, obj);
|
||||
ret = radeon_framebuffer_init(dev, fb, info, mode_cmd, obj);
|
||||
if (ret) {
|
||||
kfree(fb);
|
||||
drm_gem_object_put(obj);
|
||||
|
|
|
|||
|
|
@ -53,10 +53,10 @@ static void radeon_fbdev_destroy_pinned_object(struct drm_gem_object *gobj)
|
|||
}
|
||||
|
||||
static int radeon_fbdev_create_pinned_object(struct drm_fb_helper *fb_helper,
|
||||
const struct drm_format_info *info,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct drm_gem_object **gobj_p)
|
||||
{
|
||||
const struct drm_format_info *info;
|
||||
struct radeon_device *rdev = fb_helper->dev->dev_private;
|
||||
struct drm_gem_object *gobj = NULL;
|
||||
struct radeon_bo *rbo = NULL;
|
||||
|
|
@ -67,8 +67,6 @@ static int radeon_fbdev_create_pinned_object(struct drm_fb_helper *fb_helper,
|
|||
int height = mode_cmd->height;
|
||||
u32 cpp;
|
||||
|
||||
info = drm_get_format_info(rdev_to_drm(rdev), mode_cmd->pixel_format,
|
||||
mode_cmd->modifier[0]);
|
||||
cpp = info->cpp[0];
|
||||
|
||||
/* need to align pitch with crtc limits */
|
||||
|
|
@ -206,6 +204,7 @@ int radeon_fbdev_driver_fbdev_probe(struct drm_fb_helper *fb_helper,
|
|||
struct drm_fb_helper_surface_size *sizes)
|
||||
{
|
||||
struct radeon_device *rdev = fb_helper->dev->dev_private;
|
||||
const struct drm_format_info *format_info;
|
||||
struct drm_mode_fb_cmd2 mode_cmd = { };
|
||||
struct fb_info *info;
|
||||
struct drm_gem_object *gobj;
|
||||
|
|
@ -224,7 +223,9 @@ int radeon_fbdev_driver_fbdev_probe(struct drm_fb_helper *fb_helper,
|
|||
mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
|
||||
sizes->surface_depth);
|
||||
|
||||
ret = radeon_fbdev_create_pinned_object(fb_helper, &mode_cmd, &gobj);
|
||||
format_info = drm_get_format_info(rdev_to_drm(rdev), mode_cmd.pixel_format,
|
||||
mode_cmd.modifier[0]);
|
||||
ret = radeon_fbdev_create_pinned_object(fb_helper, format_info, &mode_cmd, &gobj);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to create fbcon object %d\n", ret);
|
||||
return ret;
|
||||
|
|
@ -236,7 +237,7 @@ int radeon_fbdev_driver_fbdev_probe(struct drm_fb_helper *fb_helper,
|
|||
ret = -ENOMEM;
|
||||
goto err_radeon_fbdev_destroy_pinned_object;
|
||||
}
|
||||
ret = radeon_framebuffer_init(rdev_to_drm(rdev), fb, &mode_cmd, gobj);
|
||||
ret = radeon_framebuffer_init(rdev_to_drm(rdev), fb, format_info, &mode_cmd, gobj);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to initialize framebuffer %d\n", ret);
|
||||
goto err_kfree;
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
|
||||
struct drm_fb_helper;
|
||||
struct drm_fb_helper_surface_size;
|
||||
struct drm_format_info;
|
||||
|
||||
struct edid;
|
||||
struct drm_edid;
|
||||
|
|
@ -890,6 +891,7 @@ extern void
|
|||
radeon_combios_encoder_dpms_scratch_regs(struct drm_encoder *encoder, bool on);
|
||||
int radeon_framebuffer_init(struct drm_device *dev,
|
||||
struct drm_framebuffer *rfb,
|
||||
const struct drm_format_info *info,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct drm_gem_object *obj);
|
||||
|
||||
|
|
|
|||
|
|
@ -7,5 +7,6 @@
|
|||
|
||||
#define GTTMMADR_BAR 0 /* MMIO + GTT */
|
||||
#define LMEM_BAR 2 /* VRAM */
|
||||
#define VF_LMEM_BAR 9 /* VF VRAM */
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -332,6 +332,7 @@ static int xe_hwmon_power_max_write(struct xe_hwmon *hwmon, u32 attr, int channe
|
|||
int ret = 0;
|
||||
u32 reg_val, max;
|
||||
struct xe_reg rapl_limit;
|
||||
u64 max_supp_power_limit = 0;
|
||||
|
||||
mutex_lock(&hwmon->hwmon_lock);
|
||||
|
||||
|
|
@ -356,6 +357,20 @@ static int xe_hwmon_power_max_write(struct xe_hwmon *hwmon, u32 attr, int channe
|
|||
goto unlock;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the sysfs value exceeds the maximum pcode supported power limit value, clamp it to
|
||||
* the supported maximum (U12.3 format).
|
||||
* This is to avoid truncation during reg_val calculation below and ensure the valid
|
||||
* power limit is sent for pcode which would clamp it to card-supported value.
|
||||
*/
|
||||
max_supp_power_limit = ((PWR_LIM_VAL) >> hwmon->scl_shift_power) * SF_POWER;
|
||||
if (value > max_supp_power_limit) {
|
||||
value = max_supp_power_limit;
|
||||
drm_info(&hwmon->xe->drm,
|
||||
"Power limit clamped as selected %s exceeds channel %d limit\n",
|
||||
PWR_ATTR_TO_STR(attr), channel);
|
||||
}
|
||||
|
||||
/* Computation in 64-bits to avoid overflow. Round to nearest. */
|
||||
reg_val = DIV_ROUND_CLOSEST_ULL((u64)value << hwmon->scl_shift_power, SF_POWER);
|
||||
|
||||
|
|
@ -739,9 +754,23 @@ static int xe_hwmon_power_curr_crit_write(struct xe_hwmon *hwmon, int channel,
|
|||
{
|
||||
int ret;
|
||||
u32 uval;
|
||||
u64 max_crit_power_curr = 0;
|
||||
|
||||
mutex_lock(&hwmon->hwmon_lock);
|
||||
|
||||
/*
|
||||
* If the sysfs value exceeds the pcode mailbox cmd POWER_SETUP_SUBCOMMAND_WRITE_I1
|
||||
* max supported value, clamp it to the command's max (U10.6 format).
|
||||
* This is to avoid truncation during uval calculation below and ensure the valid power
|
||||
* limit is sent for pcode which would clamp it to card-supported value.
|
||||
*/
|
||||
max_crit_power_curr = (POWER_SETUP_I1_DATA_MASK >> POWER_SETUP_I1_SHIFT) * scale_factor;
|
||||
if (value > max_crit_power_curr) {
|
||||
value = max_crit_power_curr;
|
||||
drm_info(&hwmon->xe->drm,
|
||||
"Power limit clamped as selected exceeds channel %d limit\n",
|
||||
channel);
|
||||
}
|
||||
uval = DIV_ROUND_CLOSEST_ULL(value << POWER_SETUP_I1_SHIFT, scale_factor);
|
||||
ret = xe_hwmon_pcode_write_i1(hwmon, uval);
|
||||
|
||||
|
|
|
|||
|
|
@ -1820,15 +1820,19 @@ int xe_migrate_access_memory(struct xe_migrate *m, struct xe_bo *bo,
|
|||
if (!IS_ALIGNED(len, XE_CACHELINE_BYTES) ||
|
||||
!IS_ALIGNED((unsigned long)buf + offset, XE_CACHELINE_BYTES)) {
|
||||
int buf_offset = 0;
|
||||
void *bounce;
|
||||
int err;
|
||||
|
||||
BUILD_BUG_ON(!is_power_of_2(XE_CACHELINE_BYTES));
|
||||
bounce = kmalloc(XE_CACHELINE_BYTES, GFP_KERNEL);
|
||||
if (!bounce)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* Less than ideal for large unaligned access but this should be
|
||||
* fairly rare, can fixup if this becomes common.
|
||||
*/
|
||||
do {
|
||||
u8 bounce[XE_CACHELINE_BYTES];
|
||||
void *ptr = (void *)bounce;
|
||||
int err;
|
||||
int copy_bytes = min_t(int, bytes_left,
|
||||
XE_CACHELINE_BYTES -
|
||||
(offset & XE_CACHELINE_MASK));
|
||||
|
|
@ -1837,22 +1841,22 @@ int xe_migrate_access_memory(struct xe_migrate *m, struct xe_bo *bo,
|
|||
err = xe_migrate_access_memory(m, bo,
|
||||
offset &
|
||||
~XE_CACHELINE_MASK,
|
||||
(void *)ptr,
|
||||
sizeof(bounce), 0);
|
||||
bounce,
|
||||
XE_CACHELINE_BYTES, 0);
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
|
||||
if (write) {
|
||||
memcpy(ptr + ptr_offset, buf + buf_offset, copy_bytes);
|
||||
memcpy(bounce + ptr_offset, buf + buf_offset, copy_bytes);
|
||||
|
||||
err = xe_migrate_access_memory(m, bo,
|
||||
offset & ~XE_CACHELINE_MASK,
|
||||
(void *)ptr,
|
||||
sizeof(bounce), write);
|
||||
bounce,
|
||||
XE_CACHELINE_BYTES, write);
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
} else {
|
||||
memcpy(buf + buf_offset, ptr + ptr_offset,
|
||||
memcpy(buf + buf_offset, bounce + ptr_offset,
|
||||
copy_bytes);
|
||||
}
|
||||
|
||||
|
|
@ -1861,7 +1865,8 @@ int xe_migrate_access_memory(struct xe_migrate *m, struct xe_bo *bo,
|
|||
offset += copy_bytes;
|
||||
} while (bytes_left);
|
||||
|
||||
return 0;
|
||||
kfree(bounce);
|
||||
return err;
|
||||
}
|
||||
|
||||
dma_addr = xe_migrate_dma_map(xe, buf, len + page_offset, write);
|
||||
|
|
@ -1882,8 +1887,11 @@ int xe_migrate_access_memory(struct xe_migrate *m, struct xe_bo *bo,
|
|||
else
|
||||
current_bytes = min_t(int, bytes_left, cursor.size);
|
||||
|
||||
if (fence)
|
||||
dma_fence_put(fence);
|
||||
if (current_bytes & ~PAGE_MASK) {
|
||||
int pitch = 4;
|
||||
|
||||
current_bytes = min_t(int, current_bytes, S16_MAX * pitch);
|
||||
}
|
||||
|
||||
__fence = xe_migrate_vram(m, current_bytes,
|
||||
(unsigned long)buf & ~PAGE_MASK,
|
||||
|
|
@ -1892,11 +1900,15 @@ int xe_migrate_access_memory(struct xe_migrate *m, struct xe_bo *bo,
|
|||
XE_MIGRATE_COPY_TO_VRAM :
|
||||
XE_MIGRATE_COPY_TO_SRAM);
|
||||
if (IS_ERR(__fence)) {
|
||||
if (fence)
|
||||
if (fence) {
|
||||
dma_fence_wait(fence, false);
|
||||
dma_fence_put(fence);
|
||||
}
|
||||
fence = __fence;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
dma_fence_put(fence);
|
||||
fence = __fence;
|
||||
|
||||
buf += current_bytes;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,10 @@
|
|||
* Copyright © 2023-2024 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include "regs/xe_bars.h"
|
||||
#include "xe_assert.h"
|
||||
#include "xe_device.h"
|
||||
#include "xe_gt_sriov_pf_config.h"
|
||||
|
|
@ -128,6 +132,18 @@ static void pf_engine_activity_stats(struct xe_device *xe, unsigned int num_vfs,
|
|||
}
|
||||
}
|
||||
|
||||
static int resize_vf_vram_bar(struct xe_device *xe, int num_vfs)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
|
||||
u32 sizes;
|
||||
|
||||
sizes = pci_iov_vf_bar_get_sizes(pdev, VF_LMEM_BAR, num_vfs);
|
||||
if (!sizes)
|
||||
return 0;
|
||||
|
||||
return pci_iov_vf_bar_set_size(pdev, VF_LMEM_BAR, __fls(sizes));
|
||||
}
|
||||
|
||||
static int pf_enable_vfs(struct xe_device *xe, int num_vfs)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
|
||||
|
|
@ -158,6 +174,12 @@ static int pf_enable_vfs(struct xe_device *xe, int num_vfs)
|
|||
if (err < 0)
|
||||
goto failed;
|
||||
|
||||
if (IS_DGFX(xe)) {
|
||||
err = resize_vf_vram_bar(xe, num_vfs);
|
||||
if (err)
|
||||
xe_sriov_info(xe, "Failed to set VF LMEM BAR size: %d\n", err);
|
||||
}
|
||||
|
||||
err = pci_enable_sriov(pdev, num_vfs);
|
||||
if (err < 0)
|
||||
goto failed;
|
||||
|
|
|
|||
|
|
@ -54,10 +54,10 @@ xe_shrinker_mod_pages(struct xe_shrinker *shrinker, long shrinkable, long purgea
|
|||
write_unlock(&shrinker->lock);
|
||||
}
|
||||
|
||||
static s64 xe_shrinker_walk(struct xe_device *xe,
|
||||
struct ttm_operation_ctx *ctx,
|
||||
const struct xe_bo_shrink_flags flags,
|
||||
unsigned long to_scan, unsigned long *scanned)
|
||||
static s64 __xe_shrinker_walk(struct xe_device *xe,
|
||||
struct ttm_operation_ctx *ctx,
|
||||
const struct xe_bo_shrink_flags flags,
|
||||
unsigned long to_scan, unsigned long *scanned)
|
||||
{
|
||||
unsigned int mem_type;
|
||||
s64 freed = 0, lret;
|
||||
|
|
@ -93,6 +93,48 @@ static s64 xe_shrinker_walk(struct xe_device *xe,
|
|||
return freed;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try shrinking idle objects without writeback first, then if not sufficient,
|
||||
* try also non-idle objects and finally if that's not sufficient either,
|
||||
* add writeback. This avoids stalls and explicit writebacks with light or
|
||||
* moderate memory pressure.
|
||||
*/
|
||||
static s64 xe_shrinker_walk(struct xe_device *xe,
|
||||
struct ttm_operation_ctx *ctx,
|
||||
const struct xe_bo_shrink_flags flags,
|
||||
unsigned long to_scan, unsigned long *scanned)
|
||||
{
|
||||
bool no_wait_gpu = true;
|
||||
struct xe_bo_shrink_flags save_flags = flags;
|
||||
s64 lret, freed;
|
||||
|
||||
swap(no_wait_gpu, ctx->no_wait_gpu);
|
||||
save_flags.writeback = false;
|
||||
lret = __xe_shrinker_walk(xe, ctx, save_flags, to_scan, scanned);
|
||||
swap(no_wait_gpu, ctx->no_wait_gpu);
|
||||
if (lret < 0 || *scanned >= to_scan)
|
||||
return lret;
|
||||
|
||||
freed = lret;
|
||||
if (!ctx->no_wait_gpu) {
|
||||
lret = __xe_shrinker_walk(xe, ctx, save_flags, to_scan, scanned);
|
||||
if (lret < 0)
|
||||
return lret;
|
||||
freed += lret;
|
||||
if (*scanned >= to_scan)
|
||||
return freed;
|
||||
}
|
||||
|
||||
if (flags.writeback) {
|
||||
lret = __xe_shrinker_walk(xe, ctx, flags, to_scan, scanned);
|
||||
if (lret < 0)
|
||||
return lret;
|
||||
freed += lret;
|
||||
}
|
||||
|
||||
return freed;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
xe_shrinker_count(struct shrinker *shrink, struct shrink_control *sc)
|
||||
{
|
||||
|
|
@ -199,6 +241,7 @@ static unsigned long xe_shrinker_scan(struct shrinker *shrink, struct shrink_con
|
|||
runtime_pm = xe_shrinker_runtime_pm_get(shrinker, true, 0, can_backup);
|
||||
|
||||
shrink_flags.purge = false;
|
||||
|
||||
lret = xe_shrinker_walk(shrinker->xe, &ctx, shrink_flags,
|
||||
nr_to_scan, &nr_scanned);
|
||||
if (lret >= 0)
|
||||
|
|
|
|||
|
|
@ -866,13 +866,61 @@ struct drm_bridge_funcs {
|
|||
struct drm_connector *connector,
|
||||
bool enable, int direction);
|
||||
|
||||
/**
|
||||
* @hdmi_cec_init:
|
||||
*
|
||||
* Initialize CEC part of the bridge.
|
||||
*
|
||||
* This callback is optional, it can be implemented by bridges that
|
||||
* set the @DRM_BRIDGE_OP_HDMI_CEC_ADAPTER flag in their
|
||||
* &drm_bridge->ops.
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success, a negative error code otherwise
|
||||
*/
|
||||
int (*hdmi_cec_init)(struct drm_bridge *bridge,
|
||||
struct drm_connector *connector);
|
||||
|
||||
/**
|
||||
* @hdmi_cec_enable:
|
||||
*
|
||||
* Enable or disable the CEC adapter inside the bridge.
|
||||
*
|
||||
* This callback is optional, it can be implemented by bridges that
|
||||
* set the @DRM_BRIDGE_OP_HDMI_CEC_ADAPTER flag in their
|
||||
* &drm_bridge->ops.
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success, a negative error code otherwise
|
||||
*/
|
||||
int (*hdmi_cec_enable)(struct drm_bridge *bridge, bool enable);
|
||||
|
||||
/**
|
||||
* @hdmi_cec_log_addr:
|
||||
*
|
||||
* Set the logical address of the CEC adapter inside the bridge.
|
||||
*
|
||||
* This callback is optional, it can be implemented by bridges that
|
||||
* set the @DRM_BRIDGE_OP_HDMI_CEC_ADAPTER flag in their
|
||||
* &drm_bridge->ops.
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success, a negative error code otherwise
|
||||
*/
|
||||
int (*hdmi_cec_log_addr)(struct drm_bridge *bridge, u8 logical_addr);
|
||||
|
||||
/**
|
||||
* @hdmi_cec_transmit:
|
||||
*
|
||||
* Transmit the message using the CEC adapter inside the bridge.
|
||||
*
|
||||
* This callback is optional, it can be implemented by bridges that
|
||||
* set the @DRM_BRIDGE_OP_HDMI_CEC_ADAPTER flag in their
|
||||
* &drm_bridge->ops.
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success, a negative error code otherwise
|
||||
*/
|
||||
int (*hdmi_cec_transmit)(struct drm_bridge *bridge, u8 attempts,
|
||||
u32 signal_free_time, struct cec_msg *msg);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue