Skip to content

Commit

Permalink
Merge tag 'drm-fixes-2021-06-04-1' of git://anongit.freedesktop.org/d…
Browse files Browse the repository at this point in the history
…rm/drm

Pull drm fixes from Dave Airlie:
 "Two big regression reverts in here, one for fbdev and one i915.
  Otherwise it's mostly amdgpu display fixes, and tegra fixes.

  fb:
   - revert broken fb_defio patch

  amdgpu:
   - Display fixes
   - FRU EEPROM error handling fix
   - RAS fix
   - PSP fix
   - Releasing pinned BO fix

  i915:
   - Revert conversion to io_mapping_map_user() which lead to BUG_ON()
   - Fix check for error valued returns in a selftest

  tegra:
   - SOR power domain race condition fix
   - build warning fix
   - runtime pm ref leak fix
   - modifier fix"

* tag 'drm-fixes-2021-06-04-1' of git://anongit.freedesktop.org/drm/drm:
  amd/display: convert DRM_DEBUG_ATOMIC to drm_dbg_atomic
  drm/amdgpu: make sure we unpin the UVD BO
  drm/amd/amdgpu:save psp ring wptr to avoid attack
  drm/amd/display: Fix potential memory leak in DMUB hw_init
  drm/amdgpu: Don't query CE and UE errors
  drm/amd/display: Fix overlay validation by considering cursors
  drm/amdgpu: refine amdgpu_fru_get_product_info
  drm/amdgpu: add judgement for dc support
  drm/amd/display: Fix GPU scaling regression by FS video support
  drm/amd/display: Allow bandwidth validation for 0 streams.
  Revert "i915: use io_mapping_map_user"
  drm/i915/selftests: Fix return value check in live_breadcrumbs_smoketest()
  Revert "fb_defio: Remove custom address_space_operations"
  drm/tegra: Correct DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT
  drm/tegra: sor: Fix AUX device reference leak
  drm/tegra: Get ref for DP AUX channel, not its ddc adapter
  drm/tegra: Fix shift overflow in tegra_shared_plane_atomic_update
  drm/tegra: sor: Fully initialize SOR before registration
  gpu: host1x: Split up client initalization and registration
  drm/tegra: sor: Do not leak runtime PM reference
  • Loading branch information
