Skip to content

Commit

Permalink
Merge tag 'drm-next-2021-02-26' of git://anongit.freedesktop.org/drm/drm
Browse files Browse the repository at this point in the history
Pull more drm updates from Dave Airlie:
 "This is mostly fixes but I missed msm-next pull last week. It's been
  in drm-next.

  Otherwise it's a selection of i915, amdgpu and misc fixes, one TTM
  memory leak, nothing really major stands out otherwise.

  core:
   - vblank fence timing improvements

  dma-buf:
   - improve error handling

  ttm:
   - memory leak fix

  msm:
   - a6xx speedbin support
   - a508, a509, a512 support
   - various a5xx fixes
   - various dpu fixes
   - qseed3lite support for sm8250
   - dsi fix for msm8994
   - mdp5 fix for framerate bug with cmd mode panels
   - a6xx GMU OOB race fixes that were showing up in CI
   - various addition and removal of semicolons
   - gem submit fix for legacy userspace relocs path

  amdgpu:
   - clang warning fix
   - S0ix platform shutdown/poweroff fix
   - misc display fixes

  i915:
   - color format fix
   - -Wuninitialised reenabled
   - GVT ww locking, cmd parser fixes

  atyfb:
   - fix build

  rockchip:
   - AFBC modifier fix"

* tag 'drm-next-2021-02-26' of git://anongit.freedesktop.org/drm/drm: (60 commits)
  drm/panel: kd35t133: allow using non-continuous dsi clock
  drm/rockchip: Require the YTR modifier for AFBC
  drm/ttm: Fix a memory leak
  drm/drm_vblank: set the dma-fence timestamp during send_vblank_event
  dma-fence: allow signaling drivers to set fence timestamp
  dma-buf: heaps: Rework heap allocation hooks to return struct dma_buf instead of fd
  dma-buf: system_heap: Make sure to return an error if we abort
  drm/amd/display: Fix system hang after multiple hotplugs (v3)
  drm/amdgpu: fix shutdown and poweroff process failed with s0ix
  drm/i915: Nuke INTEL_OUTPUT_FORMAT_INVALID
  drm/i915: Enable -Wuninitialized
  drm/amd/display: Remove Assert from dcn10_get_dig_frontend
  drm/amd/display: Add vupdate_no_lock interrupts for DCN2.1
  Revert "drm/amd/display: reuse current context instead of recreating one"
  drm/amd/pm/swsmu: Avoid using structure_size uninitialized in smu_cmn_init_soft_gpu_metrics
  fbdev: atyfb: add stubs for aty_{ld,st}_lcd()
  drm/i915/gvt: Introduce per object locking in GVT scheduler.
  drm/i915/gvt: Purge dev_priv->gt
  drm/i915/gvt: Parse default state to update reg whitelist
  dt-bindings: dp-connector: Drop maxItems from -supply
  ...
  • Loading branch information
torvalds committed Feb 25, 2021
2 parents 5ad3dba + d153e8c commit fdce296
Show file tree
Hide file tree
Showing 68 changed files with 1,223 additions and 423 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ properties:

dp-pwr-supply:
description: Power supply for the DP_PWR pin
maxItems: 1

port:
$ref: /schemas/graph.yaml#/properties/port
Expand Down
70 changes: 63 additions & 7 deletions drivers/dma-buf/dma-fence.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,22 +312,25 @@ void __dma_fence_might_wait(void)


/**
* dma_fence_signal_locked - signal completion of a fence
* dma_fence_signal_timestamp_locked - signal completion of a fence
* @fence: the fence to signal
* @timestamp: fence signal timestamp in kernel's CLOCK_MONOTONIC time domain
*
* Signal completion for software callbacks on a fence, this will unblock
* dma_fence_wait() calls and run all the callbacks added with
* dma_fence_add_callback(). Can be called multiple times, but since a fence
* can only go from the unsignaled to the signaled state and not back, it will
* only be effective the first time.
* only be effective the first time. Set the timestamp provided as the fence
* signal timestamp.
*
* Unlike dma_fence_signal(), this function must be called with &dma_fence.lock
* held.
* Unlike dma_fence_signal_timestamp(), this function must be called with
* &dma_fence.lock held.
*
* Returns 0 on success and a negative error value when @fence has been
* signalled already.
*/
int dma_fence_signal_locked(struct dma_fence *fence)
int dma_fence_signal_timestamp_locked(struct dma_fence *fence,
ktime_t timestamp)
{
struct dma_fence_cb *cur, *tmp;
struct list_head cb_list;
Expand All @@ -341,7 +344,7 @@ int dma_fence_signal_locked(struct dma_fence *fence)
/* Stash the cb_list before replacing it with the timestamp */
list_replace(&fence->cb_list, &cb_list);

fence->timestamp = ktime_get();
fence->timestamp = timestamp;
set_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags);
trace_dma_fence_signaled(fence);

Expand All @@ -352,6 +355,59 @@ int dma_fence_signal_locked(struct dma_fence *fence)

