Merge 72a85e2b0a ("Merge tag 'spi-fix-v6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi") into android-mainline
Steps on the way to 6.2-rc1 Change-Id: I89181e6c97c38188c800ef3b7461a9e5bd83f98d Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
What: /sys/kernel/oops_count
|
||||
What: /sys/kernel/warn_count
|
||||
Date: November 2022
|
||||
KernelVersion: 6.2.0
|
||||
Contact: Linux Kernel Hardening List <linux-hardening@vger.kernel.org>
|
||||
|
||||
@@ -38,6 +38,7 @@ properties:
|
||||
- fsl,imx8mq-sai
|
||||
- fsl,imx8qm-sai
|
||||
- fsl,imx8ulp-sai
|
||||
- fsl,imx93-sai
|
||||
- fsl,vf610-sai
|
||||
|
||||
reg:
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <linux/mm.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/mmu_notifier.h>
|
||||
#include <kgd_kfd_interface.h>
|
||||
#include <drm/ttm/ttm_execbuf_util.h>
|
||||
#include "amdgpu_sync.h"
|
||||
@@ -65,6 +66,7 @@ struct kgd_mem {
|
||||
struct mutex lock;
|
||||
struct amdgpu_bo *bo;
|
||||
struct dma_buf *dmabuf;
|
||||
struct hmm_range *range;
|
||||
struct list_head attachments;
|
||||
/* protected by amdkfd_process_info.lock */
|
||||
struct ttm_validate_buffer validate_list;
|
||||
@@ -75,7 +77,7 @@ struct kgd_mem {
|
||||
|
||||
uint32_t alloc_flags;
|
||||
|
||||
atomic_t invalid;
|
||||
uint32_t invalid;
|
||||
struct amdkfd_process_info *process_info;
|
||||
|
||||
struct amdgpu_sync sync;
|
||||
@@ -131,7 +133,8 @@ struct amdkfd_process_info {
|
||||
struct amdgpu_amdkfd_fence *eviction_fence;
|
||||
|
||||
/* MMU-notifier related fields */
|
||||
atomic_t evicted_bos;
|
||||
struct mutex notifier_lock;
|
||||
uint32_t evicted_bos;
|
||||
struct delayed_work restore_userptr_work;
|
||||
struct pid *pid;
|
||||
bool block_mmu_notifications;
|
||||
@@ -180,7 +183,8 @@ int kfd_debugfs_kfd_mem_limits(struct seq_file *m, void *data);
|
||||
bool amdkfd_fence_check_mm(struct dma_fence *f, struct mm_struct *mm);
|
||||
struct amdgpu_amdkfd_fence *to_amdgpu_amdkfd_fence(struct dma_fence *f);
|
||||
int amdgpu_amdkfd_remove_fence_on_pt_pd_bos(struct amdgpu_bo *bo);
|
||||
int amdgpu_amdkfd_evict_userptr(struct kgd_mem *mem, struct mm_struct *mm);
|
||||
int amdgpu_amdkfd_evict_userptr(struct mmu_interval_notifier *mni,
|
||||
unsigned long cur_seq, struct kgd_mem *mem);
|
||||
#else
|
||||
static inline
|
||||
bool amdkfd_fence_check_mm(struct dma_fence *f, struct mm_struct *mm)
|
||||
@@ -201,7 +205,8 @@ int amdgpu_amdkfd_remove_fence_on_pt_pd_bos(struct amdgpu_bo *bo)
|
||||
}
|
||||
|
||||
static inline
|
||||
int amdgpu_amdkfd_evict_userptr(struct kgd_mem *mem, struct mm_struct *mm)
|
||||
int amdgpu_amdkfd_evict_userptr(struct mmu_interval_notifier *mni,
|
||||
unsigned long cur_seq, struct kgd_mem *mem)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -265,8 +270,10 @@ int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct amdgpu_device *adev, bool is_
|
||||
(&((struct amdgpu_fpriv *) \
|
||||
((struct drm_file *)(drm_priv))->driver_priv)->vm)
|
||||
|
||||
int amdgpu_amdkfd_gpuvm_set_vm_pasid(struct amdgpu_device *adev,
|
||||
struct file *filp, u32 pasid);
|
||||
int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct amdgpu_device *adev,
|
||||
struct file *filp, u32 pasid,
|
||||
struct file *filp,
|
||||
void **process_info,
|
||||
struct dma_fence **ef);
|
||||
void amdgpu_amdkfd_gpuvm_release_process_vm(struct amdgpu_device *adev,
|
||||
|
||||
@@ -964,7 +964,9 @@ static int init_user_pages(struct kgd_mem *mem, uint64_t user_addr,
|
||||
* later stage when it is scheduled by another ioctl called by
|
||||
* CRIU master process for the target pid for restore.
|
||||
*/
|
||||
atomic_inc(&mem->invalid);
|
||||
mutex_lock(&process_info->notifier_lock);
|
||||
mem->invalid++;
|
||||
mutex_unlock(&process_info->notifier_lock);
|
||||
mutex_unlock(&process_info->lock);
|
||||
return 0;
|
||||
}
|
||||
@@ -1301,6 +1303,7 @@ static int init_kfd_vm(struct amdgpu_vm *vm, void **process_info,
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&info->lock);
|
||||
mutex_init(&info->notifier_lock);
|
||||
INIT_LIST_HEAD(&info->vm_list_head);
|
||||
INIT_LIST_HEAD(&info->kfd_bo_list);
|
||||
INIT_LIST_HEAD(&info->userptr_valid_list);
|
||||
@@ -1317,7 +1320,6 @@ static int init_kfd_vm(struct amdgpu_vm *vm, void **process_info,
|
||||
}
|
||||
|
||||
info->pid = get_task_pid(current->group_leader, PIDTYPE_PID);
|
||||
atomic_set(&info->evicted_bos, 0);
|
||||
INIT_DELAYED_WORK(&info->restore_userptr_work,
|
||||
amdgpu_amdkfd_restore_userptr_worker);
|
||||
|
||||
@@ -1372,6 +1374,7 @@ reserve_pd_fail:
|
||||
put_pid(info->pid);
|
||||
create_evict_fence_fail:
|
||||
mutex_destroy(&info->lock);
|
||||
mutex_destroy(&info->notifier_lock);
|
||||
kfree(info);
|
||||
}
|
||||
return ret;
|
||||
@@ -1426,8 +1429,36 @@ static void amdgpu_amdkfd_gpuvm_unpin_bo(struct amdgpu_bo *bo)
|
||||
amdgpu_bo_unreserve(bo);
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_gpuvm_set_vm_pasid(struct amdgpu_device *adev,
|
||||
struct file *filp, u32 pasid)
|
||||
|
||||
{
|
||||
struct amdgpu_fpriv *drv_priv;
|
||||
struct amdgpu_vm *avm;
|
||||
int ret;
|
||||
|
||||
ret = amdgpu_file_to_fpriv(filp, &drv_priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
avm = &drv_priv->vm;
|
||||
|
||||
/* Free the original amdgpu allocated pasid,
|
||||
* will be replaced with kfd allocated pasid.
|
||||
*/
|
||||
if (avm->pasid) {
|
||||
amdgpu_pasid_free(avm->pasid);
|
||||
amdgpu_vm_set_pasid(adev, avm, 0);
|
||||
}
|
||||
|
||||
ret = amdgpu_vm_set_pasid(adev, avm, pasid);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct amdgpu_device *adev,
|
||||
struct file *filp, u32 pasid,
|
||||
struct file *filp,
|
||||
void **process_info,
|
||||
struct dma_fence **ef)
|
||||
{
|
||||
@@ -1444,22 +1475,11 @@ int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct amdgpu_device *adev,
|
||||
if (avm->process_info)
|
||||
return -EINVAL;
|
||||
|
||||
/* Free the original amdgpu allocated pasid,
|
||||
* will be replaced with kfd allocated pasid.
|
||||
*/
|
||||
if (avm->pasid) {
|
||||
amdgpu_pasid_free(avm->pasid);
|
||||
amdgpu_vm_set_pasid(adev, avm, 0);
|
||||
}
|
||||
|
||||
/* Convert VM into a compute VM */
|
||||
ret = amdgpu_vm_make_compute(adev, avm);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = amdgpu_vm_set_pasid(adev, avm, pasid);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* Initialize KFD part of the VM and process info */
|
||||
ret = init_kfd_vm(avm, process_info, ef);
|
||||
if (ret)
|
||||
@@ -1496,6 +1516,7 @@ void amdgpu_amdkfd_gpuvm_destroy_cb(struct amdgpu_device *adev,
|
||||
cancel_delayed_work_sync(&process_info->restore_userptr_work);
|
||||
put_pid(process_info->pid);
|
||||
mutex_destroy(&process_info->lock);
|
||||
mutex_destroy(&process_info->notifier_lock);
|
||||
kfree(process_info);
|
||||
}
|
||||
}
|
||||
@@ -1548,7 +1569,9 @@ int amdgpu_amdkfd_criu_resume(void *p)
|
||||
|
||||
mutex_lock(&pinfo->lock);
|
||||
pr_debug("scheduling work\n");
|
||||
atomic_inc(&pinfo->evicted_bos);
|
||||
mutex_lock(&pinfo->notifier_lock);
|
||||
pinfo->evicted_bos++;
|
||||
mutex_unlock(&pinfo->notifier_lock);
|
||||
if (!READ_ONCE(pinfo->block_mmu_notifications)) {
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
@@ -1773,8 +1796,13 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
|
||||
list_del(&bo_list_entry->head);
|
||||
mutex_unlock(&process_info->lock);
|
||||
|
||||
/* No more MMU notifiers */
|
||||
amdgpu_hmm_unregister(mem->bo);
|
||||
/* Cleanup user pages and MMU notifiers */
|
||||
if (amdgpu_ttm_tt_get_usermm(mem->bo->tbo.ttm)) {
|
||||
amdgpu_hmm_unregister(mem->bo);
|
||||
mutex_lock(&process_info->notifier_lock);
|
||||
amdgpu_ttm_tt_discard_user_pages(mem->bo->tbo.ttm, mem->range);
|
||||
mutex_unlock(&process_info->notifier_lock);
|
||||
}
|
||||
|
||||
ret = reserve_bo_and_cond_vms(mem, NULL, BO_VM_ALL, &ctx);
|
||||
if (unlikely(ret))
|
||||
@@ -1864,6 +1892,16 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
|
||||
*/
|
||||
mutex_lock(&mem->process_info->lock);
|
||||
|
||||
/* Lock notifier lock. If we find an invalid userptr BO, we can be
|
||||
* sure that the MMU notifier is no longer running
|
||||
* concurrently and the queues are actually stopped
|
||||
*/
|
||||
if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm)) {
|
||||
mutex_lock(&mem->process_info->notifier_lock);
|
||||
is_invalid_userptr = !!mem->invalid;
|
||||
mutex_unlock(&mem->process_info->notifier_lock);
|
||||
}
|
||||
|
||||
mutex_lock(&mem->lock);
|
||||
|
||||
domain = mem->domain;
|
||||
@@ -2241,34 +2279,38 @@ int amdgpu_amdkfd_gpuvm_import_dmabuf(struct amdgpu_device *adev,
|
||||
*
|
||||
* Runs in MMU notifier, may be in RECLAIM_FS context. This means it
|
||||
* cannot do any memory allocations, and cannot take any locks that
|
||||
* are held elsewhere while allocating memory. Therefore this is as
|
||||
* simple as possible, using atomic counters.
|
||||
* are held elsewhere while allocating memory.
|
||||
*
|
||||
* It doesn't do anything to the BO itself. The real work happens in
|
||||
* restore, where we get updated page addresses. This function only
|
||||
* ensures that GPU access to the BO is stopped.
|
||||
*/
|
||||
int amdgpu_amdkfd_evict_userptr(struct kgd_mem *mem,
|
||||
struct mm_struct *mm)
|
||||
int amdgpu_amdkfd_evict_userptr(struct mmu_interval_notifier *mni,
|
||||
unsigned long cur_seq, struct kgd_mem *mem)
|
||||
{
|
||||
struct amdkfd_process_info *process_info = mem->process_info;
|
||||
int evicted_bos;
|
||||
int r = 0;
|
||||
|
||||
/* Do not process MMU notifications until stage-4 IOCTL is received */
|
||||
/* Do not process MMU notifications during CRIU restore until
|
||||
* KFD_CRIU_OP_RESUME IOCTL is received
|
||||
*/
|
||||
if (READ_ONCE(process_info->block_mmu_notifications))
|
||||
return 0;
|
||||
|
||||
atomic_inc(&mem->invalid);
|
||||
evicted_bos = atomic_inc_return(&process_info->evicted_bos);
|
||||
if (evicted_bos == 1) {
|
||||
mutex_lock(&process_info->notifier_lock);
|
||||
mmu_interval_set_seq(mni, cur_seq);
|
||||
|
||||
mem->invalid++;
|
||||
if (++process_info->evicted_bos == 1) {
|
||||
/* First eviction, stop the queues */
|
||||
r = kgd2kfd_quiesce_mm(mm, KFD_QUEUE_EVICTION_TRIGGER_USERPTR);
|
||||
r = kgd2kfd_quiesce_mm(mni->mm,
|
||||
KFD_QUEUE_EVICTION_TRIGGER_USERPTR);
|
||||
if (r)
|
||||
pr_err("Failed to quiesce KFD\n");
|
||||
schedule_delayed_work(&process_info->restore_userptr_work,
|
||||
msecs_to_jiffies(AMDGPU_USERPTR_RESTORE_DELAY_MS));
|
||||
}
|
||||
mutex_unlock(&process_info->notifier_lock);
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -2285,54 +2327,58 @@ static int update_invalid_user_pages(struct amdkfd_process_info *process_info,
|
||||
struct kgd_mem *mem, *tmp_mem;
|
||||
struct amdgpu_bo *bo;
|
||||
struct ttm_operation_ctx ctx = { false, false };
|
||||
int invalid, ret;
|
||||
uint32_t invalid;
|
||||
int ret = 0;
|
||||
|
||||
/* Move all invalidated BOs to the userptr_inval_list and
|
||||
* release their user pages by migration to the CPU domain
|
||||
*/
|
||||
mutex_lock(&process_info->notifier_lock);
|
||||
|
||||
/* Move all invalidated BOs to the userptr_inval_list */
|
||||
list_for_each_entry_safe(mem, tmp_mem,
|
||||
&process_info->userptr_valid_list,
|
||||
validate_list.head) {
|
||||
if (!atomic_read(&mem->invalid))
|
||||
continue; /* BO is still valid */
|
||||
|
||||
bo = mem->bo;
|
||||
|
||||
if (amdgpu_bo_reserve(bo, true))
|
||||
return -EAGAIN;
|
||||
amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_CPU);
|
||||
ret = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
|
||||
amdgpu_bo_unreserve(bo);
|
||||
if (ret) {
|
||||
pr_err("%s: Failed to invalidate userptr BO\n",
|
||||
__func__);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
list_move_tail(&mem->validate_list.head,
|
||||
&process_info->userptr_inval_list);
|
||||
}
|
||||
|
||||
if (list_empty(&process_info->userptr_inval_list))
|
||||
return 0; /* All evicted userptr BOs were freed */
|
||||
validate_list.head)
|
||||
if (mem->invalid)
|
||||
list_move_tail(&mem->validate_list.head,
|
||||
&process_info->userptr_inval_list);
|
||||
|
||||
/* Go through userptr_inval_list and update any invalid user_pages */
|
||||
list_for_each_entry(mem, &process_info->userptr_inval_list,
|
||||
validate_list.head) {
|
||||
struct hmm_range *range;
|
||||
|
||||
invalid = atomic_read(&mem->invalid);
|
||||
invalid = mem->invalid;
|
||||
if (!invalid)
|
||||
/* BO hasn't been invalidated since the last
|
||||
* revalidation attempt. Keep its BO list.
|
||||
* revalidation attempt. Keep its page list.
|
||||
*/
|
||||
continue;
|
||||
|
||||
bo = mem->bo;
|
||||
|
||||
amdgpu_ttm_tt_discard_user_pages(bo->tbo.ttm, mem->range);
|
||||
mem->range = NULL;
|
||||
|
||||
/* BO reservations and getting user pages (hmm_range_fault)
|
||||
* must happen outside the notifier lock
|
||||
*/
|
||||
mutex_unlock(&process_info->notifier_lock);
|
||||
|
||||
/* Move the BO to system (CPU) domain if necessary to unmap
|
||||
* and free the SG table
|
||||
*/
|
||||
if (bo->tbo.resource->mem_type != TTM_PL_SYSTEM) {
|
||||
if (amdgpu_bo_reserve(bo, true))
|
||||
return -EAGAIN;
|
||||
amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_CPU);
|
||||
ret = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
|
||||
amdgpu_bo_unreserve(bo);
|
||||
if (ret) {
|
||||
pr_err("%s: Failed to invalidate userptr BO\n",
|
||||
__func__);
|
||||
return -EAGAIN;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get updated user pages */
|
||||
ret = amdgpu_ttm_tt_get_user_pages(bo, bo->tbo.ttm->pages,
|
||||
&range);
|
||||
&mem->range);
|
||||
if (ret) {
|
||||
pr_debug("Failed %d to get user pages\n", ret);
|
||||
|
||||
@@ -2345,30 +2391,32 @@ static int update_invalid_user_pages(struct amdkfd_process_info *process_info,
|
||||
*/
|
||||
if (ret != -EFAULT)
|
||||
return ret;
|
||||
} else {
|
||||
|
||||
/*
|
||||
* FIXME: Cannot ignore the return code, must hold
|
||||
* notifier_lock
|
||||
*/
|
||||
amdgpu_ttm_tt_get_user_pages_done(bo->tbo.ttm, range);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
mutex_lock(&process_info->notifier_lock);
|
||||
|
||||
/* Mark the BO as valid unless it was invalidated
|
||||
* again concurrently.
|
||||
*/
|
||||
if (atomic_cmpxchg(&mem->invalid, invalid, 0) != invalid)
|
||||
return -EAGAIN;
|
||||
if (mem->invalid != invalid) {
|
||||
ret = -EAGAIN;
|
||||
goto unlock_out;
|
||||
}
|
||||
mem->invalid = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
unlock_out:
|
||||
mutex_unlock(&process_info->notifier_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Validate invalid userptr BOs
|
||||
*
|
||||
* Validates BOs on the userptr_inval_list, and moves them back to the
|
||||
* userptr_valid_list. Also updates GPUVM page tables with new page
|
||||
* addresses and waits for the page table updates to complete.
|
||||
* Validates BOs on the userptr_inval_list. Also updates GPUVM page tables
|
||||
* with new page addresses and waits for the page table updates to complete.
|
||||
*/
|
||||
static int validate_invalid_user_pages(struct amdkfd_process_info *process_info)
|
||||
{
|
||||
@@ -2439,9 +2487,6 @@ static int validate_invalid_user_pages(struct amdkfd_process_info *process_info)
|
||||
}
|
||||
}
|
||||
|
||||
list_move_tail(&mem->validate_list.head,
|
||||
&process_info->userptr_valid_list);
|
||||
|
||||
/* Update mapping. If the BO was not validated
|
||||
* (because we couldn't get user pages), this will
|
||||
* clear the page table entries, which will result in
|
||||
@@ -2457,7 +2502,9 @@ static int validate_invalid_user_pages(struct amdkfd_process_info *process_info)
|
||||
if (ret) {
|
||||
pr_err("%s: update PTE failed\n", __func__);
|
||||
/* make sure this gets validated again */
|
||||
atomic_inc(&mem->invalid);
|
||||
mutex_lock(&process_info->notifier_lock);
|
||||
mem->invalid++;
|
||||
mutex_unlock(&process_info->notifier_lock);
|
||||
goto unreserve_out;
|
||||
}
|
||||
}
|
||||
@@ -2477,6 +2524,36 @@ out_no_mem:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Confirm that all user pages are valid while holding the notifier lock
|
||||
*
|
||||
* Moves valid BOs from the userptr_inval_list back to userptr_val_list.
|
||||
*/
|
||||
static int confirm_valid_user_pages_locked(struct amdkfd_process_info *process_info)
|
||||
{
|
||||
struct kgd_mem *mem, *tmp_mem;
|
||||
int ret = 0;
|
||||
|
||||
list_for_each_entry_safe(mem, tmp_mem,
|
||||
&process_info->userptr_inval_list,
|
||||
validate_list.head) {
|
||||
bool valid = amdgpu_ttm_tt_get_user_pages_done(
|
||||
mem->bo->tbo.ttm, mem->range);
|
||||
|
||||
mem->range = NULL;
|
||||
if (!valid) {
|
||||
WARN(!mem->invalid, "Invalid BO not marked invalid");
|
||||
ret = -EAGAIN;
|
||||
continue;
|
||||
}
|
||||
WARN(mem->invalid, "Valid BO is marked invalid");
|
||||
|
||||
list_move_tail(&mem->validate_list.head,
|
||||
&process_info->userptr_valid_list);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Worker callback to restore evicted userptr BOs
|
||||
*
|
||||
* Tries to update and validate all userptr BOs. If successful and no
|
||||
@@ -2491,9 +2568,11 @@ static void amdgpu_amdkfd_restore_userptr_worker(struct work_struct *work)
|
||||
restore_userptr_work);
|
||||
struct task_struct *usertask;
|
||||
struct mm_struct *mm;
|
||||
int evicted_bos;
|
||||
uint32_t evicted_bos;
|
||||
|
||||
evicted_bos = atomic_read(&process_info->evicted_bos);
|
||||
mutex_lock(&process_info->notifier_lock);
|
||||
evicted_bos = process_info->evicted_bos;
|
||||
mutex_unlock(&process_info->notifier_lock);
|
||||
if (!evicted_bos)
|
||||
return;
|
||||
|
||||
@@ -2516,9 +2595,6 @@ static void amdgpu_amdkfd_restore_userptr_worker(struct work_struct *work)
|
||||
* and we can just restart the queues.
|
||||
*/
|
||||
if (!list_empty(&process_info->userptr_inval_list)) {
|
||||
if (atomic_read(&process_info->evicted_bos) != evicted_bos)
|
||||
goto unlock_out; /* Concurrent eviction, try again */
|
||||
|
||||
if (validate_invalid_user_pages(process_info))
|
||||
goto unlock_out;
|
||||
}
|
||||
@@ -2527,10 +2603,17 @@ static void amdgpu_amdkfd_restore_userptr_worker(struct work_struct *work)
|
||||
* be a first eviction that calls quiesce_mm. The eviction
|
||||
* reference counting inside KFD will handle this case.
|
||||
*/
|
||||
if (atomic_cmpxchg(&process_info->evicted_bos, evicted_bos, 0) !=
|
||||
evicted_bos)
|
||||
goto unlock_out;
|
||||
evicted_bos = 0;
|
||||
mutex_lock(&process_info->notifier_lock);
|
||||
if (process_info->evicted_bos != evicted_bos)
|
||||
goto unlock_notifier_out;
|
||||
|
||||
if (confirm_valid_user_pages_locked(process_info)) {
|
||||
WARN(1, "User pages unexpectedly invalid");
|
||||
goto unlock_notifier_out;
|
||||
}
|
||||
|
||||
process_info->evicted_bos = evicted_bos = 0;
|
||||
|
||||
if (kgd2kfd_resume_mm(mm)) {
|
||||
pr_err("%s: Failed to resume KFD\n", __func__);
|
||||
/* No recovery from this failure. Probably the CP is
|
||||
@@ -2538,6 +2621,8 @@ static void amdgpu_amdkfd_restore_userptr_worker(struct work_struct *work)
|
||||
*/
|
||||
}
|
||||
|
||||
unlock_notifier_out:
|
||||
mutex_unlock(&process_info->notifier_lock);
|
||||
unlock_out:
|
||||
mutex_unlock(&process_info->lock);
|
||||
|
||||
|
||||
@@ -3016,14 +3016,15 @@ static int amdgpu_device_ip_suspend_phase2(struct amdgpu_device *adev)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* skip suspend of gfx and psp for S0ix
|
||||
/* skip suspend of gfx/mes and psp for S0ix
|
||||
* gfx is in gfxoff state, so on resume it will exit gfxoff just
|
||||
* like at runtime. PSP is also part of the always on hardware
|
||||
* so no need to suspend it.
|
||||
*/
|
||||
if (adev->in_s0ix &&
|
||||
(adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP ||
|
||||
adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GFX))
|
||||
adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GFX ||
|
||||
adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_MES))
|
||||
continue;
|
||||
|
||||
/* XXX handle errors */
|
||||
@@ -4112,6 +4113,11 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
|
||||
|
||||
adev->in_suspend = true;
|
||||
|
||||
/* Evict the majority of BOs before grabbing the full access */
|
||||
r = amdgpu_device_evict_resources(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (amdgpu_sriov_vf(adev)) {
|
||||
amdgpu_virt_fini_data_exchange(adev);
|
||||
r = amdgpu_virt_request_full_gpu(adev, false);
|
||||
|
||||
@@ -2039,6 +2039,15 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
|
||||
"See modparam exp_hw_support\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
/* differentiate between P10 and P11 asics with the same DID */
|
||||
if (pdev->device == 0x67FF &&
|
||||
(pdev->revision == 0xE3 ||
|
||||
pdev->revision == 0xE7 ||
|
||||
pdev->revision == 0xF3 ||
|
||||
pdev->revision == 0xF7)) {
|
||||
flags &= ~AMD_ASIC_MASK;
|
||||
flags |= CHIP_POLARIS10;
|
||||
}
|
||||
|
||||
/* Due to hardware bugs, S/G Display on raven requires a 1:1 IOMMU mapping,
|
||||
* however, SME requires an indirect IOMMU mapping because the encryption
|
||||
@@ -2108,12 +2117,12 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
|
||||
|
||||
pci_set_drvdata(pdev, ddev);
|
||||
|
||||
ret = amdgpu_driver_load_kms(adev, ent->driver_data);
|
||||
ret = amdgpu_driver_load_kms(adev, flags);
|
||||
if (ret)
|
||||
goto err_pci;
|
||||
|
||||
retry_init:
|
||||
ret = drm_dev_register(ddev, ent->driver_data);
|
||||
ret = drm_dev_register(ddev, flags);
|
||||
if (ret == -EAGAIN && ++retry <= 3) {
|
||||
DRM_INFO("retry init %d\n", retry);
|
||||
/* Don't request EX mode too frequently which is attacking */
|
||||
|
||||
@@ -64,7 +64,8 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev, u32 *fru_addr)
|
||||
sizeof(atom_ctx->vbios_version)) ||
|
||||
strnstr(atom_ctx->vbios_version, "D163",
|
||||
sizeof(atom_ctx->vbios_version))) {
|
||||
*fru_addr = FRU_EEPROM_MADDR_6;
|
||||
if (fru_addr)
|
||||
*fru_addr = FRU_EEPROM_MADDR_6;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -83,7 +84,8 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev, u32 *fru_addr)
|
||||
sizeof(atom_ctx->vbios_version))) {
|
||||
return false;
|
||||
} else {
|
||||
*fru_addr = FRU_EEPROM_MADDR_6;
|
||||
if (fru_addr)
|
||||
*fru_addr = FRU_EEPROM_MADDR_6;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -113,7 +113,7 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size,
|
||||
bp.resv = resv;
|
||||
bp.preferred_domain = initial_domain;
|
||||
bp.flags = flags;
|
||||
bp.domain = initial_domain | AMDGPU_GEM_DOMAIN_CPU;
|
||||
bp.domain = initial_domain;
|
||||
bp.bo_ptr_size = sizeof(struct amdgpu_bo);
|
||||
|
||||
r = amdgpu_bo_create_user(adev, &bp, &ubo);
|
||||
@@ -332,10 +332,20 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data,
|
||||
}
|
||||
|
||||
initial_domain = (u32)(0xffffffff & args->in.domains);
|
||||
retry:
|
||||
r = amdgpu_gem_object_create(adev, size, args->in.alignment,
|
||||
initial_domain, flags, ttm_bo_type_device,
|
||||
resv, &gobj);
|
||||
initial_domain,
|
||||
flags, ttm_bo_type_device, resv, &gobj);
|
||||
if (r && r != -ERESTARTSYS) {
|
||||
if (flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) {
|
||||
flags &= ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if (initial_domain == AMDGPU_GEM_DOMAIN_VRAM) {
|
||||
initial_domain |= AMDGPU_GEM_DOMAIN_GTT;
|
||||
goto retry;
|
||||
}
|
||||
DRM_DEBUG("Failed to allocate GEM object (%llu, %d, %llu, %d)\n",
|
||||
size, initial_domain, args->in.alignment, r);
|
||||
}
|
||||
|
||||
@@ -105,17 +105,11 @@ static bool amdgpu_hmm_invalidate_hsa(struct mmu_interval_notifier *mni,
|
||||
unsigned long cur_seq)
|
||||
{
|
||||
struct amdgpu_bo *bo = container_of(mni, struct amdgpu_bo, notifier);
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
|
||||
|
||||
if (!mmu_notifier_range_blockable(range))
|
||||
return false;
|
||||
|
||||
mutex_lock(&adev->notifier_lock);
|
||||
|
||||
mmu_interval_set_seq(mni, cur_seq);
|
||||
|
||||
amdgpu_amdkfd_evict_userptr(bo->kfd_bo, bo->notifier.mm);
|
||||
mutex_unlock(&adev->notifier_lock);
|
||||
amdgpu_amdkfd_evict_userptr(mni, cur_seq, bo->kfd_bo);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -244,9 +238,9 @@ out_free_range:
|
||||
return r;
|
||||
}
|
||||
|
||||
int amdgpu_hmm_range_get_pages_done(struct hmm_range *hmm_range)
|
||||
bool amdgpu_hmm_range_get_pages_done(struct hmm_range *hmm_range)
|
||||
{
|
||||
int r;
|
||||
bool r;
|
||||
|
||||
r = mmu_interval_read_retry(hmm_range->notifier,
|
||||
hmm_range->notifier_seq);
|
||||
|
||||
@@ -29,12 +29,13 @@
|
||||
#include <linux/rwsem.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/interval_tree.h>
|
||||
#include <linux/mmu_notifier.h>
|
||||
|
||||
int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier *notifier,
|
||||
uint64_t start, uint64_t npages, bool readonly,
|
||||
void *owner, struct page **pages,
|
||||
struct hmm_range **phmm_range);
|
||||
int amdgpu_hmm_range_get_pages_done(struct hmm_range *hmm_range);
|
||||
bool amdgpu_hmm_range_get_pages_done(struct hmm_range *hmm_range);
|
||||
|
||||
#if defined(CONFIG_HMM_MIRROR)
|
||||
int amdgpu_hmm_register(struct amdgpu_bo *bo, unsigned long addr);
|
||||
|
||||
@@ -165,6 +165,26 @@ bool amdgpu_vmid_had_gpu_reset(struct amdgpu_device *adev,
|
||||
atomic_read(&adev->gpu_reset_counter);
|
||||
}
|
||||
|
||||
/* Check if we need to switch to another set of resources */
|
||||
static bool amdgpu_vmid_gds_switch_needed(struct amdgpu_vmid *id,
|
||||
struct amdgpu_job *job)
|
||||
{
|
||||
return id->gds_base != job->gds_base ||
|
||||
id->gds_size != job->gds_size ||
|
||||
id->gws_base != job->gws_base ||
|
||||
id->gws_size != job->gws_size ||
|
||||
id->oa_base != job->oa_base ||
|
||||
id->oa_size != job->oa_size;
|
||||
}
|
||||
|
||||
/* Check if the id is compatible with the job */
|
||||
static bool amdgpu_vmid_compatible(struct amdgpu_vmid *id,
|
||||
struct amdgpu_job *job)
|
||||
{
|
||||
return id->pd_gpu_addr == job->vm_pd_addr &&
|
||||
!amdgpu_vmid_gds_switch_needed(id, job);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_vmid_grab_idle - grab idle VMID
|
||||
*
|
||||
@@ -258,14 +278,15 @@ static int amdgpu_vmid_grab_reserved(struct amdgpu_vm *vm,
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
unsigned vmhub = ring->funcs->vmhub;
|
||||
struct amdgpu_vmid_mgr *id_mgr = &adev->vm_manager.id_mgr[vmhub];
|
||||
uint64_t fence_context = adev->fence_context + ring->idx;
|
||||
bool needs_flush = vm->use_cpu_for_update;
|
||||
uint64_t updates = amdgpu_vm_tlb_seq(vm);
|
||||
int r;
|
||||
|
||||
*id = vm->reserved_vmid[vmhub];
|
||||
*id = id_mgr->reserved;
|
||||
if ((*id)->owner != vm->immediate.fence_context ||
|
||||
(*id)->pd_gpu_addr != job->vm_pd_addr ||
|
||||
!amdgpu_vmid_compatible(*id, job) ||
|
||||
(*id)->flushed_updates < updates ||
|
||||
!(*id)->last_flush ||
|
||||
((*id)->last_flush->context != fence_context &&
|
||||
@@ -294,8 +315,8 @@ static int amdgpu_vmid_grab_reserved(struct amdgpu_vm *vm,
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
(*id)->flushed_updates = updates;
|
||||
job->vm_needs_flush = needs_flush;
|
||||
job->spm_update_needed = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -333,7 +354,7 @@ static int amdgpu_vmid_grab_used(struct amdgpu_vm *vm,
|
||||
if ((*id)->owner != vm->immediate.fence_context)
|
||||
continue;
|
||||
|
||||
if ((*id)->pd_gpu_addr != job->vm_pd_addr)
|
||||
if (!amdgpu_vmid_compatible(*id, job))
|
||||
continue;
|
||||
|
||||
if (!(*id)->last_flush ||
|
||||
@@ -355,7 +376,6 @@ static int amdgpu_vmid_grab_used(struct amdgpu_vm *vm,
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
(*id)->flushed_updates = updates;
|
||||
job->vm_needs_flush |= needs_flush;
|
||||
return 0;
|
||||
}
|
||||
@@ -408,22 +428,30 @@ int amdgpu_vmid_grab(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
|
||||
if (r)
|
||||
goto error;
|
||||
|
||||
id->flushed_updates = amdgpu_vm_tlb_seq(vm);
|
||||
job->vm_needs_flush = true;
|
||||
}
|
||||
|
||||
list_move_tail(&id->list, &id_mgr->ids_lru);
|
||||
}
|
||||
|
||||
id->pd_gpu_addr = job->vm_pd_addr;
|
||||
id->owner = vm->immediate.fence_context;
|
||||
|
||||
job->gds_switch_needed = amdgpu_vmid_gds_switch_needed(id, job);
|
||||
if (job->vm_needs_flush) {
|
||||
id->flushed_updates = amdgpu_vm_tlb_seq(vm);
|
||||
dma_fence_put(id->last_flush);
|
||||
id->last_flush = NULL;
|
||||
}
|
||||
job->vmid = id - id_mgr->ids;
|
||||
job->pasid = vm->pasid;
|
||||
|
||||
id->gds_base = job->gds_base;
|
||||
id->gds_size = job->gds_size;
|
||||
id->gws_base = job->gws_base;
|
||||
id->gws_size = job->gws_size;
|
||||
id->oa_base = job->oa_base;
|
||||
id->oa_size = job->oa_size;
|
||||
id->pd_gpu_addr = job->vm_pd_addr;
|
||||
id->owner = vm->immediate.fence_context;
|
||||
|
||||
trace_amdgpu_vm_grab_id(vm, ring, job);
|
||||
|
||||
error:
|
||||
@@ -435,31 +463,27 @@ int amdgpu_vmid_alloc_reserved(struct amdgpu_device *adev,
|
||||
struct amdgpu_vm *vm,
|
||||
unsigned vmhub)
|
||||
{
|
||||
struct amdgpu_vmid_mgr *id_mgr;
|
||||
struct amdgpu_vmid *idle;
|
||||
int r = 0;
|
||||
struct amdgpu_vmid_mgr *id_mgr = &adev->vm_manager.id_mgr[vmhub];
|
||||
|
||||
id_mgr = &adev->vm_manager.id_mgr[vmhub];
|
||||
mutex_lock(&id_mgr->lock);
|
||||
if (vm->reserved_vmid[vmhub])
|
||||
goto unlock;
|
||||
if (atomic_inc_return(&id_mgr->reserved_vmid_num) >
|
||||
AMDGPU_VM_MAX_RESERVED_VMID) {
|
||||
DRM_ERROR("Over limitation of reserved vmid\n");
|
||||
atomic_dec(&id_mgr->reserved_vmid_num);
|
||||
r = -EINVAL;
|
||||
goto unlock;
|
||||
}
|
||||
/* Select the first entry VMID */
|
||||
idle = list_first_entry(&id_mgr->ids_lru, struct amdgpu_vmid, list);
|
||||
list_del_init(&idle->list);
|
||||
vm->reserved_vmid[vmhub] = idle;
|
||||
mutex_unlock(&id_mgr->lock);
|
||||
|
||||
return 0;
|
||||
++id_mgr->reserved_use_count;
|
||||
if (!id_mgr->reserved) {
|
||||
struct amdgpu_vmid *id;
|
||||
|
||||
id = list_first_entry(&id_mgr->ids_lru, struct amdgpu_vmid,
|
||||
list);
|
||||
/* Remove from normal round robin handling */
|
||||
list_del_init(&id->list);
|
||||
id_mgr->reserved = id;
|
||||
}
|
||||
vm->reserved_vmid[vmhub] = true;
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&id_mgr->lock);
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void amdgpu_vmid_free_reserved(struct amdgpu_device *adev,
|
||||
@@ -469,12 +493,12 @@ void amdgpu_vmid_free_reserved(struct amdgpu_device *adev,
|
||||
struct amdgpu_vmid_mgr *id_mgr = &adev->vm_manager.id_mgr[vmhub];
|
||||
|
||||
mutex_lock(&id_mgr->lock);
|
||||
if (vm->reserved_vmid[vmhub]) {
|
||||
list_add(&vm->reserved_vmid[vmhub]->list,
|
||||
&id_mgr->ids_lru);
|
||||
vm->reserved_vmid[vmhub] = NULL;
|
||||
atomic_dec(&id_mgr->reserved_vmid_num);
|
||||
if (vm->reserved_vmid[vmhub] &&
|
||||
!--id_mgr->reserved_use_count) {
|
||||
/* give the reserved ID back to normal round robin */
|
||||
list_add(&id_mgr->reserved->list, &id_mgr->ids_lru);
|
||||
}
|
||||
vm->reserved_vmid[vmhub] = false;
|
||||
mutex_unlock(&id_mgr->lock);
|
||||
}
|
||||
|
||||
@@ -541,7 +565,7 @@ void amdgpu_vmid_mgr_init(struct amdgpu_device *adev)
|
||||
|
||||
mutex_init(&id_mgr->lock);
|
||||
INIT_LIST_HEAD(&id_mgr->ids_lru);
|
||||
atomic_set(&id_mgr->reserved_vmid_num, 0);
|
||||
id_mgr->reserved_use_count = 0;
|
||||
|
||||
/* manage only VMIDs not used by KFD */
|
||||
id_mgr->num_ids = adev->vm_manager.first_kfd_vmid;
|
||||
|
||||
@@ -67,7 +67,8 @@ struct amdgpu_vmid_mgr {
|
||||
unsigned num_ids;
|
||||
struct list_head ids_lru;
|
||||
struct amdgpu_vmid ids[AMDGPU_NUM_VMID];
|
||||
atomic_t reserved_vmid_num;
|
||||
struct amdgpu_vmid *reserved;
|
||||
unsigned int reserved_use_count;
|
||||
};
|
||||
|
||||
int amdgpu_pasid_alloc(unsigned int bits);
|
||||
|
||||
@@ -53,6 +53,8 @@ struct amdgpu_job {
|
||||
uint32_t preamble_status;
|
||||
uint32_t preemption_status;
|
||||
bool vm_needs_flush;
|
||||
bool gds_switch_needed;
|
||||
bool spm_update_needed;
|
||||
uint64_t vm_pd_addr;
|
||||
unsigned vmid;
|
||||
unsigned pasid;
|
||||
|
||||
@@ -346,17 +346,16 @@ int amdgpu_bo_create_kernel(struct amdgpu_device *adev,
|
||||
* @adev: amdgpu device object
|
||||
* @offset: offset of the BO
|
||||
* @size: size of the BO
|
||||
* @domain: where to place it
|
||||
* @bo_ptr: used to initialize BOs in structures
|
||||
* @cpu_addr: optional CPU address mapping
|
||||
*
|
||||
* Creates a kernel BO at a specific offset in the address space of the domain.
|
||||
* Creates a kernel BO at a specific offset in VRAM.
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success, negative error code otherwise.
|
||||
*/
|
||||
int amdgpu_bo_create_kernel_at(struct amdgpu_device *adev,
|
||||
uint64_t offset, uint64_t size, uint32_t domain,
|
||||
uint64_t offset, uint64_t size,
|
||||
struct amdgpu_bo **bo_ptr, void **cpu_addr)
|
||||
{
|
||||
struct ttm_operation_ctx ctx = { false, false };
|
||||
@@ -366,8 +365,9 @@ int amdgpu_bo_create_kernel_at(struct amdgpu_device *adev,
|
||||
offset &= PAGE_MASK;
|
||||
size = ALIGN(size, PAGE_SIZE);
|
||||
|
||||
r = amdgpu_bo_create_reserved(adev, size, PAGE_SIZE, domain, bo_ptr,
|
||||
NULL, cpu_addr);
|
||||
r = amdgpu_bo_create_reserved(adev, size, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM, bo_ptr, NULL,
|
||||
cpu_addr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
@@ -422,6 +422,8 @@ void amdgpu_bo_free_kernel(struct amdgpu_bo **bo, u64 *gpu_addr,
|
||||
if (*bo == NULL)
|
||||
return;
|
||||
|
||||
WARN_ON(amdgpu_ttm_adev((*bo)->tbo.bdev)->in_suspend);
|
||||
|
||||
if (likely(amdgpu_bo_reserve(*bo, true) == 0)) {
|
||||
if (cpu_addr)
|
||||
amdgpu_bo_kunmap(*bo);
|
||||
@@ -446,27 +448,24 @@ static bool amdgpu_bo_validate_size(struct amdgpu_device *adev,
|
||||
|
||||
/*
|
||||
* If GTT is part of requested domains the check must succeed to
|
||||
* allow fall back to GTT
|
||||
* allow fall back to GTT.
|
||||
*/
|
||||
if (domain & AMDGPU_GEM_DOMAIN_GTT) {
|
||||
man = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT);
|
||||
|
||||
if (size < man->size)
|
||||
if (man && size < man->size)
|
||||
return true;
|
||||
else
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (domain & AMDGPU_GEM_DOMAIN_VRAM) {
|
||||
else if (!man)
|
||||
WARN_ON_ONCE("GTT domain requested but GTT mem manager uninitialized");
|
||||
goto fail;
|
||||
} else if (domain & AMDGPU_GEM_DOMAIN_VRAM) {
|
||||
man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM);
|
||||
|
||||
if (size < man->size)
|
||||
if (man && size < man->size)
|
||||
return true;
|
||||
else
|
||||
goto fail;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
/* TODO add more domains checks, such as AMDGPU_GEM_DOMAIN_CPU */
|
||||
return true;
|
||||
|
||||
@@ -581,7 +580,11 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
|
||||
bo->flags |= AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE;
|
||||
|
||||
bo->tbo.bdev = &adev->mman.bdev;
|
||||
amdgpu_bo_placement_from_domain(bo, bp->domain);
|
||||
if (bp->domain & (AMDGPU_GEM_DOMAIN_GWS | AMDGPU_GEM_DOMAIN_OA |
|
||||
AMDGPU_GEM_DOMAIN_GDS))
|
||||
amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_CPU);
|
||||
else
|
||||
amdgpu_bo_placement_from_domain(bo, bp->domain);
|
||||
if (bp->type == ttm_bo_type_kernel)
|
||||
bo->tbo.priority = 1;
|
||||
|
||||
@@ -1506,7 +1509,8 @@ u64 amdgpu_bo_gpu_offset_no_check(struct amdgpu_bo *bo)
|
||||
uint32_t amdgpu_bo_get_preferred_domain(struct amdgpu_device *adev,
|
||||
uint32_t domain)
|
||||
{
|
||||
if (domain == (AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT)) {
|
||||
if ((domain == (AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT)) &&
|
||||
((adev->asic_type == CHIP_CARRIZO) || (adev->asic_type == CHIP_STONEY))) {
|
||||
domain = AMDGPU_GEM_DOMAIN_VRAM;
|
||||
if (adev->gmc.real_vram_size <= AMDGPU_SG_THRESHOLD)
|
||||
domain = AMDGPU_GEM_DOMAIN_GTT;
|
||||
|
||||
@@ -284,7 +284,7 @@ int amdgpu_bo_create_kernel(struct amdgpu_device *adev,
|
||||
u32 domain, struct amdgpu_bo **bo_ptr,
|
||||
u64 *gpu_addr, void **cpu_addr);
|
||||
int amdgpu_bo_create_kernel_at(struct amdgpu_device *adev,
|
||||
uint64_t offset, uint64_t size, uint32_t domain,
|
||||
uint64_t offset, uint64_t size,
|
||||
struct amdgpu_bo **bo_ptr, void **cpu_addr);
|
||||
int amdgpu_bo_create_user(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo_param *bp,
|
||||
|
||||
@@ -695,8 +695,19 @@ out_unlock:
|
||||
return r;
|
||||
}
|
||||
|
||||
/* amdgpu_ttm_tt_discard_user_pages - Discard range and pfn array allocations
|
||||
*/
|
||||
void amdgpu_ttm_tt_discard_user_pages(struct ttm_tt *ttm,
|
||||
struct hmm_range *range)
|
||||
{
|
||||
struct amdgpu_ttm_tt *gtt = (void *)ttm;
|
||||
|
||||
if (gtt && gtt->userptr && range)
|
||||
amdgpu_hmm_range_get_pages_done(range);
|
||||
}
|
||||
|
||||
/*
|
||||
* amdgpu_ttm_tt_userptr_range_done - stop HMM track the CPU page table change
|
||||
* amdgpu_ttm_tt_get_user_pages_done - stop HMM track the CPU page table change
|
||||
* Check if the pages backing this ttm range have been invalidated
|
||||
*
|
||||
* Returns: true if pages are still valid
|
||||
@@ -714,10 +725,6 @@ bool amdgpu_ttm_tt_get_user_pages_done(struct ttm_tt *ttm,
|
||||
|
||||
WARN_ONCE(!range->hmm_pfns, "No user pages to check\n");
|
||||
|
||||
/*
|
||||
* FIXME: Must always hold notifier_lock for this, and must
|
||||
* not ignore the return code.
|
||||
*/
|
||||
return !amdgpu_hmm_range_get_pages_done(range);
|
||||
}
|
||||
#endif
|
||||
@@ -1569,7 +1576,6 @@ static int amdgpu_ttm_fw_reserve_vram_init(struct amdgpu_device *adev)
|
||||
return amdgpu_bo_create_kernel_at(adev,
|
||||
adev->mman.fw_vram_usage_start_offset,
|
||||
adev->mman.fw_vram_usage_size,
|
||||
AMDGPU_GEM_DOMAIN_VRAM,
|
||||
&adev->mman.fw_vram_usage_reserved_bo,
|
||||
&adev->mman.fw_vram_usage_va);
|
||||
}
|
||||
@@ -1595,7 +1601,6 @@ static int amdgpu_ttm_drv_reserve_vram_init(struct amdgpu_device *adev)
|
||||
return amdgpu_bo_create_kernel_at(adev,
|
||||
adev->mman.drv_vram_usage_start_offset,
|
||||
adev->mman.drv_vram_usage_size,
|
||||
AMDGPU_GEM_DOMAIN_VRAM,
|
||||
&adev->mman.drv_vram_usage_reserved_bo,
|
||||
&adev->mman.drv_vram_usage_va);
|
||||
}
|
||||
@@ -1676,7 +1681,6 @@ static int amdgpu_ttm_reserve_tmr(struct amdgpu_device *adev)
|
||||
ret = amdgpu_bo_create_kernel_at(adev,
|
||||
ctx->c2p_train_data_offset,
|
||||
ctx->train_data_size,
|
||||
AMDGPU_GEM_DOMAIN_VRAM,
|
||||
&ctx->c2p_bo,
|
||||
NULL);
|
||||
if (ret) {
|
||||
@@ -1690,7 +1694,6 @@ static int amdgpu_ttm_reserve_tmr(struct amdgpu_device *adev)
|
||||
ret = amdgpu_bo_create_kernel_at(adev,
|
||||
adev->gmc.real_vram_size - adev->mman.discovery_tmr_size,
|
||||
adev->mman.discovery_tmr_size,
|
||||
AMDGPU_GEM_DOMAIN_VRAM,
|
||||
&adev->mman.discovery_memory,
|
||||
NULL);
|
||||
if (ret) {
|
||||
@@ -1791,21 +1794,18 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
|
||||
* avoid display artifacts while transitioning between pre-OS
|
||||
* and driver. */
|
||||
r = amdgpu_bo_create_kernel_at(adev, 0, adev->mman.stolen_vga_size,
|
||||
AMDGPU_GEM_DOMAIN_VRAM,
|
||||
&adev->mman.stolen_vga_memory,
|
||||
NULL);
|
||||
if (r)
|
||||
return r;
|
||||
r = amdgpu_bo_create_kernel_at(adev, adev->mman.stolen_vga_size,
|
||||
adev->mman.stolen_extended_size,
|
||||
AMDGPU_GEM_DOMAIN_VRAM,
|
||||
&adev->mman.stolen_extended_memory,
|
||||
NULL);
|
||||
if (r)
|
||||
return r;
|
||||
r = amdgpu_bo_create_kernel_at(adev, adev->mman.stolen_reserved_offset,
|
||||
adev->mman.stolen_reserved_size,
|
||||
AMDGPU_GEM_DOMAIN_VRAM,
|
||||
&adev->mman.stolen_reserved_memory,
|
||||
NULL);
|
||||
if (r)
|
||||
|
||||
@@ -159,6 +159,8 @@ uint64_t amdgpu_ttm_domain_start(struct amdgpu_device *adev, uint32_t type);
|
||||
#if IS_ENABLED(CONFIG_DRM_AMDGPU_USERPTR)
|
||||
int amdgpu_ttm_tt_get_user_pages(struct amdgpu_bo *bo, struct page **pages,
|
||||
struct hmm_range **range);
|
||||
void amdgpu_ttm_tt_discard_user_pages(struct ttm_tt *ttm,
|
||||
struct hmm_range *range);
|
||||
bool amdgpu_ttm_tt_get_user_pages_done(struct ttm_tt *ttm,
|
||||
struct hmm_range *range);
|
||||
#else
|
||||
@@ -168,6 +170,10 @@ static inline int amdgpu_ttm_tt_get_user_pages(struct amdgpu_bo *bo,
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
static inline void amdgpu_ttm_tt_discard_user_pages(struct ttm_tt *ttm,
|
||||
struct hmm_range *range)
|
||||
{
|
||||
}
|
||||
static inline bool amdgpu_ttm_tt_get_user_pages_done(struct ttm_tt *ttm,
|
||||
struct hmm_range *range)
|
||||
{
|
||||
|
||||
@@ -395,7 +395,6 @@ static void amdgpu_virt_ras_reserve_bps(struct amdgpu_device *adev)
|
||||
*/
|
||||
if (amdgpu_bo_create_kernel_at(adev, bp << AMDGPU_GPU_PAGE_SHIFT,
|
||||
AMDGPU_GPU_PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM,
|
||||
&bo, NULL))
|
||||
DRM_DEBUG("RAS WARN: reserve vram for retired page %llx fail\n", bp);
|
||||
|
||||
|
||||
@@ -484,25 +484,20 @@ bool amdgpu_vm_need_pipeline_sync(struct amdgpu_ring *ring,
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
unsigned vmhub = ring->funcs->vmhub;
|
||||
struct amdgpu_vmid_mgr *id_mgr = &adev->vm_manager.id_mgr[vmhub];
|
||||
struct amdgpu_vmid *id;
|
||||
bool gds_switch_needed;
|
||||
bool vm_flush_needed = job->vm_needs_flush || ring->has_compute_vm_bug;
|
||||
|
||||
if (job->vmid == 0)
|
||||
return false;
|
||||
id = &id_mgr->ids[job->vmid];
|
||||
gds_switch_needed = ring->funcs->emit_gds_switch && (
|
||||
id->gds_base != job->gds_base ||
|
||||
id->gds_size != job->gds_size ||
|
||||
id->gws_base != job->gws_base ||
|
||||
id->gws_size != job->gws_size ||
|
||||
id->oa_base != job->oa_base ||
|
||||
id->oa_size != job->oa_size);
|
||||
|
||||
if (amdgpu_vmid_had_gpu_reset(adev, id))
|
||||
if (job->vm_needs_flush || ring->has_compute_vm_bug)
|
||||
return true;
|
||||
|
||||
return vm_flush_needed || gds_switch_needed;
|
||||
if (ring->funcs->emit_gds_switch && job->gds_switch_needed)
|
||||
return true;
|
||||
|
||||
if (amdgpu_vmid_had_gpu_reset(adev, &id_mgr->ids[job->vmid]))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -524,27 +519,20 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
|
||||
unsigned vmhub = ring->funcs->vmhub;
|
||||
struct amdgpu_vmid_mgr *id_mgr = &adev->vm_manager.id_mgr[vmhub];
|
||||
struct amdgpu_vmid *id = &id_mgr->ids[job->vmid];
|
||||
bool gds_switch_needed = ring->funcs->emit_gds_switch && (
|
||||
id->gds_base != job->gds_base ||
|
||||
id->gds_size != job->gds_size ||
|
||||
id->gws_base != job->gws_base ||
|
||||
id->gws_size != job->gws_size ||
|
||||
id->oa_base != job->oa_base ||
|
||||
id->oa_size != job->oa_size);
|
||||
bool spm_update_needed = job->spm_update_needed;
|
||||
bool gds_switch_needed = ring->funcs->emit_gds_switch &&
|
||||
job->gds_switch_needed;
|
||||
bool vm_flush_needed = job->vm_needs_flush;
|
||||
struct dma_fence *fence = NULL;
|
||||
bool pasid_mapping_needed = false;
|
||||
unsigned patch_offset = 0;
|
||||
bool update_spm_vmid_needed = (job->vm && (job->vm->reserved_vmid[vmhub] != NULL));
|
||||
int r;
|
||||
|
||||
if (update_spm_vmid_needed && adev->gfx.rlc.funcs->update_spm_vmid)
|
||||
adev->gfx.rlc.funcs->update_spm_vmid(adev, job->vmid);
|
||||
|
||||
if (amdgpu_vmid_had_gpu_reset(adev, id)) {
|
||||
gds_switch_needed = true;
|
||||
vm_flush_needed = true;
|
||||
pasid_mapping_needed = true;
|
||||
spm_update_needed = true;
|
||||
}
|
||||
|
||||
mutex_lock(&id_mgr->lock);
|
||||
@@ -577,6 +565,17 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
|
||||
if (pasid_mapping_needed)
|
||||
amdgpu_gmc_emit_pasid_mapping(ring, job->vmid, job->pasid);
|
||||
|
||||
if (spm_update_needed && adev->gfx.rlc.funcs->update_spm_vmid)
|
||||
adev->gfx.rlc.funcs->update_spm_vmid(adev, job->vmid);
|
||||
|
||||
if (!ring->is_mes_queue && ring->funcs->emit_gds_switch &&
|
||||
gds_switch_needed) {
|
||||
amdgpu_ring_emit_gds_switch(ring, job->vmid, job->gds_base,
|
||||
job->gds_size, job->gws_base,
|
||||
job->gws_size, job->oa_base,
|
||||
job->oa_size);
|
||||
}
|
||||
|
||||
if (vm_flush_needed || pasid_mapping_needed) {
|
||||
r = amdgpu_fence_emit(ring, &fence, NULL, 0);
|
||||
if (r)
|
||||
@@ -601,20 +600,6 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
|
||||
}
|
||||
dma_fence_put(fence);
|
||||
|
||||
if (!ring->is_mes_queue && ring->funcs->emit_gds_switch &&
|
||||
gds_switch_needed) {
|
||||
id->gds_base = job->gds_base;
|
||||
id->gds_size = job->gds_size;
|
||||
id->gws_base = job->gws_base;
|
||||
id->gws_size = job->gws_size;
|
||||
id->oa_base = job->oa_base;
|
||||
id->oa_size = job->oa_size;
|
||||
amdgpu_ring_emit_gds_switch(ring, job->vmid, job->gds_base,
|
||||
job->gds_size, job->gws_base,
|
||||
job->gws_size, job->oa_base,
|
||||
job->oa_size);
|
||||
}
|
||||
|
||||
if (ring->funcs->patch_cond_exec)
|
||||
amdgpu_ring_patch_cond_exec(ring, patch_offset);
|
||||
|
||||
@@ -2383,7 +2368,6 @@ int amdgpu_vm_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
||||
union drm_amdgpu_vm *args = data;
|
||||
struct amdgpu_device *adev = drm_to_adev(dev);
|
||||
struct amdgpu_fpriv *fpriv = filp->driver_priv;
|
||||
long timeout = msecs_to_jiffies(2000);
|
||||
int r;
|
||||
|
||||
switch (args->in.op) {
|
||||
@@ -2395,21 +2379,6 @@ int amdgpu_vm_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
||||
return r;
|
||||
break;
|
||||
case AMDGPU_VM_OP_UNRESERVE_VMID:
|
||||
if (amdgpu_sriov_runtime(adev))
|
||||
timeout = 8 * timeout;
|
||||
|
||||
/* Wait vm idle to make sure the vmid set in SPM_VMID is
|
||||
* not referenced anymore.
|
||||
*/
|
||||
r = amdgpu_bo_reserve(fpriv->vm.root.bo, true);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_vm_wait_idle(&fpriv->vm, timeout);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
amdgpu_bo_unreserve(fpriv->vm.root.bo);
|
||||
amdgpu_vmid_free_reserved(adev, &fpriv->vm, AMDGPU_GFXHUB_0);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -119,9 +119,6 @@ struct amdgpu_bo_vm;
|
||||
/* Reserve 2MB at top/bottom of address space for kernel use */
|
||||
#define AMDGPU_VA_RESERVED_SIZE (2ULL << 20)
|
||||
|
||||
/* max vmids dedicated for process */
|
||||
#define AMDGPU_VM_MAX_RESERVED_VMID 1
|
||||
|
||||
/* See vm_update_mode */
|
||||
#define AMDGPU_VM_USE_CPU_FOR_GFX (1 << 0)
|
||||
#define AMDGPU_VM_USE_CPU_FOR_COMPUTE (1 << 1)
|
||||
@@ -298,8 +295,7 @@ struct amdgpu_vm {
|
||||
struct dma_fence *last_unlocked;
|
||||
|
||||
unsigned int pasid;
|
||||
/* dedicated to vm */
|
||||
struct amdgpu_vmid *reserved_vmid[AMDGPU_MAX_VMHUBS];
|
||||
bool reserved_vmid[AMDGPU_MAX_VMHUBS];
|
||||
|
||||
/* Flag to indicate if VM tables are updated by CPU or GPU (SDMA) */
|
||||
bool use_cpu_for_update;
|
||||
|
||||
@@ -238,8 +238,10 @@ static int amdgpu_vm_sdma_update(struct amdgpu_vm_update_params *p,
|
||||
/* Wait for PD/PT moves to be completed */
|
||||
dma_resv_iter_begin(&cursor, bo->tbo.base.resv, DMA_RESV_USAGE_KERNEL);
|
||||
dma_resv_for_each_fence_unlocked(&cursor, fence) {
|
||||
dma_fence_get(fence);
|
||||
r = drm_sched_job_add_dependency(&p->job->base, fence);
|
||||
if (r) {
|
||||
dma_fence_put(fence);
|
||||
dma_resv_iter_end(&cursor);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -1185,6 +1185,8 @@ static void gmc_v9_0_get_vm_pte(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo_va_mapping *mapping,
|
||||
uint64_t *flags)
|
||||
{
|
||||
struct amdgpu_bo *bo = mapping->bo_va->base.bo;
|
||||
|
||||
*flags &= ~AMDGPU_PTE_EXECUTABLE;
|
||||
*flags |= mapping->flags & AMDGPU_PTE_EXECUTABLE;
|
||||
|
||||
@@ -1196,7 +1198,7 @@ static void gmc_v9_0_get_vm_pte(struct amdgpu_device *adev,
|
||||
*flags &= ~AMDGPU_PTE_VALID;
|
||||
}
|
||||
|
||||
if (mapping->bo_va->base.bo)
|
||||
if (bo && bo->tbo.resource)
|
||||
gmc_v9_0_get_coherence_flags(adev, mapping->bo_va->base.bo,
|
||||
mapping, flags);
|
||||
}
|
||||
|
||||
@@ -1342,7 +1342,8 @@ static int mes_v11_0_late_init(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
if (!amdgpu_in_reset(adev) &&
|
||||
/* it's only intended for use in mes_self_test case, not for s0ix and reset */
|
||||
if (!amdgpu_in_reset(adev) && !adev->in_s0ix &&
|
||||
(adev->ip_versions[GC_HWIP][0] != IP_VERSION(11, 0, 3)))
|
||||
amdgpu_mes_self_test(adev);
|
||||
|
||||
|
||||
@@ -666,6 +666,7 @@ static int soc21_common_early_init(void *handle)
|
||||
AMD_CG_SUPPORT_VCN_MGCG |
|
||||
AMD_CG_SUPPORT_JPEG_MGCG;
|
||||
adev->pg_flags = AMD_PG_SUPPORT_VCN |
|
||||
AMD_PG_SUPPORT_VCN_DPG |
|
||||
AMD_PG_SUPPORT_GFX_PG |
|
||||
AMD_PG_SUPPORT_JPEG;
|
||||
adev->external_rev_id = adev->rev_id + 0x1;
|
||||
|
||||
@@ -689,13 +689,13 @@ void kfd_process_destroy_wq(void)
|
||||
}
|
||||
|
||||
static void kfd_process_free_gpuvm(struct kgd_mem *mem,
|
||||
struct kfd_process_device *pdd, void *kptr)
|
||||
struct kfd_process_device *pdd, void **kptr)
|
||||
{
|
||||
struct kfd_dev *dev = pdd->dev;
|
||||
|
||||
if (kptr) {
|
||||
if (kptr && *kptr) {
|
||||
amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(mem);
|
||||
kptr = NULL;
|
||||
*kptr = NULL;
|
||||
}
|
||||
|
||||
amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(dev->adev, mem, pdd->drm_priv);
|
||||
@@ -795,7 +795,7 @@ static void kfd_process_device_destroy_ib_mem(struct kfd_process_device *pdd)
|
||||
if (!qpd->ib_kaddr || !qpd->ib_base)
|
||||
return;
|
||||
|
||||
kfd_process_free_gpuvm(qpd->ib_mem, pdd, qpd->ib_kaddr);
|
||||
kfd_process_free_gpuvm(qpd->ib_mem, pdd, &qpd->ib_kaddr);
|
||||
}
|
||||
|
||||
struct kfd_process *kfd_create_process(struct file *filep)
|
||||
@@ -1277,7 +1277,7 @@ static void kfd_process_device_destroy_cwsr_dgpu(struct kfd_process_device *pdd)
|
||||
if (!dev->cwsr_enabled || !qpd->cwsr_kaddr || !qpd->cwsr_base)
|
||||
return;
|
||||
|
||||
kfd_process_free_gpuvm(qpd->cwsr_mem, pdd, qpd->cwsr_kaddr);
|
||||
kfd_process_free_gpuvm(qpd->cwsr_mem, pdd, &qpd->cwsr_kaddr);
|
||||
}
|
||||
|
||||
void kfd_process_set_trap_handler(struct qcm_process_device *qpd,
|
||||
@@ -1576,9 +1576,9 @@ int kfd_process_device_init_vm(struct kfd_process_device *pdd,
|
||||
p = pdd->process;
|
||||
dev = pdd->dev;
|
||||
|
||||
ret = amdgpu_amdkfd_gpuvm_acquire_process_vm(
|
||||
dev->adev, drm_file, p->pasid,
|
||||
&p->kgd_process_info, &p->ef);
|
||||
ret = amdgpu_amdkfd_gpuvm_acquire_process_vm(dev->adev, drm_file,
|
||||
&p->kgd_process_info,
|
||||
&p->ef);
|
||||
if (ret) {
|
||||
pr_err("Failed to create process VM object\n");
|
||||
return ret;
|
||||
@@ -1593,13 +1593,19 @@ int kfd_process_device_init_vm(struct kfd_process_device *pdd,
|
||||
if (ret)
|
||||
goto err_init_cwsr;
|
||||
|
||||
ret = amdgpu_amdkfd_gpuvm_set_vm_pasid(dev->adev, drm_file, p->pasid);
|
||||
if (ret)
|
||||
goto err_set_pasid;
|
||||
|
||||
pdd->drm_file = drm_file;
|
||||
|
||||
return 0;
|
||||
|
||||
err_set_pasid:
|
||||
kfd_process_device_destroy_cwsr_dgpu(pdd);
|
||||
err_init_cwsr:
|
||||
kfd_process_device_destroy_ib_mem(pdd);
|
||||
err_reserve_ib_mem:
|
||||
kfd_process_device_free_bos(pdd);
|
||||
pdd->drm_priv = NULL;
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -1503,6 +1503,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
|
||||
case IP_VERSION(3, 0, 1):
|
||||
case IP_VERSION(3, 1, 2):
|
||||
case IP_VERSION(3, 1, 3):
|
||||
case IP_VERSION(3, 1, 4):
|
||||
case IP_VERSION(3, 1, 5):
|
||||
case IP_VERSION(3, 1, 6):
|
||||
init_data.flags.gpu_vm_support = true;
|
||||
|
||||
@@ -55,7 +55,7 @@ void hubbub1_wm_read_state(struct hubbub *hubbub,
|
||||
s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A);
|
||||
s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A);
|
||||
}
|
||||
s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A);
|
||||
s->dram_clk_change = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A);
|
||||
|
||||
s = &wm->sets[1];
|
||||
s->wm_set = 1;
|
||||
@@ -65,7 +65,7 @@ void hubbub1_wm_read_state(struct hubbub *hubbub,
|
||||
s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B);
|
||||
s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B);
|
||||
}
|
||||
s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B);
|
||||
s->dram_clk_change = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B);
|
||||
|
||||
s = &wm->sets[2];
|
||||
s->wm_set = 2;
|
||||
@@ -75,7 +75,7 @@ void hubbub1_wm_read_state(struct hubbub *hubbub,
|
||||
s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C);
|
||||
s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C);
|
||||
}
|
||||
s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C);
|
||||
s->dram_clk_change = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C);
|
||||
|
||||
s = &wm->sets[3];
|
||||
s->wm_set = 3;
|
||||
@@ -85,7 +85,7 @@ void hubbub1_wm_read_state(struct hubbub *hubbub,
|
||||
s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D);
|
||||
s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D);
|
||||
}
|
||||
s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D);
|
||||
s->dram_clk_change = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D);
|
||||
}
|
||||
|
||||
void hubbub1_allow_self_refresh_control(struct hubbub *hubbub, bool allow)
|
||||
|
||||
@@ -159,7 +159,7 @@ static void dcn10_log_hubbub_state(struct dc *dc,
|
||||
DTN_INFO_MICRO_SEC(s->pte_meta_urgent);
|
||||
DTN_INFO_MICRO_SEC(s->sr_enter);
|
||||
DTN_INFO_MICRO_SEC(s->sr_exit);
|
||||
DTN_INFO_MICRO_SEC(s->dram_clk_chanage);
|
||||
DTN_INFO_MICRO_SEC(s->dram_clk_change);
|
||||
DTN_INFO("\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ static unsigned int dcn10_get_hubbub_state(struct dc *dc, char *pBuf, unsigned i
|
||||
memset(&wm, 0, sizeof(struct dcn_hubbub_wm));
|
||||
dc->res_pool->hubbub->funcs->wm_read_state(dc->res_pool->hubbub, &wm);
|
||||
|
||||
chars_printed = snprintf_count(pBuf, remaining_buffer, "wm_set_index,data_urgent,pte_meta_urgent,sr_enter,sr_exit,dram_clk_chanage\n");
|
||||
chars_printed = snprintf_count(pBuf, remaining_buffer, "wm_set_index,data_urgent,pte_meta_urgent,sr_enter,sr_exit,dram_clk_change\n");
|
||||
remaining_buffer -= chars_printed;
|
||||
pBuf += chars_printed;
|
||||
|
||||
@@ -98,7 +98,7 @@ static unsigned int dcn10_get_hubbub_state(struct dc *dc, char *pBuf, unsigned i
|
||||
(s->pte_meta_urgent * frac) / ref_clk_mhz / frac, (s->pte_meta_urgent * frac) / ref_clk_mhz % frac,
|
||||
(s->sr_enter * frac) / ref_clk_mhz / frac, (s->sr_enter * frac) / ref_clk_mhz % frac,
|
||||
(s->sr_exit * frac) / ref_clk_mhz / frac, (s->sr_exit * frac) / ref_clk_mhz % frac,
|
||||
(s->dram_clk_chanage * frac) / ref_clk_mhz / frac, (s->dram_clk_chanage * frac) / ref_clk_mhz % frac);
|
||||
(s->dram_clk_change * frac) / ref_clk_mhz / frac, (s->dram_clk_change * frac) / ref_clk_mhz % frac);
|
||||
remaining_buffer -= chars_printed;
|
||||
pBuf += chars_printed;
|
||||
}
|
||||
|
||||
@@ -500,7 +500,7 @@ void hubbub2_wm_read_state(struct hubbub *hubbub,
|
||||
s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A);
|
||||
s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A);
|
||||
}
|
||||
s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A);
|
||||
s->dram_clk_change = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A);
|
||||
|
||||
s = &wm->sets[1];
|
||||
s->wm_set = 1;
|
||||
@@ -511,7 +511,7 @@ void hubbub2_wm_read_state(struct hubbub *hubbub,
|
||||
s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B);
|
||||
s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B);
|
||||
}
|
||||
s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B);
|
||||
s->dram_clk_change = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B);
|
||||
|
||||
s = &wm->sets[2];
|
||||
s->wm_set = 2;
|
||||
@@ -522,7 +522,7 @@ void hubbub2_wm_read_state(struct hubbub *hubbub,
|
||||
s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C);
|
||||
s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C);
|
||||
}
|
||||
s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C);
|
||||
s->dram_clk_change = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C);
|
||||
|
||||
s = &wm->sets[3];
|
||||
s->wm_set = 3;
|
||||
@@ -533,7 +533,7 @@ void hubbub2_wm_read_state(struct hubbub *hubbub,
|
||||
s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D);
|
||||
s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D);
|
||||
}
|
||||
s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D);
|
||||
s->dram_clk_change = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D);
|
||||
}
|
||||
|
||||
void hubbub2_get_dchub_ref_freq(struct hubbub *hubbub,
|
||||
|
||||
@@ -635,7 +635,7 @@ void hubbub21_wm_read_state(struct hubbub *hubbub,
|
||||
DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, &s->sr_exit);
|
||||
|
||||
REG_GET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A,
|
||||
DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, &s->dram_clk_chanage);
|
||||
DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, &s->dram_clk_change);
|
||||
|
||||
s = &wm->sets[1];
|
||||
s->wm_set = 1;
|
||||
@@ -649,7 +649,7 @@ void hubbub21_wm_read_state(struct hubbub *hubbub,
|
||||
DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, &s->sr_exit);
|
||||
|
||||
REG_GET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B,
|
||||
DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, &s->dram_clk_chanage);
|
||||
DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, &s->dram_clk_change);
|
||||
|
||||
s = &wm->sets[2];
|
||||
s->wm_set = 2;
|
||||
@@ -663,7 +663,7 @@ void hubbub21_wm_read_state(struct hubbub *hubbub,
|
||||
DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, &s->sr_exit);
|
||||
|
||||
REG_GET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C,
|
||||
DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, &s->dram_clk_chanage);
|
||||
DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, &s->dram_clk_change);
|
||||
|
||||
s = &wm->sets[3];
|
||||
s->wm_set = 3;
|
||||
@@ -677,7 +677,7 @@ void hubbub21_wm_read_state(struct hubbub *hubbub,
|
||||
DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, &s->sr_exit);
|
||||
|
||||
REG_GET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D,
|
||||
DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, &s->dram_clk_chanage);
|
||||
DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, &s->dram_clk_change);
|
||||
}
|
||||
|
||||
static void hubbub21_apply_DEDCN21_147_wa(struct hubbub *hubbub)
|
||||
|
||||
@@ -865,7 +865,7 @@ static void hubbub32_wm_read_state(struct hubbub *hubbub,
|
||||
DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, &s->sr_exit);
|
||||
|
||||
REG_GET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A,
|
||||
DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, &s->dram_clk_chanage);
|
||||
DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, &s->dram_clk_change);
|
||||
|
||||
REG_GET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A,
|
||||
DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, &s->usr_retrain);
|
||||
@@ -885,7 +885,7 @@ static void hubbub32_wm_read_state(struct hubbub *hubbub,
|
||||
DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, &s->sr_exit);
|
||||
|
||||
REG_GET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B,
|
||||
DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, &s->dram_clk_chanage);
|
||||
DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, &s->dram_clk_change);
|
||||
|
||||
REG_GET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B,
|
||||
DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, &s->usr_retrain);
|
||||
@@ -905,7 +905,7 @@ static void hubbub32_wm_read_state(struct hubbub *hubbub,
|
||||
DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, &s->sr_exit);
|
||||
|
||||
REG_GET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C,
|
||||
DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, &s->dram_clk_chanage);
|
||||
DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, &s->dram_clk_change);
|
||||
|
||||
REG_GET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C,
|
||||
DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, &s->usr_retrain);
|
||||
@@ -925,7 +925,7 @@ static void hubbub32_wm_read_state(struct hubbub *hubbub,
|
||||
DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, &s->sr_exit);
|
||||
|
||||
REG_GET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D,
|
||||
DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, &s->dram_clk_chanage);
|
||||
DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, &s->dram_clk_change);
|
||||
|
||||
REG_GET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D,
|
||||
DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, &s->usr_retrain);
|
||||
|
||||
@@ -46,7 +46,7 @@ struct dcn_hubbub_wm_set {
|
||||
uint32_t pte_meta_urgent;
|
||||
uint32_t sr_enter;
|
||||
uint32_t sr_exit;
|
||||
uint32_t dram_clk_chanage;
|
||||
uint32_t dram_clk_change;
|
||||
uint32_t usr_retrain;
|
||||
uint32_t fclk_pstate_change;
|
||||
};
|
||||
|
||||
@@ -522,9 +522,9 @@ typedef enum {
|
||||
TEMP_HOTSPOT_M,
|
||||
TEMP_MEM,
|
||||
TEMP_VR_GFX,
|
||||
TEMP_VR_SOC,
|
||||
TEMP_VR_MEM0,
|
||||
TEMP_VR_MEM1,
|
||||
TEMP_VR_SOC,
|
||||
TEMP_VR_U,
|
||||
TEMP_LIQUID0,
|
||||
TEMP_LIQUID1,
|
||||
|
||||
@@ -241,7 +241,8 @@
|
||||
__SMU_DUMMY_MAP(GetGfxOffEntryCount), \
|
||||
__SMU_DUMMY_MAP(LogGfxOffResidency), \
|
||||
__SMU_DUMMY_MAP(SetNumBadMemoryPagesRetired), \
|
||||
__SMU_DUMMY_MAP(SetBadMemoryPagesRetiredFlagsPerChannel),
|
||||
__SMU_DUMMY_MAP(SetBadMemoryPagesRetiredFlagsPerChannel), \
|
||||
__SMU_DUMMY_MAP(AllowGpo),
|
||||
|
||||
#undef __SMU_DUMMY_MAP
|
||||
#define __SMU_DUMMY_MAP(type) SMU_MSG_##type
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#define SMU13_DRIVER_IF_VERSION_INV 0xFFFFFFFF
|
||||
#define SMU13_DRIVER_IF_VERSION_YELLOW_CARP 0x04
|
||||
#define SMU13_DRIVER_IF_VERSION_ALDE 0x08
|
||||
#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_0_0 0x34
|
||||
#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_4 0x07
|
||||
#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_5 0x04
|
||||
#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_0_10 0x32
|
||||
@@ -272,6 +273,9 @@ int smu_v13_0_init_pptable_microcode(struct smu_context *smu);
|
||||
|
||||
int smu_v13_0_run_btc(struct smu_context *smu);
|
||||
|
||||
int smu_v13_0_gpo_control(struct smu_context *smu,
|
||||
bool enablement);
|
||||
|
||||
int smu_v13_0_deep_sleep_control(struct smu_context *smu,
|
||||
bool enablement);
|
||||
|
||||
|
||||
@@ -290,6 +290,8 @@ int smu_v13_0_check_fw_version(struct smu_context *smu)
|
||||
smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_ALDE;
|
||||
break;
|
||||
case IP_VERSION(13, 0, 0):
|
||||
smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_SMU_V13_0_0_0;
|
||||
break;
|
||||
case IP_VERSION(13, 0, 10):
|
||||
smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_SMU_V13_0_0_10;
|
||||
break;
|
||||
@@ -2180,6 +2182,21 @@ int smu_v13_0_run_btc(struct smu_context *smu)
|
||||
return res;
|
||||
}
|
||||
|
||||
int smu_v13_0_gpo_control(struct smu_context *smu,
|
||||
bool enablement)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = smu_cmn_send_smc_msg_with_param(smu,
|
||||
SMU_MSG_AllowGpo,
|
||||
enablement ? 1 : 0,
|
||||
NULL);
|
||||
if (res)
|
||||
dev_err(smu->adev->dev, "SetGpoAllow %d failed!\n", enablement);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int smu_v13_0_deep_sleep_control(struct smu_context *smu,
|
||||
bool enablement)
|
||||
{
|
||||
|
||||
@@ -144,6 +144,7 @@ static struct cmn2asic_msg_mapping smu_v13_0_0_message_map[SMU_MSG_MAX_COUNT] =
|
||||
MSG_MAP(SetNumBadMemoryPagesRetired, PPSMC_MSG_SetNumBadMemoryPagesRetired, 0),
|
||||
MSG_MAP(SetBadMemoryPagesRetiredFlagsPerChannel,
|
||||
PPSMC_MSG_SetBadMemoryPagesRetiredFlagsPerChannel, 0),
|
||||
MSG_MAP(AllowGpo, PPSMC_MSG_SetGpoAllow, 0),
|
||||
};
|
||||
|
||||
static struct cmn2asic_mapping smu_v13_0_0_clk_map[SMU_CLK_COUNT] = {
|
||||
@@ -210,6 +211,8 @@ static struct cmn2asic_mapping smu_v13_0_0_feature_mask_map[SMU_FEATURE_COUNT] =
|
||||
FEA_MAP(MEM_TEMP_READ),
|
||||
FEA_MAP(ATHUB_MMHUB_PG),
|
||||
FEA_MAP(SOC_PCC),
|
||||
[SMU_FEATURE_DPM_VCLK_BIT] = {1, FEATURE_MM_DPM_BIT},
|
||||
[SMU_FEATURE_DPM_DCLK_BIT] = {1, FEATURE_MM_DPM_BIT},
|
||||
};
|
||||
|
||||
static struct cmn2asic_mapping smu_v13_0_0_table_map[SMU_TABLE_COUNT] = {
|
||||
@@ -540,6 +543,23 @@ static int smu_v13_0_0_set_default_dpm_table(struct smu_context *smu)
|
||||
dpm_table);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Update the reported maximum shader clock to the value
|
||||
* which can be guarded to be achieved on all cards. This
|
||||
* is aligned with Window setting. And considering that value
|
||||
* might be not the peak frequency the card can achieve, it
|
||||
* is normal some real-time clock frequency can overtake this
|
||||
* labelled maximum clock frequency(for example in pp_dpm_sclk
|
||||
* sysfs output).
|
||||
*/
|
||||
if (skutable->DriverReportedClocks.GameClockAc &&
|
||||
(dpm_table->dpm_levels[dpm_table->count - 1].value >
|
||||
skutable->DriverReportedClocks.GameClockAc)) {
|
||||
dpm_table->dpm_levels[dpm_table->count - 1].value =
|
||||
skutable->DriverReportedClocks.GameClockAc;
|
||||
dpm_table->max = skutable->DriverReportedClocks.GameClockAc;
|
||||
}
|
||||
} else {
|
||||
dpm_table->count = 1;
|
||||
dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
|
||||
@@ -802,6 +822,57 @@ static int smu_v13_0_0_get_smu_metrics_data(struct smu_context *smu,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int smu_v13_0_0_get_dpm_ultimate_freq(struct smu_context *smu,
|
||||
enum smu_clk_type clk_type,
|
||||
uint32_t *min,
|
||||
uint32_t *max)
|
||||
{
|
||||
struct smu_13_0_dpm_context *dpm_context =
|
||||
smu->smu_dpm.dpm_context;
|
||||
struct smu_13_0_dpm_table *dpm_table;
|
||||
|
||||
switch (clk_type) {
|
||||
case SMU_MCLK:
|
||||
case SMU_UCLK:
|
||||
/* uclk dpm table */
|
||||
dpm_table = &dpm_context->dpm_tables.uclk_table;
|
||||
break;
|
||||
case SMU_GFXCLK:
|
||||
case SMU_SCLK:
|
||||
/* gfxclk dpm table */
|
||||
dpm_table = &dpm_context->dpm_tables.gfx_table;
|
||||
break;
|
||||
case SMU_SOCCLK:
|
||||
/* socclk dpm table */
|
||||
dpm_table = &dpm_context->dpm_tables.soc_table;
|
||||
break;
|
||||
case SMU_FCLK:
|
||||
/* fclk dpm table */
|
||||
dpm_table = &dpm_context->dpm_tables.fclk_table;
|
||||
break;
|
||||
case SMU_VCLK:
|
||||
case SMU_VCLK1:
|
||||
/* vclk dpm table */
|
||||
dpm_table = &dpm_context->dpm_tables.vclk_table;
|
||||
break;
|
||||
case SMU_DCLK:
|
||||
case SMU_DCLK1:
|
||||
/* dclk dpm table */
|
||||
dpm_table = &dpm_context->dpm_tables.dclk_table;
|
||||
break;
|
||||
default:
|
||||
dev_err(smu->adev->dev, "Unsupported clock type!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (min)
|
||||
*min = dpm_table->min;
|
||||
if (max)
|
||||
*max = dpm_table->max;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int smu_v13_0_0_read_sensor(struct smu_context *smu,
|
||||
enum amd_pp_sensors sensor,
|
||||
void *data,
|
||||
@@ -1304,9 +1375,17 @@ static int smu_v13_0_0_populate_umd_state_clk(struct smu_context *smu)
|
||||
&dpm_context->dpm_tables.fclk_table;
|
||||
struct smu_umd_pstate_table *pstate_table =
|
||||
&smu->pstate_table;
|
||||
struct smu_table_context *table_context = &smu->smu_table;
|
||||
PPTable_t *pptable = table_context->driver_pptable;
|
||||
DriverReportedClocks_t driver_clocks =
|
||||
pptable->SkuTable.DriverReportedClocks;
|
||||
|
||||
pstate_table->gfxclk_pstate.min = gfx_table->min;
|
||||
pstate_table->gfxclk_pstate.peak = gfx_table->max;
|
||||
if (driver_clocks.GameClockAc &&
|
||||
(driver_clocks.GameClockAc < gfx_table->max))
|
||||
pstate_table->gfxclk_pstate.peak = driver_clocks.GameClockAc;
|
||||
else
|
||||
pstate_table->gfxclk_pstate.peak = gfx_table->max;
|
||||
|
||||
pstate_table->uclk_pstate.min = mem_table->min;
|
||||
pstate_table->uclk_pstate.peak = mem_table->max;
|
||||
@@ -1323,12 +1402,12 @@ static int smu_v13_0_0_populate_umd_state_clk(struct smu_context *smu)
|
||||
pstate_table->fclk_pstate.min = fclk_table->min;
|
||||
pstate_table->fclk_pstate.peak = fclk_table->max;
|
||||
|
||||
/*
|
||||
* For now, just use the mininum clock frequency.
|
||||
* TODO: update them when the real pstate settings available
|
||||
*/
|
||||
pstate_table->gfxclk_pstate.standard = gfx_table->min;
|
||||
pstate_table->uclk_pstate.standard = mem_table->min;
|
||||
if (driver_clocks.BaseClockAc &&
|
||||
driver_clocks.BaseClockAc < gfx_table->max)
|
||||
pstate_table->gfxclk_pstate.standard = driver_clocks.BaseClockAc;
|
||||
else
|
||||
pstate_table->gfxclk_pstate.standard = gfx_table->max;
|
||||
pstate_table->uclk_pstate.standard = mem_table->max;
|
||||
pstate_table->socclk_pstate.standard = soc_table->min;
|
||||
pstate_table->vclk_pstate.standard = vclk_table->min;
|
||||
pstate_table->dclk_pstate.standard = dclk_table->min;
|
||||
@@ -1362,12 +1441,23 @@ out:
|
||||
static int smu_v13_0_0_get_fan_speed_pwm(struct smu_context *smu,
|
||||
uint32_t *speed)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!speed)
|
||||
return -EINVAL;
|
||||
|
||||
return smu_v13_0_0_get_smu_metrics_data(smu,
|
||||
METRICS_CURR_FANPWM,
|
||||
speed);
|
||||
ret = smu_v13_0_0_get_smu_metrics_data(smu,
|
||||
METRICS_CURR_FANPWM,
|
||||
speed);
|
||||
if (ret) {
|
||||
dev_err(smu->adev->dev, "Failed to get fan speed(PWM)!");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Convert the PMFW output which is in percent to pwm(255) based */
|
||||
*speed = MIN(*speed * 255 / 100, 255);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int smu_v13_0_0_get_fan_speed_rpm(struct smu_context *smu,
|
||||
@@ -1899,7 +1989,7 @@ static const struct pptable_funcs smu_v13_0_0_ppt_funcs = {
|
||||
.get_enabled_mask = smu_cmn_get_enabled_mask,
|
||||
.dpm_set_vcn_enable = smu_v13_0_set_vcn_enable,
|
||||
.dpm_set_jpeg_enable = smu_v13_0_set_jpeg_enable,
|
||||
.get_dpm_ultimate_freq = smu_v13_0_get_dpm_ultimate_freq,
|
||||
.get_dpm_ultimate_freq = smu_v13_0_0_get_dpm_ultimate_freq,
|
||||
.get_vbios_bootup_values = smu_v13_0_get_vbios_bootup_values,
|
||||
.read_sensor = smu_v13_0_0_read_sensor,
|
||||
.feature_is_enabled = smu_cmn_feature_is_enabled,
|
||||
@@ -1947,6 +2037,7 @@ static const struct pptable_funcs smu_v13_0_0_ppt_funcs = {
|
||||
.set_df_cstate = smu_v13_0_0_set_df_cstate,
|
||||
.send_hbm_bad_pages_num = smu_v13_0_0_smu_send_bad_mem_page_num,
|
||||
.send_hbm_bad_channel_flag = smu_v13_0_0_send_bad_mem_channel_flag,
|
||||
.gpo_control = smu_v13_0_gpo_control,
|
||||
};
|
||||
|
||||
void smu_v13_0_0_set_ppt_funcs(struct smu_context *smu)
|
||||
|
||||
@@ -123,6 +123,7 @@ static struct cmn2asic_msg_mapping smu_v13_0_7_message_map[SMU_MSG_MAX_COUNT] =
|
||||
MSG_MAP(SetMGpuFanBoostLimitRpm, PPSMC_MSG_SetMGpuFanBoostLimitRpm, 0),
|
||||
MSG_MAP(DFCstateControl, PPSMC_MSG_SetExternalClientDfCstateAllow, 0),
|
||||
MSG_MAP(ArmD3, PPSMC_MSG_ArmD3, 0),
|
||||
MSG_MAP(AllowGpo, PPSMC_MSG_SetGpoAllow, 0),
|
||||
};
|
||||
|
||||
static struct cmn2asic_mapping smu_v13_0_7_clk_map[SMU_CLK_COUNT] = {
|
||||
@@ -189,6 +190,8 @@ static struct cmn2asic_mapping smu_v13_0_7_feature_mask_map[SMU_FEATURE_COUNT] =
|
||||
FEA_MAP(MEM_TEMP_READ),
|
||||
FEA_MAP(ATHUB_MMHUB_PG),
|
||||
FEA_MAP(SOC_PCC),
|
||||
[SMU_FEATURE_DPM_VCLK_BIT] = {1, FEATURE_MM_DPM_BIT},
|
||||
[SMU_FEATURE_DPM_DCLK_BIT] = {1, FEATURE_MM_DPM_BIT},
|
||||
};
|
||||
|
||||
static struct cmn2asic_mapping smu_v13_0_7_table_map[SMU_TABLE_COUNT] = {
|
||||
@@ -1360,12 +1363,23 @@ static int smu_v13_0_7_populate_umd_state_clk(struct smu_context *smu)
|
||||
static int smu_v13_0_7_get_fan_speed_pwm(struct smu_context *smu,
|
||||
uint32_t *speed)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!speed)
|
||||
return -EINVAL;
|
||||
|
||||
return smu_v13_0_7_get_smu_metrics_data(smu,
|
||||
METRICS_CURR_FANPWM,
|
||||
speed);
|
||||
ret = smu_v13_0_7_get_smu_metrics_data(smu,
|
||||
METRICS_CURR_FANPWM,
|
||||
speed);
|
||||
if (ret) {
|
||||
dev_err(smu->adev->dev, "Failed to get fan speed(PWM)!");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Convert the PMFW output which is in percent to pwm(255) based */
|
||||
*speed = MIN(*speed * 255 / 100, 255);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int smu_v13_0_7_get_fan_speed_rpm(struct smu_context *smu,
|
||||
@@ -1437,7 +1451,7 @@ static int smu_v13_0_7_get_power_limit(struct smu_context *smu,
|
||||
|
||||
static int smu_v13_0_7_get_power_profile_mode(struct smu_context *smu, char *buf)
|
||||
{
|
||||
DpmActivityMonitorCoeffIntExternal_t activity_monitor_external[PP_SMC_POWER_PROFILE_COUNT];
|
||||
DpmActivityMonitorCoeffIntExternal_t *activity_monitor_external;
|
||||
uint32_t i, j, size = 0;
|
||||
int16_t workload_type = 0;
|
||||
int result = 0;
|
||||
@@ -1445,6 +1459,12 @@ static int smu_v13_0_7_get_power_profile_mode(struct smu_context *smu, char *buf
|
||||
if (!buf)
|
||||
return -EINVAL;
|
||||
|
||||
activity_monitor_external = kcalloc(PP_SMC_POWER_PROFILE_COUNT,
|
||||
sizeof(*activity_monitor_external),
|
||||
GFP_KERNEL);
|
||||
if (!activity_monitor_external)
|
||||
return -ENOMEM;
|
||||
|
||||
size += sysfs_emit_at(buf, size, " ");
|
||||
for (i = 0; i <= PP_SMC_POWER_PROFILE_WINDOW3D; i++)
|
||||
size += sysfs_emit_at(buf, size, "%-14s%s", amdgpu_pp_profile_name[i],
|
||||
@@ -1457,15 +1477,17 @@ static int smu_v13_0_7_get_power_profile_mode(struct smu_context *smu, char *buf
|
||||
workload_type = smu_cmn_to_asic_specific_index(smu,
|
||||
CMN2ASIC_MAPPING_WORKLOAD,
|
||||
i);
|
||||
if (workload_type < 0)
|
||||
return -EINVAL;
|
||||
if (workload_type < 0) {
|
||||
result = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = smu_cmn_update_table(smu,
|
||||
SMU_TABLE_ACTIVITY_MONITOR_COEFF, workload_type,
|
||||
(void *)(&activity_monitor_external[i]), false);
|
||||
if (result) {
|
||||
dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
|
||||
return result;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1493,7 +1515,10 @@ do { \
|
||||
PRINT_DPM_MONITOR(Fclk_BoosterFreq);
|
||||
#undef PRINT_DPM_MONITOR
|
||||
|
||||
return size;
|
||||
result = size;
|
||||
out:
|
||||
kfree(activity_monitor_external);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int smu_v13_0_7_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
|
||||
@@ -1688,6 +1713,7 @@ static const struct pptable_funcs smu_v13_0_7_ppt_funcs = {
|
||||
.mode1_reset = smu_v13_0_mode1_reset,
|
||||
.set_mp1_state = smu_v13_0_7_set_mp1_state,
|
||||
.set_df_cstate = smu_v13_0_7_set_df_cstate,
|
||||
.gpo_control = smu_v13_0_gpo_control,
|
||||
};
|
||||
|
||||
void smu_v13_0_7_set_ppt_funcs(struct smu_context *smu)
|
||||
|
||||
@@ -673,8 +673,6 @@ static void intel_enable_dp(struct intel_atomic_state *state,
|
||||
intel_dp_pcon_dsc_configure(intel_dp, pipe_config);
|
||||
intel_dp_start_link_train(intel_dp, pipe_config);
|
||||
intel_dp_stop_link_train(intel_dp, pipe_config);
|
||||
|
||||
intel_audio_codec_enable(encoder, pipe_config, conn_state);
|
||||
}
|
||||
|
||||
static void g4x_enable_dp(struct intel_atomic_state *state,
|
||||
@@ -683,6 +681,7 @@ static void g4x_enable_dp(struct intel_atomic_state *state,
|
||||
const struct drm_connector_state *conn_state)
|
||||
{
|
||||
intel_enable_dp(state, encoder, pipe_config, conn_state);
|
||||
intel_audio_codec_enable(encoder, pipe_config, conn_state);
|
||||
intel_edp_backlight_on(pipe_config, conn_state);
|
||||
}
|
||||
|
||||
@@ -691,6 +690,7 @@ static void vlv_enable_dp(struct intel_atomic_state *state,
|
||||
const struct intel_crtc_state *pipe_config,
|
||||
const struct drm_connector_state *conn_state)
|
||||
{
|
||||
intel_audio_codec_enable(encoder, pipe_config, conn_state);
|
||||
intel_edp_backlight_on(pipe_config, conn_state);
|
||||
}
|
||||
|
||||
|
||||
@@ -157,10 +157,8 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder,
|
||||
&pipe_config->infoframes.hdmi);
|
||||
}
|
||||
|
||||
static void g4x_enable_hdmi(struct intel_atomic_state *state,
|
||||
struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *pipe_config,
|
||||
const struct drm_connector_state *conn_state)
|
||||
static void g4x_hdmi_enable_port(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
struct drm_device *dev = encoder->base.dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
@@ -175,6 +173,16 @@ static void g4x_enable_hdmi(struct intel_atomic_state *state,
|
||||
|
||||
intel_de_write(dev_priv, intel_hdmi->hdmi_reg, temp);
|
||||
intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
|
||||
}
|
||||
|
||||
static void g4x_enable_hdmi(struct intel_atomic_state *state,
|
||||
struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *pipe_config,
|
||||
const struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
|
||||
g4x_hdmi_enable_port(encoder, pipe_config);
|
||||
|
||||
drm_WARN_ON(&dev_priv->drm, pipe_config->has_audio &&
|
||||
!pipe_config->has_hdmi_sink);
|
||||
@@ -294,6 +302,11 @@ static void vlv_enable_hdmi(struct intel_atomic_state *state,
|
||||
const struct intel_crtc_state *pipe_config,
|
||||
const struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
|
||||
drm_WARN_ON(&dev_priv->drm, pipe_config->has_audio &&
|
||||
!pipe_config->has_hdmi_sink);
|
||||
intel_audio_codec_enable(encoder, pipe_config, conn_state);
|
||||
}
|
||||
|
||||
static void intel_disable_hdmi(struct intel_atomic_state *state,
|
||||
@@ -415,7 +428,7 @@ static void vlv_hdmi_pre_enable(struct intel_atomic_state *state,
|
||||
pipe_config->has_infoframe,
|
||||
pipe_config, conn_state);
|
||||
|
||||
g4x_enable_hdmi(state, encoder, pipe_config, conn_state);
|
||||
g4x_hdmi_enable_port(encoder, pipe_config);
|
||||
|
||||
vlv_wait_port_ready(dev_priv, dig_port, 0x0);
|
||||
}
|
||||
@@ -492,7 +505,7 @@ static void chv_hdmi_pre_enable(struct intel_atomic_state *state,
|
||||
pipe_config->has_infoframe,
|
||||
pipe_config, conn_state);
|
||||
|
||||
g4x_enable_hdmi(state, encoder, pipe_config, conn_state);
|
||||
g4x_hdmi_enable_port(encoder, pipe_config);
|
||||
|
||||
vlv_wait_port_ready(dev_priv, dig_port, 0x0);
|
||||
|
||||
|
||||
@@ -3679,61 +3679,6 @@ static void intel_dp_phy_pattern_update(struct intel_dp *intel_dp,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
intel_dp_autotest_phy_ddi_disable(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
|
||||
struct drm_device *dev = dig_port->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct intel_crtc *crtc = to_intel_crtc(dig_port->base.base.crtc);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
u32 trans_ddi_func_ctl_value, trans_conf_value, dp_tp_ctl_value;
|
||||
|
||||
trans_ddi_func_ctl_value = intel_de_read(dev_priv,
|
||||
TRANS_DDI_FUNC_CTL(pipe));
|
||||
trans_conf_value = intel_de_read(dev_priv, PIPECONF(pipe));
|
||||
dp_tp_ctl_value = intel_de_read(dev_priv, TGL_DP_TP_CTL(pipe));
|
||||
|
||||
trans_ddi_func_ctl_value &= ~(TRANS_DDI_FUNC_ENABLE |
|
||||
TGL_TRANS_DDI_PORT_MASK);
|
||||
trans_conf_value &= ~PIPECONF_ENABLE;
|
||||
dp_tp_ctl_value &= ~DP_TP_CTL_ENABLE;
|
||||
|
||||
intel_de_write(dev_priv, PIPECONF(pipe), trans_conf_value);
|
||||
intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(pipe),
|
||||
trans_ddi_func_ctl_value);
|
||||
intel_de_write(dev_priv, TGL_DP_TP_CTL(pipe), dp_tp_ctl_value);
|
||||
}
|
||||
|
||||
static void
|
||||
intel_dp_autotest_phy_ddi_enable(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
|
||||
struct drm_device *dev = dig_port->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
enum port port = dig_port->base.port;
|
||||
struct intel_crtc *crtc = to_intel_crtc(dig_port->base.base.crtc);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
u32 trans_ddi_func_ctl_value, trans_conf_value, dp_tp_ctl_value;
|
||||
|
||||
trans_ddi_func_ctl_value = intel_de_read(dev_priv,
|
||||
TRANS_DDI_FUNC_CTL(pipe));
|
||||
trans_conf_value = intel_de_read(dev_priv, PIPECONF(pipe));
|
||||
dp_tp_ctl_value = intel_de_read(dev_priv, TGL_DP_TP_CTL(pipe));
|
||||
|
||||
trans_ddi_func_ctl_value |= TRANS_DDI_FUNC_ENABLE |
|
||||
TGL_TRANS_DDI_SELECT_PORT(port);
|
||||
trans_conf_value |= PIPECONF_ENABLE;
|
||||
dp_tp_ctl_value |= DP_TP_CTL_ENABLE;
|
||||
|
||||
intel_de_write(dev_priv, PIPECONF(pipe), trans_conf_value);
|
||||
intel_de_write(dev_priv, TGL_DP_TP_CTL(pipe), dp_tp_ctl_value);
|
||||
intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(pipe),
|
||||
trans_ddi_func_ctl_value);
|
||||
}
|
||||
|
||||
static void intel_dp_process_phy_request(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
@@ -3752,14 +3697,10 @@ static void intel_dp_process_phy_request(struct intel_dp *intel_dp,
|
||||
intel_dp_get_adjust_train(intel_dp, crtc_state, DP_PHY_DPRX,
|
||||
link_status);
|
||||
|
||||
intel_dp_autotest_phy_ddi_disable(intel_dp, crtc_state);
|
||||
|
||||
intel_dp_set_signal_levels(intel_dp, crtc_state, DP_PHY_DPRX);
|
||||
|
||||
intel_dp_phy_pattern_update(intel_dp, crtc_state);
|
||||
|
||||
intel_dp_autotest_phy_ddi_enable(intel_dp, crtc_state);
|
||||
|
||||
drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_LANE0_SET,
|
||||
intel_dp->train_set, crtc_state->lane_count);
|
||||
|
||||
|
||||
@@ -785,6 +785,9 @@ bool i915_gem_object_needs_ccs_pages(struct drm_i915_gem_object *obj)
|
||||
if (!HAS_FLAT_CCS(to_i915(obj->base.dev)))
|
||||
return false;
|
||||
|
||||
if (obj->flags & I915_BO_ALLOC_CCS_AUX)
|
||||
return true;
|
||||
|
||||
for (i = 0; i < obj->mm.n_placements; i++) {
|
||||
/* Compression is not allowed for the objects with smem placement */
|
||||
if (obj->mm.placements[i]->type == INTEL_MEMORY_SYSTEM)
|
||||
|
||||
@@ -327,16 +327,18 @@ struct drm_i915_gem_object {
|
||||
* dealing with userspace objects the CPU fault handler is free to ignore this.
|
||||
*/
|
||||
#define I915_BO_ALLOC_GPU_ONLY BIT(6)
|
||||
#define I915_BO_ALLOC_CCS_AUX BIT(7)
|
||||
#define I915_BO_ALLOC_FLAGS (I915_BO_ALLOC_CONTIGUOUS | \
|
||||
I915_BO_ALLOC_VOLATILE | \
|
||||
I915_BO_ALLOC_CPU_CLEAR | \
|
||||
I915_BO_ALLOC_USER | \
|
||||
I915_BO_ALLOC_PM_VOLATILE | \
|
||||
I915_BO_ALLOC_PM_EARLY | \
|
||||
I915_BO_ALLOC_GPU_ONLY)
|
||||
#define I915_BO_READONLY BIT(7)
|
||||
#define I915_TILING_QUIRK_BIT 8 /* unknown swizzling; do not release! */
|
||||
#define I915_BO_PROTECTED BIT(9)
|
||||
I915_BO_ALLOC_GPU_ONLY | \
|
||||
I915_BO_ALLOC_CCS_AUX)
|
||||
#define I915_BO_READONLY BIT(8)
|
||||
#define I915_TILING_QUIRK_BIT 9 /* unknown swizzling; do not release! */
|
||||
#define I915_BO_PROTECTED BIT(10)
|
||||
/**
|
||||
* @mem_flags - Mutable placement-related flags
|
||||
*
|
||||
|
||||
@@ -50,6 +50,7 @@ static int i915_ttm_backup(struct i915_gem_apply_to_region *apply,
|
||||
container_of(bo->bdev, typeof(*i915), bdev);
|
||||
struct drm_i915_gem_object *backup;
|
||||
struct ttm_operation_ctx ctx = {};
|
||||
unsigned int flags;
|
||||
int err = 0;
|
||||
|
||||
if (bo->resource->mem_type == I915_PL_SYSTEM || obj->ttm.backup)
|
||||
@@ -65,7 +66,22 @@ static int i915_ttm_backup(struct i915_gem_apply_to_region *apply,
|
||||
if (obj->flags & I915_BO_ALLOC_PM_VOLATILE)
|
||||
return 0;
|
||||
|
||||
backup = i915_gem_object_create_shmem(i915, obj->base.size);
|
||||
/*
|
||||
* It seems that we might have some framebuffers still pinned at this
|
||||
* stage, but for such objects we might also need to deal with the CCS
|
||||
* aux state. Make sure we force the save/restore of the CCS state,
|
||||
* otherwise we might observe display corruption, when returning from
|
||||
* suspend.
|
||||
*/
|
||||
flags = 0;
|
||||
if (i915_gem_object_needs_ccs_pages(obj)) {
|
||||
WARN_ON_ONCE(!i915_gem_object_is_framebuffer(obj));
|
||||
WARN_ON_ONCE(!pm_apply->allow_gpu);
|
||||
|
||||
flags = I915_BO_ALLOC_CCS_AUX;
|
||||
}
|
||||
backup = i915_gem_object_create_region(i915->mm.regions[INTEL_REGION_SMEM],
|
||||
obj->base.size, 0, flags);
|
||||
if (IS_ERR(backup))
|
||||
return PTR_ERR(backup);
|
||||
|
||||
|
||||
@@ -702,7 +702,7 @@ void intel_gt_mcr_get_ss_steering(struct intel_gt *gt, unsigned int dss,
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_gt_mcr_wait_for_reg_fw - wait until MCR register matches expected state
|
||||
* intel_gt_mcr_wait_for_reg - wait until MCR register matches expected state
|
||||
* @gt: GT structure
|
||||
* @reg: the register to read
|
||||
* @mask: mask to apply to register value
|
||||
|
||||
@@ -342,6 +342,16 @@ static int emit_no_arbitration(struct i915_request *rq)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max_pte_pkt_size(struct i915_request *rq, int pkt)
|
||||
{
|
||||
struct intel_ring *ring = rq->ring;
|
||||
|
||||
pkt = min_t(int, pkt, (ring->space - rq->reserved_space) / sizeof(u32) + 5);
|
||||
pkt = min_t(int, pkt, (ring->size - ring->emit) / sizeof(u32) + 5);
|
||||
|
||||
return pkt;
|
||||
}
|
||||
|
||||
static int emit_pte(struct i915_request *rq,
|
||||
struct sgt_dma *it,
|
||||
enum i915_cache_level cache_level,
|
||||
@@ -388,8 +398,7 @@ static int emit_pte(struct i915_request *rq,
|
||||
return PTR_ERR(cs);
|
||||
|
||||
/* Pack as many PTE updates as possible into a single MI command */
|
||||
pkt = min_t(int, dword_length, ring->space / sizeof(u32) + 5);
|
||||
pkt = min_t(int, pkt, (ring->size - ring->emit) / sizeof(u32) + 5);
|
||||
pkt = max_pte_pkt_size(rq, dword_length);
|
||||
|
||||
hdr = cs;
|
||||
*cs++ = MI_STORE_DATA_IMM | REG_BIT(21); /* as qword elements */
|
||||
@@ -422,8 +431,7 @@ static int emit_pte(struct i915_request *rq,
|
||||
}
|
||||
}
|
||||
|
||||
pkt = min_t(int, dword_rem, ring->space / sizeof(u32) + 5);
|
||||
pkt = min_t(int, pkt, (ring->size - ring->emit) / sizeof(u32) + 5);
|
||||
pkt = max_pte_pkt_size(rq, dword_rem);
|
||||
|
||||
hdr = cs;
|
||||
*cs++ = MI_STORE_DATA_IMM | REG_BIT(21);
|
||||
@@ -829,14 +837,35 @@ intel_context_migrate_copy(struct intel_context *ce,
|
||||
if (err)
|
||||
goto out_rq;
|
||||
|
||||
/*
|
||||
* While we can't always restore/manage the CCS state,
|
||||
* we still need to ensure we don't leak the CCS state
|
||||
* from the previous user, so make sure we overwrite it
|
||||
* with something.
|
||||
*/
|
||||
err = emit_copy_ccs(rq, dst_offset, INDIRECT_ACCESS,
|
||||
dst_offset, DIRECT_ACCESS, len);
|
||||
if (src_is_lmem) {
|
||||
/*
|
||||
* If the src is already in lmem, then we must
|
||||
* be doing an lmem -> lmem transfer, and so
|
||||
* should be safe to directly copy the CCS
|
||||
* state. In this case we have either
|
||||
* initialised the CCS aux state when first
|
||||
* clearing the pages (since it is already
|
||||
* allocated in lmem), or the user has
|
||||
* potentially populated it, in which case we
|
||||
* need to copy the CCS state as-is.
|
||||
*/
|
||||
err = emit_copy_ccs(rq,
|
||||
dst_offset, INDIRECT_ACCESS,
|
||||
src_offset, INDIRECT_ACCESS,
|
||||
len);
|
||||
} else {
|
||||
/*
|
||||
* While we can't always restore/manage the CCS
|
||||
* state, we still need to ensure we don't leak
|
||||
* the CCS state from the previous user, so make
|
||||
* sure we overwrite it with something.
|
||||
*/
|
||||
err = emit_copy_ccs(rq,
|
||||
dst_offset, INDIRECT_ACCESS,
|
||||
dst_offset, DIRECT_ACCESS,
|
||||
len);
|
||||
}
|
||||
|
||||
if (err)
|
||||
goto out_rq;
|
||||
|
||||
|
||||
@@ -1383,6 +1383,9 @@ static u32 oa_context_image_offset(struct intel_context *ce, u32 reg)
|
||||
u32 offset, len = (ce->engine->context_size - PAGE_SIZE) / 4;
|
||||
u32 *state = ce->lrc_reg_state;
|
||||
|
||||
if (drm_WARN_ON(&ce->engine->i915->drm, !state))
|
||||
return U32_MAX;
|
||||
|
||||
for (offset = 0; offset < len; ) {
|
||||
if (IS_MI_LRI_CMD(state[offset])) {
|
||||
/*
|
||||
@@ -1447,7 +1450,8 @@ static int oa_get_render_ctx_id(struct i915_perf_stream *stream)
|
||||
if (IS_ERR(ce))
|
||||
return PTR_ERR(ce);
|
||||
|
||||
if (engine_supports_mi_query(stream->engine)) {
|
||||
if (engine_supports_mi_query(stream->engine) &&
|
||||
HAS_LOGICAL_RING_CONTEXTS(stream->perf->i915)) {
|
||||
/*
|
||||
* We are enabling perf query here. If we don't find the context
|
||||
* offset here, just return an error.
|
||||
|
||||
@@ -824,9 +824,9 @@ void intel_uncore_forcewake_flush(struct intel_uncore *uncore,
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_uncore_forcewake_put__locked - grab forcewake domain references
|
||||
* intel_uncore_forcewake_put__locked - release forcewake domain references
|
||||
* @uncore: the intel_uncore structure
|
||||
* @fw_domains: forcewake domains to get reference on
|
||||
* @fw_domains: forcewake domains to put references
|
||||
*
|
||||
* See intel_uncore_forcewake_put(). This variant places the onus
|
||||
* on the caller to explicitly handle the dev_priv->uncore.lock spinlock.
|
||||
|
||||
@@ -54,7 +54,11 @@ static void lkdtm_CFI_FORWARD_PROTO(void)
|
||||
# ifdef CONFIG_ARM64_BTI_KERNEL
|
||||
# define __no_pac "branch-protection=bti"
|
||||
# else
|
||||
# define __no_pac "branch-protection=none"
|
||||
# ifdef CONFIG_CC_HAS_BRANCH_PROT_PAC_RET
|
||||
# define __no_pac "branch-protection=none"
|
||||
# else
|
||||
# define __no_pac "sign-return-address=none"
|
||||
# endif
|
||||
# endif
|
||||
# define __no_ret_protection __noscs __attribute__((__target__(__no_pac)))
|
||||
#else
|
||||
|
||||
@@ -1002,7 +1002,7 @@ static int drms_uA_update(struct regulator_dev *rdev)
|
||||
/* get input voltage */
|
||||
input_uV = 0;
|
||||
if (rdev->supply)
|
||||
input_uV = regulator_get_voltage(rdev->supply);
|
||||
input_uV = regulator_get_voltage_rdev(rdev->supply->rdev);
|
||||
if (input_uV <= 0)
|
||||
input_uV = rdev->constraints->input_uV;
|
||||
|
||||
@@ -5540,7 +5540,7 @@ regulator_register(struct device *dev,
|
||||
|
||||
/* register with sysfs */
|
||||
rdev->dev.class = ®ulator_class;
|
||||
rdev->dev.parent = dev;
|
||||
rdev->dev.parent = config->dev;
|
||||
dev_set_name(&rdev->dev, "regulator.%lu",
|
||||
(unsigned long) atomic_inc_return(®ulator_no));
|
||||
dev_set_drvdata(&rdev->dev, rdev);
|
||||
|
||||
@@ -333,13 +333,26 @@ static int fsl_spi_prepare_message(struct spi_controller *ctlr,
|
||||
{
|
||||
struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(ctlr);
|
||||
struct spi_transfer *t;
|
||||
struct spi_transfer *first;
|
||||
|
||||
first = list_first_entry(&m->transfers, struct spi_transfer,
|
||||
transfer_list);
|
||||
|
||||
/*
|
||||
* In CPU mode, optimize large byte transfers to use larger
|
||||
* bits_per_word values to reduce number of interrupts taken.
|
||||
*
|
||||
* Some glitches can appear on the SPI clock when the mode changes.
|
||||
* Check that there is no speed change during the transfer and set it up
|
||||
* now to change the mode without having a chip-select asserted.
|
||||
*/
|
||||
if (!(mpc8xxx_spi->flags & SPI_CPM_MODE)) {
|
||||
list_for_each_entry(t, &m->transfers, transfer_list) {
|
||||
list_for_each_entry(t, &m->transfers, transfer_list) {
|
||||
if (t->speed_hz != first->speed_hz) {
|
||||
dev_err(&m->spi->dev,
|
||||
"speed_hz cannot change during message.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!(mpc8xxx_spi->flags & SPI_CPM_MODE)) {
|
||||
if (t->len < 256 || t->bits_per_word != 8)
|
||||
continue;
|
||||
if ((t->len & 3) == 0)
|
||||
@@ -348,7 +361,7 @@ static int fsl_spi_prepare_message(struct spi_controller *ctlr,
|
||||
t->bits_per_word = 16;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return fsl_spi_setup_transfer(m->spi, first);
|
||||
}
|
||||
|
||||
static int fsl_spi_transfer_one(struct spi_controller *controller,
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <linux/fs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/idr.h>
|
||||
#include <net/9p/9p.h>
|
||||
#include <net/9p/client.h>
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/cred.h>
|
||||
#include <linux/parser.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <net/9p/9p.h>
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include <linux/string.h>
|
||||
#include <linux/inet.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/swap.h>
|
||||
#include <linux/uio.h>
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include <linux/string.h>
|
||||
#include <linux/inet.h>
|
||||
#include <linux/namei.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <net/9p/9p.h>
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include <linux/string.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/inet.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uio.h>
|
||||
#include <linux/fscache.h>
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/utsname.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/uio.h>
|
||||
#include <linux/slab.h>
|
||||
#include <net/9p/9p.h>
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include <linux/string.h>
|
||||
#include <linux/inet.h>
|
||||
#include <linux/namei.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/xattr.h>
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include <linux/string.h>
|
||||
#include <linux/inet.h>
|
||||
#include <linux/namei.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/xattr.h>
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include <linux/inet.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/mount.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/statfs.h>
|
||||
|
||||
@@ -126,6 +126,7 @@ config PSTORE_CONSOLE
|
||||
config PSTORE_PMSG
|
||||
bool "Log user space messages"
|
||||
depends on PSTORE
|
||||
select RT_MUTEXES
|
||||
help
|
||||
When the option is enabled, pstore will export a character
|
||||
interface /dev/pmsg0 to log user space messages. On reboot
|
||||
|
||||
+4
-3
@@ -7,9 +7,10 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/rtmutex.h>
|
||||
#include "internal.h"
|
||||
|
||||
static DEFINE_MUTEX(pmsg_lock);
|
||||
static DEFINE_RT_MUTEX(pmsg_lock);
|
||||
|
||||
static ssize_t write_pmsg(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
@@ -28,9 +29,9 @@ static ssize_t write_pmsg(struct file *file, const char __user *buf,
|
||||
if (!access_ok(buf, count))
|
||||
return -EFAULT;
|
||||
|
||||
mutex_lock(&pmsg_lock);
|
||||
rt_mutex_lock(&pmsg_lock);
|
||||
ret = psinfo->write_user(&record, buf);
|
||||
mutex_unlock(&pmsg_lock);
|
||||
rt_mutex_unlock(&pmsg_lock);
|
||||
return ret ? ret : count;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -680,7 +680,7 @@ static int ramoops_parse_dt(struct platform_device *pdev,
|
||||
field = value; \
|
||||
}
|
||||
|
||||
parse_u32("mem-type", pdata->record_size, pdata->mem_type);
|
||||
parse_u32("mem-type", pdata->mem_type, pdata->mem_type);
|
||||
parse_u32("record-size", pdata->record_size, 0);
|
||||
parse_u32("console-size", pdata->console_size, 0);
|
||||
parse_u32("ftrace-size", pdata->ftrace_size, 0);
|
||||
|
||||
@@ -531,6 +531,7 @@ struct p9_rstatfs {
|
||||
* @offset: used by marshalling routines to track current position in buffer
|
||||
* @capacity: used by marshalling routines to track total malloc'd capacity
|
||||
* @sdata: payload
|
||||
* @zc: whether zero-copy is used
|
||||
*
|
||||
* &p9_fcall represents the structure for all 9P RPC
|
||||
* transactions. Requests are packaged into fcalls, and reponses
|
||||
@@ -549,6 +550,7 @@ struct p9_fcall {
|
||||
|
||||
struct kmem_cache *cache;
|
||||
u8 *sdata;
|
||||
bool zc;
|
||||
};
|
||||
|
||||
int p9_errstr2errno(char *errstr, int len);
|
||||
|
||||
@@ -258,6 +258,7 @@ struct hda_codec {
|
||||
unsigned int link_down_at_suspend:1; /* link down at runtime suspend */
|
||||
unsigned int relaxed_resume:1; /* don't resume forcibly for jack */
|
||||
unsigned int forced_resume:1; /* forced resume for jack */
|
||||
unsigned int no_stream_clean_at_suspend:1; /* do not clean streams at suspend */
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
unsigned long power_on_acct;
|
||||
|
||||
@@ -75,6 +75,8 @@ struct hdac_ext_stream *snd_hdac_ext_stream_assign(struct hdac_bus *bus,
|
||||
struct snd_pcm_substream *substream,
|
||||
int type);
|
||||
void snd_hdac_ext_stream_release(struct hdac_ext_stream *hext_stream, int type);
|
||||
struct hdac_ext_stream *snd_hdac_ext_cstream_assign(struct hdac_bus *bus,
|
||||
struct snd_compr_stream *cstream);
|
||||
void snd_hdac_ext_stream_decouple_locked(struct hdac_bus *bus,
|
||||
struct hdac_ext_stream *hext_stream, bool decouple);
|
||||
void snd_hdac_ext_stream_decouple(struct hdac_bus *bus,
|
||||
|
||||
@@ -41,9 +41,6 @@ UBSAN_SANITIZE_kcov.o := n
|
||||
KMSAN_SANITIZE_kcov.o := n
|
||||
CFLAGS_kcov.o := $(call cc-option, -fno-conserve-stack) -fno-stack-protector
|
||||
|
||||
# Don't instrument error handlers
|
||||
CFLAGS_REMOVE_cfi.o := $(CC_FLAGS_CFI)
|
||||
|
||||
obj-y += sched/
|
||||
obj-y += locking/
|
||||
obj-y += power/
|
||||
|
||||
@@ -560,6 +560,8 @@ static struct page *__dma_alloc_pages(struct device *dev, size_t size,
|
||||
return NULL;
|
||||
if (WARN_ON_ONCE(gfp & (__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM)))
|
||||
return NULL;
|
||||
if (WARN_ON_ONCE(gfp & __GFP_COMP))
|
||||
return NULL;
|
||||
|
||||
size = PAGE_ALIGN(size);
|
||||
if (dma_alloc_direct(dev, ops))
|
||||
@@ -645,6 +647,8 @@ struct sg_table *dma_alloc_noncontiguous(struct device *dev, size_t size,
|
||||
|
||||
if (WARN_ON_ONCE(attrs & ~DMA_ATTR_ALLOC_SINGLE_PAGES))
|
||||
return NULL;
|
||||
if (WARN_ON_ONCE(gfp & __GFP_COMP))
|
||||
return NULL;
|
||||
|
||||
if (ops && ops->alloc_noncontiguous)
|
||||
sgt = ops->alloc_noncontiguous(dev, size, dir, gfp, attrs);
|
||||
|
||||
+4
-2
@@ -931,6 +931,7 @@ void __noreturn make_task_dead(int signr)
|
||||
* Then do everything else.
|
||||
*/
|
||||
struct task_struct *tsk = current;
|
||||
unsigned int limit;
|
||||
|
||||
if (unlikely(in_interrupt()))
|
||||
panic("Aiee, killing interrupt handler!");
|
||||
@@ -954,8 +955,9 @@ void __noreturn make_task_dead(int signr)
|
||||
* To make sure this can't happen, place an upper bound on how often the
|
||||
* kernel may oops without panic().
|
||||
*/
|
||||
if (atomic_inc_return(&oops_count) >= READ_ONCE(oops_limit) && oops_limit)
|
||||
panic("Oopsed too often (kernel.oops_limit is %d)", oops_limit);
|
||||
limit = READ_ONCE(oops_limit);
|
||||
if (atomic_inc_return(&oops_count) >= limit && limit)
|
||||
panic("Oopsed too often (kernel.oops_limit is %d)", limit);
|
||||
|
||||
/*
|
||||
* We're taking recursive faults here in make_task_dead. Safest is to just
|
||||
|
||||
+5
-2
@@ -232,12 +232,15 @@ static void panic_print_sys_info(bool console_flush)
|
||||
|
||||
void check_panic_on_warn(const char *origin)
|
||||
{
|
||||
unsigned int limit;
|
||||
|
||||
if (panic_on_warn)
|
||||
panic("%s: panic_on_warn set ...\n", origin);
|
||||
|
||||
if (atomic_inc_return(&warn_count) >= READ_ONCE(warn_limit) && warn_limit)
|
||||
limit = READ_ONCE(warn_limit);
|
||||
if (atomic_inc_return(&warn_count) >= limit && limit)
|
||||
panic("%s: system warned too often (kernel.warn_limit is %d)",
|
||||
origin, warn_limit);
|
||||
origin, limit);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+22
-11
@@ -297,6 +297,11 @@ p9_tag_alloc(struct p9_client *c, int8_t type, uint t_size, uint r_size,
|
||||
p9pdu_reset(&req->rc);
|
||||
req->t_err = 0;
|
||||
req->status = REQ_STATUS_ALLOC;
|
||||
/* refcount needs to be set to 0 before inserting into the idr
|
||||
* so p9_tag_lookup does not accept a request that is not fully
|
||||
* initialized. refcount_set to 2 below will mark request ready.
|
||||
*/
|
||||
refcount_set(&req->refcount, 0);
|
||||
init_waitqueue_head(&req->wq);
|
||||
INIT_LIST_HEAD(&req->req_list);
|
||||
|
||||
@@ -438,7 +443,7 @@ void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status)
|
||||
* the status change is visible to another thread
|
||||
*/
|
||||
smp_wmb();
|
||||
req->status = status;
|
||||
WRITE_ONCE(req->status, status);
|
||||
|
||||
wake_up(&req->wq);
|
||||
p9_debug(P9_DEBUG_MUX, "wakeup: %d\n", req->tc.tag);
|
||||
@@ -514,10 +519,9 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
|
||||
int ecode;
|
||||
|
||||
err = p9_parse_header(&req->rc, NULL, &type, NULL, 0);
|
||||
if (req->rc.size >= c->msize) {
|
||||
p9_debug(P9_DEBUG_ERROR,
|
||||
"requested packet size too big: %d\n",
|
||||
req->rc.size);
|
||||
if (req->rc.size > req->rc.capacity && !req->rc.zc) {
|
||||
pr_err("requested packet size too big: %d does not fit %zu (type=%d)\n",
|
||||
req->rc.size, req->rc.capacity, req->rc.id);
|
||||
return -EIO;
|
||||
}
|
||||
/* dump the response from server
|
||||
@@ -600,7 +604,7 @@ static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq)
|
||||
/* if we haven't received a response for oldreq,
|
||||
* remove it from the list
|
||||
*/
|
||||
if (oldreq->status == REQ_STATUS_SENT) {
|
||||
if (READ_ONCE(oldreq->status) == REQ_STATUS_SENT) {
|
||||
if (c->trans_mod->cancelled)
|
||||
c->trans_mod->cancelled(c, oldreq);
|
||||
}
|
||||
@@ -680,6 +684,9 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
|
||||
if (IS_ERR(req))
|
||||
return req;
|
||||
|
||||
req->tc.zc = false;
|
||||
req->rc.zc = false;
|
||||
|
||||
if (signal_pending(current)) {
|
||||
sigpending = 1;
|
||||
clear_thread_flag(TIF_SIGPENDING);
|
||||
@@ -697,7 +704,8 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
|
||||
}
|
||||
again:
|
||||
/* Wait for the response */
|
||||
err = wait_event_killable(req->wq, req->status >= REQ_STATUS_RCVD);
|
||||
err = wait_event_killable(req->wq,
|
||||
READ_ONCE(req->status) >= REQ_STATUS_RCVD);
|
||||
|
||||
/* Make sure our req is coherent with regard to updates in other
|
||||
* threads - echoes to wmb() in the callback
|
||||
@@ -711,7 +719,7 @@ again:
|
||||
goto again;
|
||||
}
|
||||
|
||||
if (req->status == REQ_STATUS_ERROR) {
|
||||
if (READ_ONCE(req->status) == REQ_STATUS_ERROR) {
|
||||
p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err);
|
||||
err = req->t_err;
|
||||
}
|
||||
@@ -724,7 +732,7 @@ again:
|
||||
p9_client_flush(c, req);
|
||||
|
||||
/* if we received the response anyway, don't signal error */
|
||||
if (req->status == REQ_STATUS_RCVD)
|
||||
if (READ_ONCE(req->status) == REQ_STATUS_RCVD)
|
||||
err = 0;
|
||||
}
|
||||
recalc_sigpending:
|
||||
@@ -778,6 +786,9 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type,
|
||||
if (IS_ERR(req))
|
||||
return req;
|
||||
|
||||
req->tc.zc = true;
|
||||
req->rc.zc = true;
|
||||
|
||||
if (signal_pending(current)) {
|
||||
sigpending = 1;
|
||||
clear_thread_flag(TIF_SIGPENDING);
|
||||
@@ -793,7 +804,7 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type,
|
||||
if (err != -ERESTARTSYS)
|
||||
goto recalc_sigpending;
|
||||
}
|
||||
if (req->status == REQ_STATUS_ERROR) {
|
||||
if (READ_ONCE(req->status) == REQ_STATUS_ERROR) {
|
||||
p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err);
|
||||
err = req->t_err;
|
||||
}
|
||||
@@ -806,7 +817,7 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type,
|
||||
p9_client_flush(c, req);
|
||||
|
||||
/* if we received the response anyway, don't signal error */
|
||||
if (req->status == REQ_STATUS_RCVD)
|
||||
if (READ_ONCE(req->status) == REQ_STATUS_RCVD)
|
||||
err = 0;
|
||||
}
|
||||
recalc_sigpending:
|
||||
|
||||
+6
-7
@@ -20,7 +20,6 @@
|
||||
#include <linux/un.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/inet.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/parser.h>
|
||||
#include <linux/slab.h>
|
||||
@@ -202,11 +201,11 @@ static void p9_conn_cancel(struct p9_conn *m, int err)
|
||||
|
||||
list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) {
|
||||
list_move(&req->req_list, &cancel_list);
|
||||
req->status = REQ_STATUS_ERROR;
|
||||
WRITE_ONCE(req->status, REQ_STATUS_ERROR);
|
||||
}
|
||||
list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) {
|
||||
list_move(&req->req_list, &cancel_list);
|
||||
req->status = REQ_STATUS_ERROR;
|
||||
WRITE_ONCE(req->status, REQ_STATUS_ERROR);
|
||||
}
|
||||
|
||||
spin_unlock(&m->req_lock);
|
||||
@@ -467,7 +466,7 @@ static void p9_write_work(struct work_struct *work)
|
||||
|
||||
req = list_entry(m->unsent_req_list.next, struct p9_req_t,
|
||||
req_list);
|
||||
req->status = REQ_STATUS_SENT;
|
||||
WRITE_ONCE(req->status, REQ_STATUS_SENT);
|
||||
p9_debug(P9_DEBUG_TRANS, "move req %p\n", req);
|
||||
list_move_tail(&req->req_list, &m->req_list);
|
||||
|
||||
@@ -676,7 +675,7 @@ static int p9_fd_request(struct p9_client *client, struct p9_req_t *req)
|
||||
return m->err;
|
||||
|
||||
spin_lock(&m->req_lock);
|
||||
req->status = REQ_STATUS_UNSENT;
|
||||
WRITE_ONCE(req->status, REQ_STATUS_UNSENT);
|
||||
list_add_tail(&req->req_list, &m->unsent_req_list);
|
||||
spin_unlock(&m->req_lock);
|
||||
|
||||
@@ -703,7 +702,7 @@ static int p9_fd_cancel(struct p9_client *client, struct p9_req_t *req)
|
||||
|
||||
if (req->status == REQ_STATUS_UNSENT) {
|
||||
list_del(&req->req_list);
|
||||
req->status = REQ_STATUS_FLSHD;
|
||||
WRITE_ONCE(req->status, REQ_STATUS_FLSHD);
|
||||
p9_req_put(client, req);
|
||||
ret = 0;
|
||||
}
|
||||
@@ -732,7 +731,7 @@ static int p9_fd_cancelled(struct p9_client *client, struct p9_req_t *req)
|
||||
* remove it from the list.
|
||||
*/
|
||||
list_del(&req->req_list);
|
||||
req->status = REQ_STATUS_FLSHD;
|
||||
WRITE_ONCE(req->status, REQ_STATUS_FLSHD);
|
||||
spin_unlock(&m->req_lock);
|
||||
|
||||
p9_req_put(client, req);
|
||||
|
||||
+2
-3
@@ -21,7 +21,6 @@
|
||||
#include <linux/un.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/inet.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/parser.h>
|
||||
#include <linux/semaphore.h>
|
||||
@@ -507,7 +506,7 @@ dont_need_post_recv:
|
||||
* because doing if after could erase the REQ_STATUS_RCVD
|
||||
* status in case of a very fast reply.
|
||||
*/
|
||||
req->status = REQ_STATUS_SENT;
|
||||
WRITE_ONCE(req->status, REQ_STATUS_SENT);
|
||||
err = ib_post_send(rdma->qp, &wr, NULL);
|
||||
if (err)
|
||||
goto send_error;
|
||||
@@ -517,7 +516,7 @@ dont_need_post_recv:
|
||||
|
||||
/* Handle errors that happened during or while preparing the send: */
|
||||
send_error:
|
||||
req->status = REQ_STATUS_ERROR;
|
||||
WRITE_ONCE(req->status, REQ_STATUS_ERROR);
|
||||
kfree(c);
|
||||
p9_debug(P9_DEBUG_ERROR, "Error %d in rdma_request()\n", err);
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include <linux/un.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/inet.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/slab.h>
|
||||
@@ -263,7 +262,7 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req)
|
||||
|
||||
p9_debug(P9_DEBUG_TRANS, "9p debug: virtio request\n");
|
||||
|
||||
req->status = REQ_STATUS_SENT;
|
||||
WRITE_ONCE(req->status, REQ_STATUS_SENT);
|
||||
req_retry:
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
|
||||
@@ -469,7 +468,7 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req,
|
||||
inlen = n;
|
||||
}
|
||||
}
|
||||
req->status = REQ_STATUS_SENT;
|
||||
WRITE_ONCE(req->status, REQ_STATUS_SENT);
|
||||
req_retry_pinned:
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
|
||||
@@ -532,9 +531,10 @@ req_retry_pinned:
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
kicked = 1;
|
||||
p9_debug(P9_DEBUG_TRANS, "virtio request kicked\n");
|
||||
err = wait_event_killable(req->wq, req->status >= REQ_STATUS_RCVD);
|
||||
err = wait_event_killable(req->wq,
|
||||
READ_ONCE(req->status) >= REQ_STATUS_RCVD);
|
||||
// RERROR needs reply (== error string) in static data
|
||||
if (req->status == REQ_STATUS_RCVD &&
|
||||
if (READ_ONCE(req->status) == REQ_STATUS_RCVD &&
|
||||
unlikely(req->rc.sdata[4] == P9_RERROR))
|
||||
handle_rerror(req, in_hdr_len, offs, in_pages);
|
||||
|
||||
|
||||
+5
-3
@@ -157,7 +157,7 @@ again:
|
||||
&masked_prod, masked_cons,
|
||||
XEN_9PFS_RING_SIZE(ring));
|
||||
|
||||
p9_req->status = REQ_STATUS_SENT;
|
||||
WRITE_ONCE(p9_req->status, REQ_STATUS_SENT);
|
||||
virt_wmb(); /* write ring before updating pointer */
|
||||
prod += size;
|
||||
ring->intf->out_prod = prod;
|
||||
@@ -212,11 +212,13 @@ static void p9_xen_response(struct work_struct *work)
|
||||
dev_warn(&priv->dev->dev,
|
||||
"requested packet size too big: %d for tag %d with capacity %zd\n",
|
||||
h.size, h.tag, req->rc.capacity);
|
||||
req->status = REQ_STATUS_ERROR;
|
||||
WRITE_ONCE(req->status, REQ_STATUS_ERROR);
|
||||
goto recv_error;
|
||||
}
|
||||
|
||||
memcpy(&req->rc, &h, sizeof(h));
|
||||
req->rc.size = h.size;
|
||||
req->rc.id = h.id;
|
||||
req->rc.tag = h.tag;
|
||||
req->rc.offset = 0;
|
||||
|
||||
masked_cons = xen_9pfs_mask(cons, XEN_9PFS_RING_SIZE(ring));
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ FLAGS="--very-quiet"
|
||||
# inspected there.
|
||||
#
|
||||
# --profile will not output if --very-quiet is used, so avoid it.
|
||||
echo $SPFLAGS | egrep -e "--profile|--show-trying" 2>&1 > /dev/null
|
||||
echo $SPFLAGS | grep -E -e "--profile|--show-trying" 2>&1 > /dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
FLAGS="--quiet"
|
||||
fi
|
||||
|
||||
@@ -257,6 +257,9 @@ config INIT_ON_FREE_DEFAULT_ON
|
||||
|
||||
config CC_HAS_ZERO_CALL_USED_REGS
|
||||
def_bool $(cc-option,-fzero-call-used-regs=used-gpr)
|
||||
# https://github.com/ClangBuiltLinux/linux/issues/1766
|
||||
# https://github.com/llvm/llvm-project/issues/59242
|
||||
depends on !CC_IS_CLANG || CLANG_VERSION > 150006
|
||||
|
||||
config ZERO_CALL_USED_REGS
|
||||
bool "Enable register zeroing on function exit"
|
||||
|
||||
+18
-12
@@ -122,21 +122,11 @@ static void loadpin_sb_free_security(struct super_block *mnt_sb)
|
||||
}
|
||||
}
|
||||
|
||||
static int loadpin_read_file(struct file *file, enum kernel_read_file_id id,
|
||||
bool contents)
|
||||
static int loadpin_check(struct file *file, enum kernel_read_file_id id)
|
||||
{
|
||||
struct super_block *load_root;
|
||||
const char *origin = kernel_read_file_id_str(id);
|
||||
|
||||
/*
|
||||
* If we will not know that we'll be seeing the full contents
|
||||
* then we cannot trust a load will be complete and unchanged
|
||||
* off disk. Treat all contents=false hooks as if there were
|
||||
* no associated file struct.
|
||||
*/
|
||||
if (!contents)
|
||||
file = NULL;
|
||||
|
||||
/* If the file id is excluded, ignore the pinning. */
|
||||
if ((unsigned int)id < ARRAY_SIZE(ignore_read_file_id) &&
|
||||
ignore_read_file_id[id]) {
|
||||
@@ -192,9 +182,25 @@ static int loadpin_read_file(struct file *file, enum kernel_read_file_id id,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int loadpin_read_file(struct file *file, enum kernel_read_file_id id,
|
||||
bool contents)
|
||||
{
|
||||
/*
|
||||
* LoadPin only cares about the _origin_ of a file, not its
|
||||
* contents, so we can ignore the "are full contents available"
|
||||
* argument here.
|
||||
*/
|
||||
return loadpin_check(file, id);
|
||||
}
|
||||
|
||||
static int loadpin_load_data(enum kernel_load_data_id id, bool contents)
|
||||
{
|
||||
return loadpin_read_file(NULL, (enum kernel_read_file_id) id, contents);
|
||||
/*
|
||||
* LoadPin only cares about the _origin_ of a file, not its
|
||||
* contents, so a NULL file is passed, and we can ignore the
|
||||
* state of "contents".
|
||||
*/
|
||||
return loadpin_check(NULL, (enum kernel_read_file_id) id);
|
||||
}
|
||||
|
||||
static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = {
|
||||
|
||||
@@ -542,7 +542,7 @@ static void *snd_dma_noncontig_alloc(struct snd_dma_buffer *dmab, size_t size)
|
||||
void *p;
|
||||
|
||||
sgt = dma_alloc_noncontiguous(dmab->dev.dev, size, dmab->dev.dir,
|
||||
DEFAULT_GFP | __GFP_COMP, 0);
|
||||
DEFAULT_GFP, 0);
|
||||
#ifdef CONFIG_SND_DMA_SGBUF
|
||||
if (!sgt && !get_dma_ops(dmab->dev.dev)) {
|
||||
if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG)
|
||||
@@ -820,7 +820,7 @@ static void *snd_dma_noncoherent_alloc(struct snd_dma_buffer *dmab, size_t size)
|
||||
void *p;
|
||||
|
||||
p = dma_alloc_noncoherent(dmab->dev.dev, size, &dmab->addr,
|
||||
dmab->dev.dir, DEFAULT_GFP | __GFP_COMP);
|
||||
dmab->dev.dir, DEFAULT_GFP);
|
||||
if (p)
|
||||
dmab->dev.need_sync = dma_need_sync(dmab->dev.dev, dmab->addr);
|
||||
return p;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/hda_register.h>
|
||||
#include <sound/hdaudio_ext.h>
|
||||
#include <sound/compress_driver.h>
|
||||
|
||||
/**
|
||||
* snd_hdac_ext_stream_init - initialize each stream (aka device)
|
||||
@@ -367,3 +368,43 @@ void snd_hdac_ext_stream_release(struct hdac_ext_stream *hext_stream, int type)
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_release);
|
||||
|
||||
/**
|
||||
* snd_hdac_ext_cstream_assign - assign a host stream for compress
|
||||
* @bus: HD-audio core bus
|
||||
* @cstream: Compress stream to assign
|
||||
*
|
||||
* Assign an unused host stream for the given compress stream.
|
||||
* If no stream is free, NULL is returned. Stream is decoupled
|
||||
* before assignment.
|
||||
*/
|
||||
struct hdac_ext_stream *snd_hdac_ext_cstream_assign(struct hdac_bus *bus,
|
||||
struct snd_compr_stream *cstream)
|
||||
{
|
||||
struct hdac_ext_stream *res = NULL;
|
||||
struct hdac_stream *hstream;
|
||||
|
||||
spin_lock_irq(&bus->reg_lock);
|
||||
list_for_each_entry(hstream, &bus->stream_list, list) {
|
||||
struct hdac_ext_stream *hext_stream = stream_to_hdac_ext_stream(hstream);
|
||||
|
||||
if (hstream->direction != cstream->direction)
|
||||
continue;
|
||||
|
||||
if (!hstream->opened) {
|
||||
res = hext_stream;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (res) {
|
||||
snd_hdac_ext_stream_decouple_locked(bus, res, true);
|
||||
res->hstream.opened = 1;
|
||||
res->hstream.running = 0;
|
||||
res->hstream.cstream = cstream;
|
||||
}
|
||||
spin_unlock_irq(&bus->reg_lock);
|
||||
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_ext_cstream_assign);
|
||||
|
||||
@@ -578,8 +578,8 @@ int snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status,
|
||||
sd_status = snd_hdac_stream_readb(azx_dev, SD_STS);
|
||||
snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK);
|
||||
handled |= 1 << azx_dev->index;
|
||||
if (!azx_dev->substream || !azx_dev->running ||
|
||||
!(sd_status & SD_INT_COMPLETE))
|
||||
if ((!azx_dev->substream && !azx_dev->cstream) ||
|
||||
!azx_dev->running || !(sd_status & SD_INT_COMPLETE))
|
||||
continue;
|
||||
if (ack)
|
||||
ack(bus, azx_dev);
|
||||
|
||||
+35
-19
@@ -7,6 +7,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/clocksource.h>
|
||||
#include <sound/compress_driver.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/hdaudio.h>
|
||||
@@ -487,11 +488,23 @@ int snd_hdac_stream_setup_periods(struct hdac_stream *azx_dev)
|
||||
{
|
||||
struct hdac_bus *bus = azx_dev->bus;
|
||||
struct snd_pcm_substream *substream = azx_dev->substream;
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_compr_stream *cstream = azx_dev->cstream;
|
||||
struct snd_pcm_runtime *runtime = NULL;
|
||||
struct snd_dma_buffer *dmab;
|
||||
__le32 *bdl;
|
||||
int i, ofs, periods, period_bytes;
|
||||
int pos_adj, pos_align;
|
||||
|
||||
if (substream) {
|
||||
runtime = substream->runtime;
|
||||
dmab = snd_pcm_get_dma_buf(substream);
|
||||
} else if (cstream) {
|
||||
dmab = snd_pcm_get_dma_buf(cstream);
|
||||
} else {
|
||||
WARN(1, "No substream or cstream assigned\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* reset BDL address */
|
||||
snd_hdac_stream_writel(azx_dev, SD_BDLPL, 0);
|
||||
snd_hdac_stream_writel(azx_dev, SD_BDLPU, 0);
|
||||
@@ -505,7 +518,7 @@ int snd_hdac_stream_setup_periods(struct hdac_stream *azx_dev)
|
||||
azx_dev->frags = 0;
|
||||
|
||||
pos_adj = bus->bdl_pos_adj;
|
||||
if (!azx_dev->no_period_wakeup && pos_adj > 0) {
|
||||
if (runtime && !azx_dev->no_period_wakeup && pos_adj > 0) {
|
||||
pos_align = pos_adj;
|
||||
pos_adj = DIV_ROUND_UP(pos_adj * runtime->rate, 48000);
|
||||
if (!pos_adj)
|
||||
@@ -518,8 +531,7 @@ int snd_hdac_stream_setup_periods(struct hdac_stream *azx_dev)
|
||||
pos_adj);
|
||||
pos_adj = 0;
|
||||
} else {
|
||||
ofs = setup_bdle(bus, snd_pcm_get_dma_buf(substream),
|
||||
azx_dev,
|
||||
ofs = setup_bdle(bus, dmab, azx_dev,
|
||||
&bdl, ofs, pos_adj, true);
|
||||
if (ofs < 0)
|
||||
goto error;
|
||||
@@ -529,13 +541,11 @@ int snd_hdac_stream_setup_periods(struct hdac_stream *azx_dev)
|
||||
|
||||
for (i = 0; i < periods; i++) {
|
||||
if (i == periods - 1 && pos_adj)
|
||||
ofs = setup_bdle(bus, snd_pcm_get_dma_buf(substream),
|
||||
azx_dev, &bdl, ofs,
|
||||
period_bytes - pos_adj, 0);
|
||||
ofs = setup_bdle(bus, dmab, azx_dev,
|
||||
&bdl, ofs, period_bytes - pos_adj, 0);
|
||||
else
|
||||
ofs = setup_bdle(bus, snd_pcm_get_dma_buf(substream),
|
||||
azx_dev, &bdl, ofs,
|
||||
period_bytes,
|
||||
ofs = setup_bdle(bus, dmab, azx_dev,
|
||||
&bdl, ofs, period_bytes,
|
||||
!azx_dev->no_period_wakeup);
|
||||
if (ofs < 0)
|
||||
goto error;
|
||||
@@ -560,26 +570,32 @@ EXPORT_SYMBOL_GPL(snd_hdac_stream_setup_periods);
|
||||
int snd_hdac_stream_set_params(struct hdac_stream *azx_dev,
|
||||
unsigned int format_val)
|
||||
{
|
||||
|
||||
unsigned int bufsize, period_bytes;
|
||||
struct snd_pcm_substream *substream = azx_dev->substream;
|
||||
struct snd_pcm_runtime *runtime;
|
||||
struct snd_compr_stream *cstream = azx_dev->cstream;
|
||||
unsigned int bufsize, period_bytes;
|
||||
unsigned int no_period_wakeup;
|
||||
int err;
|
||||
|
||||
if (!substream)
|
||||
if (substream) {
|
||||
bufsize = snd_pcm_lib_buffer_bytes(substream);
|
||||
period_bytes = snd_pcm_lib_period_bytes(substream);
|
||||
no_period_wakeup = substream->runtime->no_period_wakeup;
|
||||
} else if (cstream) {
|
||||
bufsize = cstream->runtime->buffer_size;
|
||||
period_bytes = cstream->runtime->fragment_size;
|
||||
no_period_wakeup = 0;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
runtime = substream->runtime;
|
||||
bufsize = snd_pcm_lib_buffer_bytes(substream);
|
||||
period_bytes = snd_pcm_lib_period_bytes(substream);
|
||||
}
|
||||
|
||||
if (bufsize != azx_dev->bufsize ||
|
||||
period_bytes != azx_dev->period_bytes ||
|
||||
format_val != azx_dev->format_val ||
|
||||
runtime->no_period_wakeup != azx_dev->no_period_wakeup) {
|
||||
no_period_wakeup != azx_dev->no_period_wakeup) {
|
||||
azx_dev->bufsize = bufsize;
|
||||
azx_dev->period_bytes = period_bytes;
|
||||
azx_dev->format_val = format_val;
|
||||
azx_dev->no_period_wakeup = runtime->no_period_wakeup;
|
||||
azx_dev->no_period_wakeup = no_period_wakeup;
|
||||
err = snd_hdac_stream_setup_periods(azx_dev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
@@ -363,15 +363,6 @@ snd_azf3328_codec_inw(const struct snd_azf3328_codec_data *codec, unsigned reg)
|
||||
return inw(codec->io_base + reg);
|
||||
}
|
||||
|
||||
static inline void
|
||||
snd_azf3328_codec_outl(const struct snd_azf3328_codec_data *codec,
|
||||
unsigned reg,
|
||||
u32 value
|
||||
)
|
||||
{
|
||||
outl(value, codec->io_base + reg);
|
||||
}
|
||||
|
||||
static inline void
|
||||
snd_azf3328_codec_outl_multi(const struct snd_azf3328_codec_data *codec,
|
||||
unsigned reg, const void *buffer, int count
|
||||
|
||||
@@ -2886,7 +2886,8 @@ static unsigned int hda_call_codec_suspend(struct hda_codec *codec)
|
||||
snd_hdac_enter_pm(&codec->core);
|
||||
if (codec->patch_ops.suspend)
|
||||
codec->patch_ops.suspend(codec);
|
||||
hda_cleanup_all_streams(codec);
|
||||
if (!codec->no_stream_clean_at_suspend)
|
||||
hda_cleanup_all_streams(codec);
|
||||
state = hda_set_power_state(codec, AC_PWRST_D3);
|
||||
update_power_acct(codec, true);
|
||||
snd_hdac_leave_pm(&codec->core);
|
||||
|
||||
+117
-3
@@ -1738,6 +1738,7 @@ static void silent_stream_enable(struct hda_codec *codec,
|
||||
|
||||
switch (spec->silent_stream_type) {
|
||||
case SILENT_STREAM_KAE:
|
||||
silent_stream_enable_i915(codec, per_pin);
|
||||
silent_stream_set_kae(codec, per_pin, true);
|
||||
break;
|
||||
case SILENT_STREAM_I915:
|
||||
@@ -1975,6 +1976,7 @@ static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid)
|
||||
static const struct snd_pci_quirk force_connect_list[] = {
|
||||
SND_PCI_QUIRK(0x103c, 0x870f, "HP", 1),
|
||||
SND_PCI_QUIRK(0x103c, 0x871a, "HP", 1),
|
||||
SND_PCI_QUIRK(0x103c, 0x8711, "HP", 1),
|
||||
SND_PCI_QUIRK(0x1462, 0xec94, "MS-7C94", 1),
|
||||
SND_PCI_QUIRK(0x8086, 0x2081, "Intel NUC 10", 1),
|
||||
{}
|
||||
@@ -2878,9 +2880,33 @@ static int i915_hsw_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
|
||||
hda_nid_t pin_nid, int dev_id, u32 stream_tag,
|
||||
int format)
|
||||
{
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
int pin_idx = pin_id_to_pin_index(codec, pin_nid, dev_id);
|
||||
struct hdmi_spec_per_pin *per_pin;
|
||||
int res;
|
||||
|
||||
if (pin_idx < 0)
|
||||
per_pin = NULL;
|
||||
else
|
||||
per_pin = get_pin(spec, pin_idx);
|
||||
|
||||
haswell_verify_D0(codec, cvt_nid, pin_nid);
|
||||
return hdmi_setup_stream(codec, cvt_nid, pin_nid, dev_id,
|
||||
stream_tag, format);
|
||||
|
||||
if (spec->silent_stream_type == SILENT_STREAM_KAE && per_pin && per_pin->silent_stream) {
|
||||
silent_stream_set_kae(codec, per_pin, false);
|
||||
/* wait for pending transfers in codec to clear */
|
||||
usleep_range(100, 200);
|
||||
}
|
||||
|
||||
res = hdmi_setup_stream(codec, cvt_nid, pin_nid, dev_id,
|
||||
stream_tag, format);
|
||||
|
||||
if (spec->silent_stream_type == SILENT_STREAM_KAE && per_pin && per_pin->silent_stream) {
|
||||
usleep_range(100, 200);
|
||||
silent_stream_set_kae(codec, per_pin, true);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* pin_cvt_fixup ops override for HSW+ and VLV+ */
|
||||
@@ -2900,6 +2926,88 @@ static void i915_pin_cvt_fixup(struct hda_codec *codec,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int i915_adlp_hdmi_suspend(struct hda_codec *codec)
|
||||
{
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
bool silent_streams = false;
|
||||
int pin_idx, res;
|
||||
|
||||
res = generic_hdmi_suspend(codec);
|
||||
|
||||
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
|
||||
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
|
||||
|
||||
if (per_pin->silent_stream) {
|
||||
silent_streams = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (silent_streams && spec->silent_stream_type == SILENT_STREAM_KAE) {
|
||||
/*
|
||||
* stream-id should remain programmed when codec goes
|
||||
* to runtime suspend
|
||||
*/
|
||||
codec->no_stream_clean_at_suspend = 1;
|
||||
|
||||
/*
|
||||
* the system might go to S3, in which case keep-alive
|
||||
* must be reprogrammed upon resume
|
||||
*/
|
||||
codec->forced_resume = 1;
|
||||
|
||||
codec_dbg(codec, "HDMI: KAE active at suspend\n");
|
||||
} else {
|
||||
codec->no_stream_clean_at_suspend = 0;
|
||||
codec->forced_resume = 0;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int i915_adlp_hdmi_resume(struct hda_codec *codec)
|
||||
{
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
int pin_idx, res;
|
||||
|
||||
res = generic_hdmi_resume(codec);
|
||||
|
||||
/* KAE not programmed at suspend, nothing to do here */
|
||||
if (!codec->no_stream_clean_at_suspend)
|
||||
return res;
|
||||
|
||||
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
|
||||
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
|
||||
|
||||
/*
|
||||
* If system was in suspend with monitor connected,
|
||||
* the codec setting may have been lost. Re-enable
|
||||
* keep-alive.
|
||||
*/
|
||||
if (per_pin->silent_stream) {
|
||||
unsigned int param;
|
||||
|
||||
param = snd_hda_codec_read(codec, per_pin->cvt_nid, 0,
|
||||
AC_VERB_GET_CONV, 0);
|
||||
if (!param) {
|
||||
codec_dbg(codec, "HDMI: KAE: restore stream id\n");
|
||||
silent_stream_enable_i915(codec, per_pin);
|
||||
}
|
||||
|
||||
param = snd_hda_codec_read(codec, per_pin->cvt_nid, 0,
|
||||
AC_VERB_GET_DIGI_CONVERT_1, 0);
|
||||
if (!(param & (AC_DIG3_KAE << 16))) {
|
||||
codec_dbg(codec, "HDMI: KAE: restore DIG3_KAE\n");
|
||||
silent_stream_set_kae(codec, per_pin, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* precondition and allocation for Intel codecs */
|
||||
static int alloc_intel_hdmi(struct hda_codec *codec)
|
||||
{
|
||||
@@ -3030,8 +3138,14 @@ static int patch_i915_adlp_hdmi(struct hda_codec *codec)
|
||||
if (!res) {
|
||||
spec = codec->spec;
|
||||
|
||||
if (spec->silent_stream_type)
|
||||
if (spec->silent_stream_type) {
|
||||
spec->silent_stream_type = SILENT_STREAM_KAE;
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
codec->patch_ops.resume = i915_adlp_hdmi_resume;
|
||||
codec->patch_ops.suspend = i915_adlp_hdmi_suspend;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
@@ -10999,6 +10999,17 @@ static void alc897_fixup_lenovo_headset_mic(struct hda_codec *codec,
|
||||
}
|
||||
}
|
||||
|
||||
static void alc897_fixup_lenovo_headset_mode(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
struct alc_spec *spec = codec->spec;
|
||||
|
||||
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
|
||||
spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
|
||||
spec->gen.hp_automute_hook = alc897_hp_automute_hook;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct coef_fw alc668_coefs[] = {
|
||||
WRITE_COEF(0x01, 0xbebe), WRITE_COEF(0x02, 0xaaaa), WRITE_COEF(0x03, 0x0),
|
||||
WRITE_COEF(0x04, 0x0180), WRITE_COEF(0x06, 0x0), WRITE_COEF(0x07, 0x0f80),
|
||||
@@ -11082,6 +11093,8 @@ enum {
|
||||
ALC897_FIXUP_LENOVO_HEADSET_MIC,
|
||||
ALC897_FIXUP_HEADSET_MIC_PIN,
|
||||
ALC897_FIXUP_HP_HSMIC_VERB,
|
||||
ALC897_FIXUP_LENOVO_HEADSET_MODE,
|
||||
ALC897_FIXUP_HEADSET_MIC_PIN2,
|
||||
};
|
||||
|
||||
static const struct hda_fixup alc662_fixups[] = {
|
||||
@@ -11508,6 +11521,19 @@ static const struct hda_fixup alc662_fixups[] = {
|
||||
{ }
|
||||
},
|
||||
},
|
||||
[ALC897_FIXUP_LENOVO_HEADSET_MODE] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc897_fixup_lenovo_headset_mode,
|
||||
},
|
||||
[ALC897_FIXUP_HEADSET_MIC_PIN2] = {
|
||||
.type = HDA_FIXUP_PINS,
|
||||
.v.pins = (const struct hda_pintbl[]) {
|
||||
{ 0x1a, 0x01a11140 }, /* use as headset mic, without its own jack detect */
|
||||
{ }
|
||||
},
|
||||
.chained = true,
|
||||
.chain_id = ALC897_FIXUP_LENOVO_HEADSET_MODE
|
||||
},
|
||||
};
|
||||
|
||||
static const struct snd_pci_quirk alc662_fixup_tbl[] = {
|
||||
@@ -11560,6 +11586,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x17aa, 0x32cb, "Lenovo ThinkCentre M70", ALC897_FIXUP_HEADSET_MIC_PIN),
|
||||
SND_PCI_QUIRK(0x17aa, 0x32cf, "Lenovo ThinkCentre M950", ALC897_FIXUP_HEADSET_MIC_PIN),
|
||||
SND_PCI_QUIRK(0x17aa, 0x32f7, "Lenovo ThinkCentre M90", ALC897_FIXUP_HEADSET_MIC_PIN),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3742, "Lenovo TianYi510Pro-14IOB", ALC897_FIXUP_HEADSET_MIC_PIN2),
|
||||
SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
|
||||
SND_PCI_QUIRK(0x1849, 0x5892, "ASRock B150M", ALC892_FIXUP_ASROCK_MOBO),
|
||||
|
||||
@@ -253,7 +253,7 @@ MODULE_DEVICE_TABLE(of, lochnagar_of_match);
|
||||
static struct platform_driver lochnagar_sc_codec_driver = {
|
||||
.driver = {
|
||||
.name = "lochnagar-soundcard",
|
||||
.of_match_table = of_match_ptr(lochnagar_of_match),
|
||||
.of_match_table = lochnagar_of_match,
|
||||
},
|
||||
|
||||
.probe = lochnagar_sc_probe,
|
||||
|
||||
@@ -3311,8 +3311,6 @@ static int rt5670_i2c_probe(struct i2c_client *i2c)
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
pm_runtime_put(&i2c->dev);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
pm_runtime_disable(&i2c->dev);
|
||||
|
||||
@@ -130,12 +130,6 @@ static inline void wcd_enable_clsh_block(struct wcd_clsh_ctrl *ctrl,
|
||||
ctrl->clsh_users = 0;
|
||||
}
|
||||
|
||||
static inline bool wcd_clsh_enable_status(struct snd_soc_component *comp)
|
||||
{
|
||||
return snd_soc_component_read(comp, WCD9XXX_A_CDC_CLSH_CRC) &
|
||||
WCD9XXX_A_CDC_CLSH_CRC_CLK_EN_MASK;
|
||||
}
|
||||
|
||||
static inline void wcd_clsh_set_buck_mode(struct snd_soc_component *comp,
|
||||
int mode)
|
||||
{
|
||||
|
||||
@@ -3853,7 +3853,12 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
|
||||
} else {
|
||||
dev_dbg(component->dev, "Jack not detected\n");
|
||||
|
||||
/* Release wm8994->accdet_lock to avoid deadlock:
|
||||
* cancel_delayed_work_sync() takes wm8994->mic_work internal
|
||||
* lock and wm1811_mic_work takes wm8994->accdet_lock */
|
||||
mutex_unlock(&wm8994->accdet_lock);
|
||||
cancel_delayed_work_sync(&wm8994->mic_work);
|
||||
mutex_lock(&wm8994->accdet_lock);
|
||||
|
||||
snd_soc_component_update_bits(component, WM8958_MICBIAS2,
|
||||
WM8958_MICB2_DISCH, WM8958_MICB2_DISCH);
|
||||
|
||||
@@ -75,8 +75,7 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = scnprintf(buf, PAGE_SIZE, "PDCR: %08x\nPTCR: %08x\n",
|
||||
pdcr, ptcr);
|
||||
ret = sysfs_emit(buf, "PDCR: %08x\nPTCR: %08x\n", pdcr, ptcr);
|
||||
|
||||
if (ptcr & IMX_AUDMUX_V2_PTCR_TFSDIR)
|
||||
ret += scnprintf(buf + ret, PAGE_SIZE - ret,
|
||||
|
||||
@@ -485,8 +485,10 @@ static int __graph_for_each_link(struct asoc_simple_priv *priv,
|
||||
of_node_put(codec_ep);
|
||||
of_node_put(codec_port);
|
||||
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
of_node_put(cpu_ep);
|
||||
return ret;
|
||||
}
|
||||
|
||||
codec_port_old = codec_port;
|
||||
}
|
||||
|
||||
@@ -217,6 +217,7 @@ config SND_SOC_INTEL_AVS
|
||||
select SND_SOC_ACPI if ACPI
|
||||
select SND_SOC_TOPOLOGY
|
||||
select SND_SOC_HDA
|
||||
select SND_SOC_COMPRESS if DEBUG_FS
|
||||
select SND_HDA_EXT_CORE
|
||||
select SND_HDA_DSP_LOADER
|
||||
select SND_INTEL_DSP_CONFIG
|
||||
|
||||
@@ -9,6 +9,10 @@ snd-soc-avs-objs += trace.o
|
||||
# tell define_trace.h where to find the trace header
|
||||
CFLAGS_trace.o := -I$(src)
|
||||
|
||||
ifneq ($(CONFIG_DEBUG_FS),)
|
||||
snd-soc-avs-objs += probes.o debugfs.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_SND_SOC_INTEL_AVS) += snd-soc-avs.o
|
||||
|
||||
# Machine support
|
||||
|
||||
@@ -13,8 +13,9 @@
|
||||
#include "path.h"
|
||||
#include "topology.h"
|
||||
|
||||
static int apl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_period,
|
||||
u32 fifo_full_period, unsigned long resource_mask, u32 *priorities)
|
||||
static int __maybe_unused
|
||||
apl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_period,
|
||||
u32 fifo_full_period, unsigned long resource_mask, u32 *priorities)
|
||||
{
|
||||
struct apl_log_state_info *info;
|
||||
u32 size, num_cores = adev->hw_cfg.dsp_cores;
|
||||
@@ -50,7 +51,6 @@ static int apl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32
|
||||
static int apl_log_buffer_status(struct avs_dev *adev, union avs_notify_msg *msg)
|
||||
{
|
||||
struct apl_log_buffer_layout layout;
|
||||
unsigned long flags;
|
||||
void __iomem *addr, *buf;
|
||||
|
||||
addr = avs_log_buffer_addr(adev, msg->log.core);
|
||||
@@ -59,26 +59,20 @@ static int apl_log_buffer_status(struct avs_dev *adev, union avs_notify_msg *msg
|
||||
|
||||
memcpy_fromio(&layout, addr, sizeof(layout));
|
||||
|
||||
spin_lock_irqsave(&adev->dbg.trace_lock, flags);
|
||||
if (!kfifo_initialized(&adev->dbg.trace_fifo))
|
||||
if (!avs_logging_fw(adev))
|
||||
/* consume the logs regardless of consumer presence */
|
||||
goto update_read_ptr;
|
||||
|
||||
buf = apl_log_payload_addr(addr);
|
||||
|
||||
if (layout.read_ptr > layout.write_ptr) {
|
||||
__kfifo_fromio_locked(&adev->dbg.trace_fifo, buf + layout.read_ptr,
|
||||
apl_log_payload_size(adev) - layout.read_ptr,
|
||||
&adev->dbg.fifo_lock);
|
||||
avs_dump_fw_log(adev, buf + layout.read_ptr,
|
||||
apl_log_payload_size(adev) - layout.read_ptr);
|
||||
layout.read_ptr = 0;
|
||||
}
|
||||
__kfifo_fromio_locked(&adev->dbg.trace_fifo, buf + layout.read_ptr,
|
||||
layout.write_ptr - layout.read_ptr, &adev->dbg.fifo_lock);
|
||||
|
||||
wake_up(&adev->dbg.trace_waitq);
|
||||
avs_dump_fw_log_wakeup(adev, buf + layout.read_ptr, layout.write_ptr - layout.read_ptr);
|
||||
|
||||
update_read_ptr:
|
||||
spin_unlock_irqrestore(&adev->dbg.trace_lock, flags);
|
||||
writel(layout.write_ptr, addr);
|
||||
return 0;
|
||||
}
|
||||
@@ -140,7 +134,7 @@ static int apl_coredump(struct avs_dev *adev, union avs_notify_msg *msg)
|
||||
* gathered before dumping stack
|
||||
*/
|
||||
lbs_msg.log.core = msg->ext.coredump.core_id;
|
||||
avs_dsp_op(adev, log_buffer_status, &lbs_msg);
|
||||
avs_log_buffer_status_locked(adev, &lbs_msg);
|
||||
}
|
||||
|
||||
pos = dump + AVS_FW_REGS_SIZE;
|
||||
@@ -243,10 +237,10 @@ const struct avs_dsp_ops apl_dsp_ops = {
|
||||
.load_basefw = avs_hda_load_basefw,
|
||||
.load_lib = avs_hda_load_library,
|
||||
.transfer_mods = avs_hda_transfer_modules,
|
||||
.enable_logs = apl_enable_logs,
|
||||
.log_buffer_offset = skl_log_buffer_offset,
|
||||
.log_buffer_status = apl_log_buffer_status,
|
||||
.coredump = apl_coredump,
|
||||
.d0ix_toggle = apl_d0ix_toggle,
|
||||
.set_d0ix = apl_set_d0ix,
|
||||
AVS_SET_ENABLE_LOGS_OP(apl)
|
||||
};
|
||||
|
||||
+66
-14
@@ -9,6 +9,7 @@
|
||||
#ifndef __SOUND_SOC_INTEL_AVS_H
|
||||
#define __SOUND_SOC_INTEL_AVS_H
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/kfifo.h>
|
||||
@@ -93,16 +94,6 @@ struct avs_fw_entry {
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
struct avs_debug {
|
||||
struct kfifo trace_fifo;
|
||||
spinlock_t fifo_lock; /* serialize I/O for trace_fifo */
|
||||
spinlock_t trace_lock; /* serialize debug window I/O between each LOG_BUFFER_STATUS */
|
||||
wait_queue_head_t trace_waitq;
|
||||
u32 aging_timer_period;
|
||||
u32 fifo_full_timer_period;
|
||||
u32 logged_resources; /* context dependent: core or library */
|
||||
};
|
||||
|
||||
/*
|
||||
* struct avs_dev - Intel HD-Audio driver data
|
||||
*
|
||||
@@ -146,7 +137,18 @@ struct avs_dev {
|
||||
spinlock_t path_list_lock;
|
||||
struct mutex path_mutex;
|
||||
|
||||
struct avs_debug dbg;
|
||||
spinlock_t trace_lock; /* serialize debug window I/O between each LOG_BUFFER_STATUS */
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct kfifo trace_fifo;
|
||||
wait_queue_head_t trace_waitq;
|
||||
u32 aging_timer_period;
|
||||
u32 fifo_full_timer_period;
|
||||
u32 logged_resources; /* context dependent: core or library */
|
||||
struct dentry *debugfs_root;
|
||||
/* probes */
|
||||
struct hdac_ext_stream *extractor;
|
||||
unsigned int num_probe_streams;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* from hda_bus to avs_dev */
|
||||
@@ -321,6 +323,9 @@ struct avs_soc_component {
|
||||
|
||||
extern const struct snd_soc_dai_ops avs_dai_fe_ops;
|
||||
|
||||
int avs_soc_component_register(struct device *dev, const char *name,
|
||||
const struct snd_soc_component_driver *drv,
|
||||
struct snd_soc_dai_driver *cpu_dais, int num_cpu_dais);
|
||||
int avs_dmic_platform_register(struct avs_dev *adev, const char *name);
|
||||
int avs_i2s_platform_register(struct avs_dev *adev, const char *name, unsigned long port_mask,
|
||||
unsigned long *tdms);
|
||||
@@ -331,9 +336,6 @@ void avs_unregister_all_boards(struct avs_dev *adev);
|
||||
|
||||
/* Firmware tracing helpers */
|
||||
|
||||
unsigned int __kfifo_fromio_locked(struct kfifo *fifo, const void __iomem *src, unsigned int len,
|
||||
spinlock_t *lock);
|
||||
|
||||
#define avs_log_buffer_size(adev) \
|
||||
((adev)->fw_cfg.trace_log_bytes / (adev)->hw_cfg.dsp_cores)
|
||||
|
||||
@@ -344,6 +346,18 @@ unsigned int __kfifo_fromio_locked(struct kfifo *fifo, const void __iomem *src,
|
||||
(avs_sram_addr(adev, AVS_DEBUG_WINDOW) + __offset); \
|
||||
})
|
||||
|
||||
static inline int avs_log_buffer_status_locked(struct avs_dev *adev, union avs_notify_msg *msg)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&adev->trace_lock, flags);
|
||||
ret = avs_dsp_op(adev, log_buffer_status, msg);
|
||||
spin_unlock_irqrestore(&adev->trace_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct apl_log_buffer_layout {
|
||||
u32 read_ptr;
|
||||
u32 write_ptr;
|
||||
@@ -356,4 +370,42 @@ struct apl_log_buffer_layout {
|
||||
#define apl_log_payload_addr(addr) \
|
||||
(addr + sizeof(struct apl_log_buffer_layout))
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
#define AVS_SET_ENABLE_LOGS_OP(name) \
|
||||
.enable_logs = name##_enable_logs
|
||||
|
||||
bool avs_logging_fw(struct avs_dev *adev);
|
||||
void avs_dump_fw_log(struct avs_dev *adev, const void __iomem *src, unsigned int len);
|
||||
void avs_dump_fw_log_wakeup(struct avs_dev *adev, const void __iomem *src, unsigned int len);
|
||||
|
||||
int avs_probe_platform_register(struct avs_dev *adev, const char *name);
|
||||
|
||||
void avs_debugfs_init(struct avs_dev *adev);
|
||||
void avs_debugfs_exit(struct avs_dev *adev);
|
||||
#else
|
||||
#define AVS_SET_ENABLE_LOGS_OP(name)
|
||||
|
||||
static inline bool avs_logging_fw(struct avs_dev *adev)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void avs_dump_fw_log(struct avs_dev *adev, const void __iomem *src, unsigned int len)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
avs_dump_fw_log_wakeup(struct avs_dev *adev, const void __iomem *src, unsigned int len)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int avs_probe_platform_register(struct avs_dev *adev, const char *name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void avs_debugfs_init(struct avs_dev *adev) { }
|
||||
static inline void avs_debugfs_exit(struct avs_dev *adev) { }
|
||||
#endif
|
||||
|
||||
#endif /* __SOUND_SOC_INTEL_AVS_H */
|
||||
|
||||
@@ -291,6 +291,33 @@ static void board_pdev_unregister(void *data)
|
||||
platform_device_unregister(data);
|
||||
}
|
||||
|
||||
static int __maybe_unused avs_register_probe_board(struct avs_dev *adev)
|
||||
{
|
||||
struct platform_device *board;
|
||||
struct snd_soc_acpi_mach mach = {{0}};
|
||||
int ret;
|
||||
|
||||
ret = avs_probe_platform_register(adev, "probe-platform");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mach.mach_params.platform = "probe-platform";
|
||||
|
||||
board = platform_device_register_data(NULL, "avs_probe_mb", PLATFORM_DEVID_NONE,
|
||||
(const void *)&mach, sizeof(mach));
|
||||
if (IS_ERR(board)) {
|
||||
dev_err(adev->dev, "probe board register failed\n");
|
||||
return PTR_ERR(board);
|
||||
}
|
||||
|
||||
ret = devm_add_action(adev->dev, board_pdev_unregister, board);
|
||||
if (ret < 0) {
|
||||
platform_device_unregister(board);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int avs_register_dmic_board(struct avs_dev *adev)
|
||||
{
|
||||
struct platform_device *codec, *board;
|
||||
@@ -500,6 +527,12 @@ int avs_register_all_boards(struct avs_dev *adev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
ret = avs_register_probe_board(adev);
|
||||
if (ret < 0)
|
||||
dev_warn(adev->dev, "enumerate PROBE endpoints failed: %d\n", ret);
|
||||
#endif
|
||||
|
||||
ret = avs_register_dmic_board(adev);
|
||||
if (ret < 0)
|
||||
dev_warn(adev->dev, "enumerate DMIC endpoints failed: %d\n",
|
||||
|
||||
@@ -77,6 +77,14 @@ config SND_SOC_INTEL_AVS_MACH_NAU8825
|
||||
Say Y or m if you have such a device. This is a recommended option.
|
||||
If unsure select "N".
|
||||
|
||||
config SND_SOC_INTEL_AVS_MACH_PROBE
|
||||
tristate "Probing (data) board"
|
||||
depends on DEBUG_FS
|
||||
select SND_HWDEP
|
||||
help
|
||||
This adds support for data probing board which can be used to
|
||||
gather data from runtime stream over compress operations.
|
||||
|
||||
config SND_SOC_INTEL_AVS_MACH_RT274
|
||||
tristate "rt274 in I2S mode"
|
||||
depends on I2C
|
||||
|
||||
@@ -8,6 +8,7 @@ snd-soc-avs-max98927-objs := max98927.o
|
||||
snd-soc-avs-max98357a-objs := max98357a.o
|
||||
snd-soc-avs-max98373-objs := max98373.o
|
||||
snd-soc-avs-nau8825-objs := nau8825.o
|
||||
snd-soc-avs-probe-objs := probe.o
|
||||
snd-soc-avs-rt274-objs := rt274.o
|
||||
snd-soc-avs-rt286-objs := rt286.o
|
||||
snd-soc-avs-rt298-objs := rt298.o
|
||||
@@ -22,6 +23,7 @@ obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_MAX98927) += snd-soc-avs-max98927.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_MAX98357A) += snd-soc-avs-max98357a.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_MAX98373) += snd-soc-avs-max98373.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_NAU8825) += snd-soc-avs-nau8825.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_PROBE) += snd-soc-avs-probe.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT274) += snd-soc-avs-rt274.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT286) += snd-soc-avs-rt286.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT298) += snd-soc-avs-rt298.o
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user