Linus Torvalds committed Jun 4, 2021
2 parents f88cd3f + 37e2f2e commit 3a3c5ab
Show file tree
Hide file tree
Showing 22 changed files with 240 additions and 99 deletions.
16 changes: 0 additions & 16 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,6 @@ static int amdgpu_ctx_query2(struct amdgpu_device *adev,
{
struct amdgpu_ctx *ctx;
struct amdgpu_ctx_mgr *mgr;
unsigned long ras_counter;

if (!fpriv)
return -EINVAL;
Expand All @@ -362,21 +361,6 @@ static int amdgpu_ctx_query2(struct amdgpu_device *adev,
if (atomic_read(&ctx->guilty))
out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_GUILTY;

/*query ue count*/
ras_counter = amdgpu_ras_query_error_count(adev, false);
/*ras counter is monotonic increasing*/
if (ras_counter != ctx->ras_counter_ue) {
out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_RAS_UE;
ctx->ras_counter_ue = ras_counter;
}

/*query ce count*/
ras_counter = amdgpu_ras_query_error_count(adev, true);
if (ras_counter != ctx->ras_counter_ce) {
out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_RAS_CE;
ctx->ras_counter_ce = ras_counter;
}

mutex_unlock(&mgr->lock);
return 0;
}
Expand Down
4 changes: 3 additions & 1 deletion drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -3118,7 +3118,9 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type)
*/
bool amdgpu_device_has_dc_support(struct amdgpu_device *adev)
{
if (amdgpu_sriov_vf(adev) || adev->enable_virtual_display)
if (amdgpu_sriov_vf(adev) ||
adev->enable_virtual_display ||
(adev->harvest_ip_mask & AMD_HARVEST_IP_DMU_MASK))
return false;

return amdgpu_device_asic_has_dc_support(adev->asic_type);
Expand Down
42 changes: 23 additions & 19 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,15 +101,16 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr,
int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
{
unsigned char buff[34];
int addrptr = 0, size = 0;
int addrptr, size;
int len;

if (!is_fru_eeprom_supported(adev))
return 0;

/* If algo exists, it means that the i2c_adapter's initialized */
if (!adev->pm.smu_i2c.algo) {
DRM_WARN("Cannot access FRU, EEPROM accessor not initialized");
return 0;
return -ENODEV;
}

/* There's a lot of repetition here. This is due to the FRU having
Expand All @@ -128,7 +129,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
size = amdgpu_fru_read_eeprom(adev, addrptr, buff);
if (size < 1) {
DRM_ERROR("Failed to read FRU Manufacturer, ret:%d", size);
return size;
return -EINVAL;
}

/* Increment the addrptr by the size of the field, and 1 due to the
Expand All @@ -138,62 +139,65 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
size = amdgpu_fru_read_eeprom(adev, addrptr, buff);
if (size < 1) {
DRM_ERROR("Failed to read FRU product name, ret:%d", size);
return size;
return -EINVAL;
}

len = size;
/* Product name should only be 32 characters. Any more,
* and something could be wrong. Cap it at 32 to be safe
*/
if (size > 32) {
if (len >= sizeof(adev->product_name)) {
DRM_WARN("FRU Product Number is larger than 32 characters. This is likely a mistake");
size = 32;
len = sizeof(adev->product_name) - 1;
}
/* Start at 2 due to buff using fields 0 and 1 for the address */
memcpy(adev->product_name, &buff[2], size);
adev->product_name[size] = '\0';
memcpy(adev->product_name, &buff[2], len);
adev->product_name[len] = '\0';

addrptr += size + 1;
size = amdgpu_fru_read_eeprom(adev, addrptr, buff);
if (size < 1) {
DRM_ERROR("Failed to read FRU product number, ret:%d", size);
return size;
return -EINVAL;
}

len = size;
/* Product number should only be 16 characters. Any more,
* and something could be wrong. Cap it at 16 to be safe
*/
if (size > 16) {
if (len >= sizeof(adev->product_number)) {
DRM_WARN("FRU Product Number is larger than 16 characters. This is likely a mistake");
size = 16;
len = sizeof(adev->product_number) - 1;
}
memcpy(adev->product_number, &buff[2], size);
adev->product_number[size] = '\0';
memcpy(adev->product_number, &buff[2], len);
adev->product_number[len] = '\0';

addrptr += size + 1;
size = amdgpu_fru_read_eeprom(adev, addrptr, buff);

if (size < 1) {
DRM_ERROR("Failed to read FRU product version, ret:%d", size);
return size;
return -EINVAL;
}

addrptr += size + 1;
size = amdgpu_fru_read_eeprom(adev, addrptr, buff);

if (size < 1) {
DRM_ERROR("Failed to read FRU serial number, ret:%d", size);
return size;
return -EINVAL;
}

len = size;
/* Serial number should only be 16 characters. Any more,
* and something could be wrong. Cap it at 16 to be safe
*/
if (size > 16) {
if (len >= sizeof(adev->serial)) {
DRM_WARN("FRU Serial Number is larger than 16 characters. This is likely a mistake");
size = 16;
len = sizeof(adev->serial) - 1;
}
memcpy(adev->serial, &buff[2], size);
adev->serial[size] = '\0';
memcpy(adev->serial, &buff[2], len);
adev->serial[len] = '\0';

return 0;
}
1 change: 1 addition & 0 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ struct psp_ring
uint64_t ring_mem_mc_addr;
void *ring_mem_handle;
uint32_t ring_size;
uint32_t ring_wptr;
};

/* More registers may will be supported */
Expand Down
3 changes: 2 additions & 1 deletion drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,7 @@ static uint32_t psp_v11_0_ring_get_wptr(struct psp_context *psp)
struct amdgpu_device *adev = psp->adev;

if (amdgpu_sriov_vf(adev))
data = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102);
data = psp->km_ring.ring_wptr;
else
data = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67);

Expand All @@ -734,6 +734,7 @@ static void psp_v11_0_ring_set_wptr(struct psp_context *psp, uint32_t value)
if (amdgpu_sriov_vf(adev)) {
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102, value);
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101, GFX_CTRL_CMD_ID_CONSUME_CMD);
psp->km_ring.ring_wptr = value;
} else
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67, value);
}
Expand Down
3 changes: 2 additions & 1 deletion drivers/gpu/drm/amd/amdgpu/psp_v3_1.c
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ static uint32_t psp_v3_1_ring_get_wptr(struct psp_context *psp)
struct amdgpu_device *adev = psp->adev;

if (amdgpu_sriov_vf(adev))
data = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102);
data = psp->km_ring.ring_wptr;
else
data = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67);
return data;
Expand All @@ -394,6 +394,7 @@ static void psp_v3_1_ring_set_wptr(struct psp_context *psp, uint32_t value)
/* send interrupt to PSP for SRIOV ring write pointer update */
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101,
GFX_CTRL_CMD_ID_CONSUME_CMD);
psp->km_ring.ring_wptr = value;
} else
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67, value);
}
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,7 @@ static int uvd_v6_0_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout)