return 0;
}
EXPORT_SYMBOL(dma_fence_signal_timestamp_locked);

/**
* dma_fence_signal_timestamp - signal completion of a fence
* @fence: the fence to signal
* @timestamp: fence signal timestamp in kernel's CLOCK_MONOTONIC time domain
*
* Signal completion for software callbacks on a fence, this will unblock
* dma_fence_wait() calls and run all the callbacks added with
* dma_fence_add_callback(). Can be called multiple times, but since a fence
* can only go from the unsignaled to the signaled state and not back, it will
* only be effective the first time. Set the timestamp provided as the fence
* signal timestamp.
*
* Returns 0 on success and a negative error value when @fence has been
* signalled already.
*/
int dma_fence_signal_timestamp(struct dma_fence *fence, ktime_t timestamp)
{
unsigned long flags;
int ret;

if (!fence)
return -EINVAL;

spin_lock_irqsave(fence->lock, flags);
ret = dma_fence_signal_timestamp_locked(fence, timestamp);
spin_unlock_irqrestore(fence->lock, flags);

return ret;
}
EXPORT_SYMBOL(dma_fence_signal_timestamp);

/**
* dma_fence_signal_locked - signal completion of a fence
* @fence: the fence to signal
*
* Signal completion for software callbacks on a fence, this will unblock
* dma_fence_wait() calls and run all the callbacks added with
* dma_fence_add_callback(). Can be called multiple times, but since a fence
* can only go from the unsignaled to the signaled state and not back, it will
* only be effective the first time.
*
* Unlike dma_fence_signal(), this function must be called with &dma_fence.lock
* held.
*
* Returns 0 on success and a negative error value when @fence has been
* signalled already.
*/
int dma_fence_signal_locked(struct dma_fence *fence)
{
return dma_fence_signal_timestamp_locked(fence, ktime_get());
}
EXPORT_SYMBOL(dma_fence_signal_locked);

/**
Expand Down Expand Up @@ -379,7 +435,7 @@ int dma_fence_signal(struct dma_fence *fence)
tmp = dma_fence_begin_signalling();

spin_lock_irqsave(fence->lock, flags);
ret = dma_fence_signal_locked(fence);
ret = dma_fence_signal_timestamp_locked(fence, ktime_get());
spin_unlock_irqrestore(fence->lock, flags);

dma_fence_end_signalling(tmp);
Expand Down
14 changes: 13 additions & 1 deletion drivers/dma-buf/dma-heap.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ static int dma_heap_buffer_alloc(struct dma_heap *heap, size_t len,
unsigned int fd_flags,
unsigned int heap_flags)
{
struct dma_buf *dmabuf;
int fd;

/*
* Allocations from all heaps have to begin
* and end on page boundaries.
Expand All @@ -60,7 +63,16 @@ static int dma_heap_buffer_alloc(struct dma_heap *heap, size_t len,
if (!len)
return -EINVAL;

return heap->ops->allocate(heap, len, fd_flags, heap_flags);
dmabuf = heap->ops->allocate(heap, len, fd_flags, heap_flags);
if (IS_ERR(dmabuf))
return PTR_ERR(dmabuf);

fd = dma_buf_fd(dmabuf, fd_flags);
if (fd < 0) {
dma_buf_put(dmabuf);
/* just return, as put will call release and that will free */
}
return fd;
}

static int dma_heap_open(struct inode *inode, struct file *file)
Expand Down
22 changes: 7 additions & 15 deletions drivers/dma-buf/heaps/cma_heap.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,10 +271,10 @@ static const struct dma_buf_ops cma_heap_buf_ops = {
.release = cma_heap_dma_buf_release,
};