error:
dma_fence_put(fence);
amdgpu_bo_unpin(bo);
amdgpu_bo_unreserve(bo);
amdgpu_bo_unref(&bo);
return r;
Expand Down
30 changes: 19 additions & 11 deletions drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
Original file line number Diff line number Diff line change
Expand Up @@ -925,7 +925,8 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev)
abm->dmcu_is_running = dmcu->funcs->is_dmcu_initialized(dmcu);
}

adev->dm.dc->ctx->dmub_srv = dc_dmub_srv_create(adev->dm.dc, dmub_srv);
if (!adev->dm.dc->ctx->dmub_srv)
adev->dm.dc->ctx->dmub_srv = dc_dmub_srv_create(adev->dm.dc, dmub_srv);
if (!adev->dm.dc->ctx->dmub_srv) {
DRM_ERROR("Couldn't allocate DC DMUB server!\n");
return -ENOMEM;
Expand Down Expand Up @@ -1954,7 +1955,6 @@ static int dm_suspend(void *handle)

amdgpu_dm_irq_suspend(adev);


dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D3);

return 0;
Expand Down Expand Up @@ -5500,7 +5500,8 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
struct drm_display_mode saved_mode;
struct drm_display_mode *freesync_mode = NULL;
bool native_mode_found = false;
bool recalculate_timing = dm_state ? (dm_state->scaling != RMX_OFF) : false;
bool recalculate_timing = false;
bool scale = dm_state ? (dm_state->scaling != RMX_OFF) : false;
int mode_refresh;
int preferred_refresh = 0;
#if defined(CONFIG_DRM_AMD_DC_DCN)
Expand Down Expand Up @@ -5563,19 +5564,18 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
*/
DRM_DEBUG_DRIVER("No preferred mode found\n");
} else {
recalculate_timing |= amdgpu_freesync_vid_mode &&
recalculate_timing = amdgpu_freesync_vid_mode &&
is_freesync_video_mode(&mode, aconnector);
if (recalculate_timing) {
freesync_mode = get_highest_refresh_rate_mode(aconnector, false);
saved_mode = mode;
mode = *freesync_mode;
} else {
decide_crtc_timing_for_drm_display_mode(
&mode, preferred_mode,
dm_state ? (dm_state->scaling != RMX_OFF) : false);
}
&mode, preferred_mode, scale);

preferred_refresh = drm_mode_vrefresh(preferred_mode);
preferred_refresh = drm_mode_vrefresh(preferred_mode);
}
}

if (recalculate_timing)
Expand All @@ -5587,7 +5587,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
* If scaling is enabled and refresh rate didn't change
* we copy the vic and polarities of the old timings
*/
if (!recalculate_timing || mode_refresh != preferred_refresh)
if (!scale || mode_refresh != preferred_refresh)
fill_stream_properties_from_drm_display_mode(
stream, &mode, &aconnector->base, con_state, NULL,
requested_bpc);
Expand Down Expand Up @@ -9854,7 +9854,7 @@ static int dm_check_crtc_cursor(struct drm_atomic_state *state,

if (cursor_scale_w != primary_scale_w ||
cursor_scale_h != primary_scale_h) {
DRM_DEBUG_ATOMIC("Cursor plane scaling doesn't match primary plane\n");
drm_dbg_atomic(crtc->dev, "Cursor plane scaling doesn't match primary plane\n");
return -EINVAL;
}

Expand Down Expand Up @@ -9891,7 +9891,7 @@ static int validate_overlay(struct drm_atomic_state *state)
int i;
struct drm_plane *plane;
struct drm_plane_state *old_plane_state, *new_plane_state;
struct drm_plane_state *primary_state, *overlay_state = NULL;
struct drm_plane_state *primary_state, *cursor_state, *overlay_state = NULL;

/* Check if primary plane is contained inside overlay */
for_each_oldnew_plane_in_state_reverse(state, plane, old_plane_state, new_plane_state, i) {
Expand Down Expand Up @@ -9921,6 +9921,14 @@ static int validate_overlay(struct drm_atomic_state *state)
if (!primary_state->crtc)
return 0;

/* check if cursor plane is enabled */
cursor_state = drm_atomic_get_plane_state(state, overlay_state->crtc->cursor);
if (IS_ERR(cursor_state))
return PTR_ERR(cursor_state);

if (drm_atomic_plane_disabling(plane->state, cursor_state))
return 0;

/* Perform the bounds check to ensure the overlay plane covers the primary */
if (primary_state->crtc_x < overlay_state->crtc_x ||
primary_state->crtc_y < overlay_state->crtc_y ||
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
Original file line number Diff line number Diff line change
Expand Up @@ -3236,7 +3236,7 @@ static noinline bool dcn20_validate_bandwidth_fp(struct dc *dc,
voltage_supported = dcn20_validate_bandwidth_internal(dc, context, false);
dummy_pstate_supported = context->bw_ctx.bw.dcn.clk.p_state_change_support;

if (voltage_supported && dummy_pstate_supported) {
if (voltage_supported && (dummy_pstate_supported || !(context->stream_count))) {
context->bw_ctx.bw.dcn.clk.p_state_change_support = false;
goto restore_dml_state;
}
Expand Down
1 change: 0 additions & 1 deletion drivers/gpu/drm/i915/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ config DRM_I915
select INPUT if ACPI
select ACPI_VIDEO if ACPI
select ACPI_BUTTON if ACPI
select IO_MAPPING
select SYNC_FILE
select IOSF_MBI
select CRC32
Expand Down
9 changes: 5 additions & 4 deletions drivers/gpu/drm/i915/gem/i915_gem_mman.c
Original file line number Diff line number Diff line change
Expand Up @@ -367,10 +367,11 @@ static vm_fault_t vm_fault_gtt(struct vm_fault *vmf)
goto err_unpin;

/* Finally, remap it using the new GTT offset */
ret = io_mapping_map_user(&ggtt->iomap, area, area->vm_start +
(vma->ggtt_view.partial.offset << PAGE_SHIFT),
(ggtt->gmadr.start + vma->node.start) >> PAGE_SHIFT,
min_t(u64, vma->size, area->vm_end - area->vm_start));
ret = remap_io_mapping(area,
area->vm_start + (vma->ggtt_view.partial.offset << PAGE_SHIFT),
(ggtt->gmadr.start + vma->node.start) >> PAGE_SHIFT,
min_t(u64, vma->size, area->vm_end - area->vm_start),
&ggtt->iomap);
if (ret)
goto err_fence;

Expand Down
3 changes: 3 additions & 0 deletions drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -1905,6 +1905,9 @@ int i915_reg_read_ioctl(struct drm_device *dev, void *data,
struct drm_file *file);

/* i915_mm.c */
int remap_io_mapping(struct vm_area_struct *vma,
unsigned long addr, unsigned long pfn, unsigned long size,
struct io_mapping *iomap);
int remap_io_sg(struct vm_area_struct *vma,
unsigned long addr, unsigned long size,
struct scatterlist *sgl, resource_size_t iobase);
Expand Down
44 changes: 44 additions & 0 deletions drivers/gpu/drm/i915/i915_mm.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@ struct remap_pfn {
resource_size_t iobase;
};

static int remap_pfn(pte_t *pte, unsigned long addr, void *data)
{
struct remap_pfn *r = data;

/* Special PTE are not associated with any struct page */
set_pte_at(r->mm, addr, pte, pte_mkspecial(pfn_pte(r->pfn, r->prot)));
r->pfn++;

return 0;
}

#define use_dma(io) ((io) != -1)

static inline unsigned long sgt_pfn(const struct remap_pfn *r)
Expand Down Expand Up @@ -66,7 +77,40 @@ static int remap_sg(pte_t *pte, unsigned long addr, void *data)
return 0;
}

/**
* remap_io_mapping - remap an IO mapping to userspace
* @vma: user vma to map to
* @addr: target user address to start at
* @pfn: physical address of kernel memory
* @size: size of map area
* @iomap: the source io_mapping
*
* Note: this is only safe if the mm semaphore is held when called.
*/
int remap_io_mapping(struct vm_area_struct *vma,
unsigned long addr, unsigned long pfn, unsigned long size,
struct io_mapping *iomap)
{
struct remap_pfn r;
int err;

#define EXPECTED_FLAGS (VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP)
GEM_BUG_ON((vma->vm_flags & EXPECTED_FLAGS) != EXPECTED_FLAGS);

/* We rely on prevalidation of the io-mapping to skip track_pfn(). */
r.mm = vma->vm_mm;
r.pfn = pfn;
r.prot = __pgprot((pgprot_val(iomap->prot) & _PAGE_CACHE_MASK) |
(pgprot_val(vma->vm_page_prot) & ~_PAGE_CACHE_MASK));

err = apply_to_page_range(r.mm, addr, size, remap_pfn, &r);
if (unlikely(err)) {
zap_vma_ptes(vma, addr, (r.pfn - pfn) << PAGE_SHIFT);
return err;
}

return 0;
}

/**
* remap_io_sg - remap an IO mapping to userspace
Expand Down
Loading

0 comments on commit 3a3c5ab

Please sign in to comment.