static int cma_heap_allocate(struct dma_heap *heap,
unsigned long len,
unsigned long fd_flags,
unsigned long heap_flags)
static struct dma_buf *cma_heap_allocate(struct dma_heap *heap,
unsigned long len,
unsigned long fd_flags,
unsigned long heap_flags)
{
struct cma_heap *cma_heap = dma_heap_get_drvdata(heap);
struct cma_heap_buffer *buffer;
Expand All @@ -289,7 +289,7 @@ static int cma_heap_allocate(struct dma_heap *heap,

buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
if (!buffer)
return -ENOMEM;
return ERR_PTR(-ENOMEM);

INIT_LIST_HEAD(&buffer->attachments);
mutex_init(&buffer->lock);
Expand Down Expand Up @@ -348,15 +348,7 @@ static int cma_heap_allocate(struct dma_heap *heap,
ret = PTR_ERR(dmabuf);
goto free_pages;
}

ret = dma_buf_fd(dmabuf, fd_flags);
if (ret < 0) {
dma_buf_put(dmabuf);
/* just return, as put will call release and that will free */
return ret;
}

return ret;
return dmabuf;

free_pages:
kfree(buffer->pages);
Expand All @@ -365,7 +357,7 @@ static int cma_heap_allocate(struct dma_heap *heap,
free_buffer:
kfree(buffer);

return ret;
return ERR_PTR(ret);
}

static const struct dma_heap_ops cma_heap_ops = {
Expand Down
25 changes: 10 additions & 15 deletions drivers/dma-buf/heaps/system_heap.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,10 +331,10 @@ static struct page *alloc_largest_available(unsigned long size,
return NULL;
}

static int system_heap_allocate(struct dma_heap *heap,
unsigned long len,
unsigned long fd_flags,
unsigned long heap_flags)
static struct dma_buf *system_heap_allocate(struct dma_heap *heap,
unsigned long len,
unsigned long fd_flags,
unsigned long heap_flags)
{
struct system_heap_buffer *buffer;
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
Expand All @@ -349,7 +349,7 @@ static int system_heap_allocate(struct dma_heap *heap,

buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
if (!buffer)
return -ENOMEM;
return ERR_PTR(-ENOMEM);

INIT_LIST_HEAD(&buffer->attachments);
mutex_init(&buffer->lock);
Expand All @@ -363,8 +363,10 @@ static int system_heap_allocate(struct dma_heap *heap,
* Avoid trying to allocate memory if the process
* has been killed by SIGKILL
*/
if (fatal_signal_pending(current))
if (fatal_signal_pending(current)) {
ret = -EINTR;
goto free_buffer;
}

page = alloc_largest_available(size_remaining, max_order);
if (!page)
Expand Down Expand Up @@ -397,14 +399,7 @@ static int system_heap_allocate(struct dma_heap *heap,
ret = PTR_ERR(dmabuf);
goto free_pages;
}

ret = dma_buf_fd(dmabuf, fd_flags);
if (ret < 0) {
dma_buf_put(dmabuf);
/* just return, as put will call release and that will free */
return ret;
}
return ret;
return dmabuf;

free_pages:
for_each_sgtable_sg(table, sg, i) {
Expand All @@ -418,7 +413,7 @@ static int system_heap_allocate(struct dma_heap *heap,
__free_pages(page, compound_order(page));
kfree(buffer);

return ret;
return ERR_PTR(ret);
}

static const struct dma_heap_ops system_heap_ops = {
Expand Down
6 changes: 6 additions & 0 deletions drivers/gpu/drm/amd/amdgpu/amdgpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -1008,6 +1008,12 @@ struct amdgpu_device {
bool in_suspend;
bool in_hibernate;

/*
* The combination flag in_poweroff_reboot_com used to identify the poweroff
* and reboot opt in the s0i3 system-wide suspend.
*/
bool in_poweroff_reboot_com;

atomic_t in_gpu_reset;
enum pp_mp1_state mp1_state;
struct rw_semaphore reset_sem;
Expand Down
6 changes: 4 additions & 2 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -2678,7 +2678,8 @@ static int amdgpu_device_ip_suspend_phase1(struct amdgpu_device *adev)
{
int i, r;

if (!amdgpu_acpi_is_s0ix_supported(adev) || amdgpu_in_reset(adev)) {
if (adev->in_poweroff_reboot_com ||
!amdgpu_acpi_is_s0ix_supported(adev) || amdgpu_in_reset(adev)) {
amdgpu_device_set_pg_state(adev, AMD_PG_STATE_UNGATE);
amdgpu_device_set_cg_state(adev, AMD_CG_STATE_UNGATE);
}
Expand Down Expand Up @@ -3741,7 +3742,8 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)

amdgpu_fence_driver_suspend(adev);

if (!amdgpu_acpi_is_s0ix_supported(adev) || amdgpu_in_reset(adev))
if (adev->in_poweroff_reboot_com ||
!amdgpu_acpi_is_s0ix_supported(adev) || amdgpu_in_reset(adev))
r = amdgpu_device_ip_suspend_phase2(adev);
else
amdgpu_gfx_state_change_set(adev, sGpuChangeState_D3Entry);
Expand Down
9 changes: 8 additions & 1 deletion drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1270,7 +1270,9 @@ amdgpu_pci_shutdown(struct pci_dev *pdev)
*/
if (!amdgpu_passthrough(adev))
adev->mp1_state = PP_MP1_STATE_UNLOAD;
adev->in_poweroff_reboot_com = true;
amdgpu_device_ip_suspend(adev);
adev->in_poweroff_reboot_com = false;
adev->mp1_state = PP_MP1_STATE_NONE;
}

Expand Down Expand Up @@ -1312,8 +1314,13 @@ static int amdgpu_pmops_thaw(struct device *dev)
static int amdgpu_pmops_poweroff(struct device *dev)
{
struct drm_device *drm_dev = dev_get_drvdata(dev);
struct amdgpu_device *adev = drm_to_adev(drm_dev);
int r;

return amdgpu_device_suspend(drm_dev, true);
adev->in_poweroff_reboot_com = true;
r = amdgpu_device_suspend(drm_dev, true);
adev->in_poweroff_reboot_com = false;
return r;
}

static int amdgpu_pmops_restore(struct device *dev)
Expand Down
Loading

0 comments on commit fdce296

Please sign in to comment.