提交 e9c3ddee 编写于 作者: D Dave Airlie

Merge branch 'drm-next-4.9' of git://people.freedesktop.org/~agd5f/linux into drm-next

First drm-next pull for radeon and amdgpu for 4.9.  Highlights:
- powerplay support for iceland asics
- improved GPU reset (both full asic and per block)
- UVD and VCE powergating for CZ and ST
- VCE clockgating for CZ and ST
- Support for pre-initialized (e.g., zeroed) vram buffers
- ttm cleanups
- virtual display support
- core and radeon/amdgpu support for page_flip_target
- lots of bug fixes and clean ups

* 'drm-next-4.9' of git://people.freedesktop.org/~agd5f/linux: (171 commits)
  drm/amdgpu: use memcpy_toio for VCE firmware upload
  drm/amdgpu: use memcpy_to/fromio for UVD fw upload
  drm/amd/powerplay: delete useless code in iceland_hwmgr.c.
  drm/radeon: switch UVD code to use UVD_NO_OP for padding
  drm/amdgpu: switch UVD code to use UVD_NO_OP for padding
  drm/radeon: add support for UVD_NO_OP register
  drm/amdgpu: add support for UVD_NO_OP register
  drm/amdgpu: fix VCE ib alignment value
  drm/amdgpu: fix IB alignment for UVD
  drm/amd/amdgpu: Print ring name in amdgpu_ib_schedule()
  drm/radeon: remove dead code, si_mc_load_microcode (v2)
  drm/radeon/cik: remove dead code (v2)
  drm/amd/powerplay: avoid NULL dereference, cz_hwmgr.c
  drm/amd/powerplay: avoid NULL pointer dereference
  drm/amdgpu/gmc8: remove dead code (v2)
  drm/amdgpu/gmc7: remove dead code (v2)
  drm/amdgpu: Fix indentation in dce_v8_0_audio_write_sad_regs()
  drm/amdgpu: Use correct mask in dce_v8_0_afmt_setmode() and fix comment typos.
  drm/amdgpu: cleanup amdgpu_vm_bo_update params
  drm/amdgpu: stop adding dummy entry in amdgpu_ttm_placement_init
  ...
...@@ -163,9 +163,6 @@ config DRM_AMDGPU ...@@ -163,9 +163,6 @@ config DRM_AMDGPU
If M is selected, the module will be called amdgpu. If M is selected, the module will be called amdgpu.
source "drivers/gpu/drm/amd/amdgpu/Kconfig" source "drivers/gpu/drm/amd/amdgpu/Kconfig"
source "drivers/gpu/drm/amd/powerplay/Kconfig"
source "drivers/gpu/drm/amd/acp/Kconfig"
source "drivers/gpu/drm/nouveau/Kconfig" source "drivers/gpu/drm/nouveau/Kconfig"
......
...@@ -25,3 +25,5 @@ config DRM_AMDGPU_GART_DEBUGFS ...@@ -25,3 +25,5 @@ config DRM_AMDGPU_GART_DEBUGFS
Selecting this option creates a debugfs file to inspect the mapped Selecting this option creates a debugfs file to inspect the mapped
pages. Uses more memory for housekeeping, enable only for debugging. pages. Uses more memory for housekeeping, enable only for debugging.
source "drivers/gpu/drm/amd/powerplay/Kconfig"
source "drivers/gpu/drm/amd/acp/Kconfig"
...@@ -58,7 +58,8 @@ amdgpu-y += \ ...@@ -58,7 +58,8 @@ amdgpu-y += \
# add DCE block # add DCE block
amdgpu-y += \ amdgpu-y += \
dce_v10_0.o \ dce_v10_0.o \
dce_v11_0.o dce_v11_0.o \
dce_virtual.o
# add GFX block # add GFX block
amdgpu-y += \ amdgpu-y += \
......
...@@ -90,6 +90,7 @@ ...@@ -90,6 +90,7 @@
#define ENCODER_OBJECT_ID_INTERNAL_VCE 0x24 #define ENCODER_OBJECT_ID_INTERNAL_VCE 0x24
#define ENCODER_OBJECT_ID_INTERNAL_UNIPHY3 0x25 #define ENCODER_OBJECT_ID_INTERNAL_UNIPHY3 0x25
#define ENCODER_OBJECT_ID_INTERNAL_AMCLK 0x27 #define ENCODER_OBJECT_ID_INTERNAL_AMCLK 0x27
#define ENCODER_OBJECT_ID_VIRTUAL 0x28
#define ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO 0xFF #define ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO 0xFF
...@@ -119,6 +120,7 @@ ...@@ -119,6 +120,7 @@
#define CONNECTOR_OBJECT_ID_eDP 0x14 #define CONNECTOR_OBJECT_ID_eDP 0x14
#define CONNECTOR_OBJECT_ID_MXM 0x15 #define CONNECTOR_OBJECT_ID_MXM 0x15
#define CONNECTOR_OBJECT_ID_LVDS_eDP 0x16 #define CONNECTOR_OBJECT_ID_LVDS_eDP 0x16
#define CONNECTOR_OBJECT_ID_VIRTUAL 0x17
/* deleted */ /* deleted */
...@@ -147,6 +149,7 @@ ...@@ -147,6 +149,7 @@
#define GRAPH_OBJECT_ENUM_ID5 0x05 #define GRAPH_OBJECT_ENUM_ID5 0x05
#define GRAPH_OBJECT_ENUM_ID6 0x06 #define GRAPH_OBJECT_ENUM_ID6 0x06
#define GRAPH_OBJECT_ENUM_ID7 0x07 #define GRAPH_OBJECT_ENUM_ID7 0x07
#define GRAPH_OBJECT_ENUM_VIRTUAL 0x08
/****************************************************/ /****************************************************/
/* Graphics Object ID Bit definition */ /* Graphics Object ID Bit definition */
...@@ -408,6 +411,10 @@ ...@@ -408,6 +411,10 @@
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_HDMI_ANX9805 << OBJECT_ID_SHIFT) ENCODER_OBJECT_ID_HDMI_ANX9805 << OBJECT_ID_SHIFT)
#define ENCODER_VIRTUAL_ENUM_VIRTUAL ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_VIRTUAL << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_VIRTUAL << OBJECT_ID_SHIFT)
/****************************************************/ /****************************************************/
/* Connector Object ID definition - Shared with BIOS */ /* Connector Object ID definition - Shared with BIOS */
/****************************************************/ /****************************************************/
......
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
#include "amdgpu_ih.h" #include "amdgpu_ih.h"
#include "amdgpu_irq.h" #include "amdgpu_irq.h"
#include "amdgpu_ucode.h" #include "amdgpu_ucode.h"
#include "amdgpu_ttm.h"
#include "amdgpu_gds.h" #include "amdgpu_gds.h"
#include "amd_powerplay.h" #include "amd_powerplay.h"
#include "amdgpu_acp.h" #include "amdgpu_acp.h"
...@@ -91,6 +92,8 @@ extern unsigned amdgpu_pcie_lane_cap; ...@@ -91,6 +92,8 @@ extern unsigned amdgpu_pcie_lane_cap;
extern unsigned amdgpu_cg_mask; extern unsigned amdgpu_cg_mask;
extern unsigned amdgpu_pg_mask; extern unsigned amdgpu_pg_mask;
extern char *amdgpu_disable_cu; extern char *amdgpu_disable_cu;
extern int amdgpu_sclk_deep_sleep_en;
extern char *amdgpu_virtual_display;
#define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS 3000 #define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS 3000
#define AMDGPU_MAX_USEC_TIMEOUT 100000 /* 100 ms */ #define AMDGPU_MAX_USEC_TIMEOUT 100000 /* 100 ms */
...@@ -248,10 +251,9 @@ struct amdgpu_vm_pte_funcs { ...@@ -248,10 +251,9 @@ struct amdgpu_vm_pte_funcs {
uint64_t pe, uint64_t src, uint64_t pe, uint64_t src,
unsigned count); unsigned count);
/* write pte one entry at a time with addr mapping */ /* write pte one entry at a time with addr mapping */
void (*write_pte)(struct amdgpu_ib *ib, void (*write_pte)(struct amdgpu_ib *ib, uint64_t pe,
const dma_addr_t *pages_addr, uint64_t pe, uint64_t value, unsigned count,
uint64_t addr, unsigned count, uint32_t incr);
uint32_t incr, uint32_t flags);
/* for linear pte/pde updates without addr mapping */ /* for linear pte/pde updates without addr mapping */
void (*set_pte_pde)(struct amdgpu_ib *ib, void (*set_pte_pde)(struct amdgpu_ib *ib,
uint64_t pe, uint64_t pe,
...@@ -396,46 +398,9 @@ int amdgpu_fence_wait_empty(struct amdgpu_ring *ring); ...@@ -396,46 +398,9 @@ int amdgpu_fence_wait_empty(struct amdgpu_ring *ring);
unsigned amdgpu_fence_count_emitted(struct amdgpu_ring *ring); unsigned amdgpu_fence_count_emitted(struct amdgpu_ring *ring);
/* /*
* TTM. * BO.
*/ */
#define AMDGPU_TTM_LRU_SIZE 20
struct amdgpu_mman_lru {
struct list_head *lru[TTM_NUM_MEM_TYPES];
struct list_head *swap_lru;
};
struct amdgpu_mman {
struct ttm_bo_global_ref bo_global_ref;
struct drm_global_reference mem_global_ref;
struct ttm_bo_device bdev;
bool mem_global_referenced;
bool initialized;
#if defined(CONFIG_DEBUG_FS)
struct dentry *vram;
struct dentry *gtt;
#endif
/* buffer handling */
const struct amdgpu_buffer_funcs *buffer_funcs;
struct amdgpu_ring *buffer_funcs_ring;
/* Scheduler entity for buffer moves */
struct amd_sched_entity entity;
/* custom LRU management */
struct amdgpu_mman_lru log2_size[AMDGPU_TTM_LRU_SIZE];
};
int amdgpu_copy_buffer(struct amdgpu_ring *ring,
uint64_t src_offset,
uint64_t dst_offset,
uint32_t byte_count,
struct reservation_object *resv,
struct fence **fence);
int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma);
struct amdgpu_bo_list_entry { struct amdgpu_bo_list_entry {
struct amdgpu_bo *robj; struct amdgpu_bo *robj;
struct ttm_validate_buffer tv; struct ttm_validate_buffer tv;
...@@ -498,10 +463,12 @@ struct amdgpu_bo { ...@@ -498,10 +463,12 @@ struct amdgpu_bo {
struct amdgpu_device *adev; struct amdgpu_device *adev;
struct drm_gem_object gem_base; struct drm_gem_object gem_base;
struct amdgpu_bo *parent; struct amdgpu_bo *parent;
struct amdgpu_bo *shadow;
struct ttm_bo_kmap_obj dma_buf_vmap; struct ttm_bo_kmap_obj dma_buf_vmap;
struct amdgpu_mn *mn; struct amdgpu_mn *mn;
struct list_head mn_list; struct list_head mn_list;
struct list_head shadow_list;
}; };
#define gem_to_amdgpu_bo(gobj) container_of((gobj), struct amdgpu_bo, gem_base) #define gem_to_amdgpu_bo(gobj) container_of((gobj), struct amdgpu_bo, gem_base)
...@@ -677,6 +644,8 @@ struct amdgpu_mc { ...@@ -677,6 +644,8 @@ struct amdgpu_mc {
uint32_t fw_version; uint32_t fw_version;
struct amdgpu_irq_src vm_fault; struct amdgpu_irq_src vm_fault;
uint32_t vram_type; uint32_t vram_type;
uint32_t srbm_soft_reset;
struct amdgpu_mode_mc_save save;
}; };
/* /*
...@@ -721,10 +690,11 @@ void amdgpu_doorbell_get_kfd_info(struct amdgpu_device *adev, ...@@ -721,10 +690,11 @@ void amdgpu_doorbell_get_kfd_info(struct amdgpu_device *adev,
*/ */
struct amdgpu_flip_work { struct amdgpu_flip_work {
struct work_struct flip_work; struct delayed_work flip_work;
struct work_struct unpin_work; struct work_struct unpin_work;
struct amdgpu_device *adev; struct amdgpu_device *adev;
int crtc_id; int crtc_id;
u32 target_vblank;
uint64_t base; uint64_t base;
struct drm_pending_vblank_event *event; struct drm_pending_vblank_event *event;
struct amdgpu_bo *old_rbo; struct amdgpu_bo *old_rbo;
...@@ -815,13 +785,17 @@ struct amdgpu_ring { ...@@ -815,13 +785,17 @@ struct amdgpu_ring {
/* maximum number of VMIDs */ /* maximum number of VMIDs */
#define AMDGPU_NUM_VM 16 #define AMDGPU_NUM_VM 16
/* Maximum number of PTEs the hardware can write with one command */
#define AMDGPU_VM_MAX_UPDATE_SIZE 0x3FFFF
/* number of entries in page table */ /* number of entries in page table */
#define AMDGPU_VM_PTE_COUNT (1 << amdgpu_vm_block_size) #define AMDGPU_VM_PTE_COUNT (1 << amdgpu_vm_block_size)
/* PTBs (Page Table Blocks) need to be aligned to 32K */ /* PTBs (Page Table Blocks) need to be aligned to 32K */
#define AMDGPU_VM_PTB_ALIGN_SIZE 32768 #define AMDGPU_VM_PTB_ALIGN_SIZE 32768
#define AMDGPU_VM_PTB_ALIGN_MASK (AMDGPU_VM_PTB_ALIGN_SIZE - 1)
#define AMDGPU_VM_PTB_ALIGN(a) (((a) + AMDGPU_VM_PTB_ALIGN_MASK) & ~AMDGPU_VM_PTB_ALIGN_MASK) /* LOG2 number of continuous pages for the fragment field */
#define AMDGPU_LOG2_PAGES_PER_FRAG 4
#define AMDGPU_PTE_VALID (1 << 0) #define AMDGPU_PTE_VALID (1 << 0)
#define AMDGPU_PTE_SYSTEM (1 << 1) #define AMDGPU_PTE_SYSTEM (1 << 1)
...@@ -833,10 +807,7 @@ struct amdgpu_ring { ...@@ -833,10 +807,7 @@ struct amdgpu_ring {
#define AMDGPU_PTE_READABLE (1 << 5) #define AMDGPU_PTE_READABLE (1 << 5)
#define AMDGPU_PTE_WRITEABLE (1 << 6) #define AMDGPU_PTE_WRITEABLE (1 << 6)
/* PTE (Page Table Entry) fragment field for different page sizes */ #define AMDGPU_PTE_FRAG(x) ((x & 0x1f) << 7)
#define AMDGPU_PTE_FRAG_4KB (0 << 7)
#define AMDGPU_PTE_FRAG_64KB (4 << 7)
#define AMDGPU_LOG2_PAGES_PER_FRAG 4
/* How to programm VM fault handling */ /* How to programm VM fault handling */
#define AMDGPU_VM_FAULT_STOP_NEVER 0 #define AMDGPU_VM_FAULT_STOP_NEVER 0
...@@ -846,6 +817,7 @@ struct amdgpu_ring { ...@@ -846,6 +817,7 @@ struct amdgpu_ring {
struct amdgpu_vm_pt { struct amdgpu_vm_pt {
struct amdgpu_bo_list_entry entry; struct amdgpu_bo_list_entry entry;
uint64_t addr; uint64_t addr;
uint64_t shadow_addr;
}; };
struct amdgpu_vm { struct amdgpu_vm {
...@@ -948,7 +920,6 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, ...@@ -948,7 +920,6 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
struct amdgpu_job *job); struct amdgpu_job *job);
int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job); int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job);
void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vm_id); void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vm_id);
uint64_t amdgpu_vm_map_gart(const dma_addr_t *pages_addr, uint64_t addr);
int amdgpu_vm_update_page_directory(struct amdgpu_device *adev, int amdgpu_vm_update_page_directory(struct amdgpu_device *adev,
struct amdgpu_vm *vm); struct amdgpu_vm *vm);
int amdgpu_vm_clear_freed(struct amdgpu_device *adev, int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
...@@ -957,7 +928,7 @@ int amdgpu_vm_clear_invalids(struct amdgpu_device *adev, struct amdgpu_vm *vm, ...@@ -957,7 +928,7 @@ int amdgpu_vm_clear_invalids(struct amdgpu_device *adev, struct amdgpu_vm *vm,
struct amdgpu_sync *sync); struct amdgpu_sync *sync);
int amdgpu_vm_bo_update(struct amdgpu_device *adev, int amdgpu_vm_bo_update(struct amdgpu_device *adev,
struct amdgpu_bo_va *bo_va, struct amdgpu_bo_va *bo_va,
struct ttm_mem_reg *mem); bool clear);
void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev, void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev,
struct amdgpu_bo *bo); struct amdgpu_bo *bo);
struct amdgpu_bo_va *amdgpu_vm_bo_find(struct amdgpu_vm *vm, struct amdgpu_bo_va *amdgpu_vm_bo_find(struct amdgpu_vm *vm,
...@@ -1195,6 +1166,10 @@ struct amdgpu_gfx { ...@@ -1195,6 +1166,10 @@ struct amdgpu_gfx {
unsigned ce_ram_size; unsigned ce_ram_size;
struct amdgpu_cu_info cu_info; struct amdgpu_cu_info cu_info;
const struct amdgpu_gfx_funcs *funcs; const struct amdgpu_gfx_funcs *funcs;
/* reset mask */
uint32_t grbm_soft_reset;
uint32_t srbm_soft_reset;
}; };
int amdgpu_ib_get(struct amdgpu_device *adev, struct amdgpu_vm *vm, int amdgpu_ib_get(struct amdgpu_device *adev, struct amdgpu_vm *vm,
...@@ -1683,6 +1658,7 @@ struct amdgpu_uvd { ...@@ -1683,6 +1658,7 @@ struct amdgpu_uvd {
bool address_64_bit; bool address_64_bit;
bool use_ctx_buf; bool use_ctx_buf;
struct amd_sched_entity entity; struct amd_sched_entity entity;
uint32_t srbm_soft_reset;
}; };
/* /*
...@@ -1709,6 +1685,7 @@ struct amdgpu_vce { ...@@ -1709,6 +1685,7 @@ struct amdgpu_vce {
struct amdgpu_irq_src irq; struct amdgpu_irq_src irq;
unsigned harvest_config; unsigned harvest_config;
struct amd_sched_entity entity; struct amd_sched_entity entity;
uint32_t srbm_soft_reset;
}; };
/* /*
...@@ -1729,6 +1706,7 @@ struct amdgpu_sdma { ...@@ -1729,6 +1706,7 @@ struct amdgpu_sdma {
struct amdgpu_irq_src trap_irq; struct amdgpu_irq_src trap_irq;
struct amdgpu_irq_src illegal_inst_irq; struct amdgpu_irq_src illegal_inst_irq;
int num_instances; int num_instances;
uint32_t srbm_soft_reset;
}; };
/* /*
...@@ -1956,6 +1934,7 @@ struct amdgpu_ip_block_status { ...@@ -1956,6 +1934,7 @@ struct amdgpu_ip_block_status {
bool valid; bool valid;
bool sw; bool sw;
bool hw; bool hw;
bool hang;
}; };
struct amdgpu_device { struct amdgpu_device {
...@@ -2055,6 +2034,7 @@ struct amdgpu_device { ...@@ -2055,6 +2034,7 @@ struct amdgpu_device {
atomic_t gpu_reset_counter; atomic_t gpu_reset_counter;
/* display */ /* display */
bool enable_virtual_display;
struct amdgpu_mode_info mode_info; struct amdgpu_mode_info mode_info;
struct work_struct hotplug_work; struct work_struct hotplug_work;
struct amdgpu_irq_src crtc_irq; struct amdgpu_irq_src crtc_irq;
...@@ -2117,6 +2097,10 @@ struct amdgpu_device { ...@@ -2117,6 +2097,10 @@ struct amdgpu_device {
struct kfd_dev *kfd; struct kfd_dev *kfd;
struct amdgpu_virtualization virtualization; struct amdgpu_virtualization virtualization;
/* link all shadow bo */
struct list_head shadow_list;
struct mutex shadow_list_lock;
}; };
bool amdgpu_device_is_px(struct drm_device *dev); bool amdgpu_device_is_px(struct drm_device *dev);
...@@ -2192,6 +2176,9 @@ void amdgpu_mm_wdoorbell(struct amdgpu_device *adev, u32 index, u32 v); ...@@ -2192,6 +2176,9 @@ void amdgpu_mm_wdoorbell(struct amdgpu_device *adev, u32 index, u32 v);
#define REG_GET_FIELD(value, reg, field) \ #define REG_GET_FIELD(value, reg, field) \
(((value) & REG_FIELD_MASK(reg, field)) >> REG_FIELD_SHIFT(reg, field)) (((value) & REG_FIELD_MASK(reg, field)) >> REG_FIELD_SHIFT(reg, field))
#define WREG32_FIELD(reg, field, val) \
WREG32(mm##reg, (RREG32(mm##reg) & ~REG_FIELD_MASK(reg, field)) | (val) << REG_FIELD_SHIFT(reg, field))
/* /*
* BIOS helpers. * BIOS helpers.
*/ */
...@@ -2242,7 +2229,7 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring) ...@@ -2242,7 +2229,7 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring)
#define amdgpu_gart_flush_gpu_tlb(adev, vmid) (adev)->gart.gart_funcs->flush_gpu_tlb((adev), (vmid)) #define amdgpu_gart_flush_gpu_tlb(adev, vmid) (adev)->gart.gart_funcs->flush_gpu_tlb((adev), (vmid))
#define amdgpu_gart_set_pte_pde(adev, pt, idx, addr, flags) (adev)->gart.gart_funcs->set_pte_pde((adev), (pt), (idx), (addr), (flags)) #define amdgpu_gart_set_pte_pde(adev, pt, idx, addr, flags) (adev)->gart.gart_funcs->set_pte_pde((adev), (pt), (idx), (addr), (flags))
#define amdgpu_vm_copy_pte(adev, ib, pe, src, count) ((adev)->vm_manager.vm_pte_funcs->copy_pte((ib), (pe), (src), (count))) #define amdgpu_vm_copy_pte(adev, ib, pe, src, count) ((adev)->vm_manager.vm_pte_funcs->copy_pte((ib), (pe), (src), (count)))
#define amdgpu_vm_write_pte(adev, ib, pa, pe, addr, count, incr, flags) ((adev)->vm_manager.vm_pte_funcs->write_pte((ib), (pa), (pe), (addr), (count), (incr), (flags))) #define amdgpu_vm_write_pte(adev, ib, pe, value, count, incr) ((adev)->vm_manager.vm_pte_funcs->write_pte((ib), (pe), (value), (count), (incr)))
#define amdgpu_vm_set_pte_pde(adev, ib, pe, addr, count, incr, flags) ((adev)->vm_manager.vm_pte_funcs->set_pte_pde((ib), (pe), (addr), (count), (incr), (flags))) #define amdgpu_vm_set_pte_pde(adev, ib, pe, addr, count, incr, flags) ((adev)->vm_manager.vm_pte_funcs->set_pte_pde((ib), (pe), (addr), (count), (incr), (flags)))
#define amdgpu_ring_parse_cs(r, p, ib) ((r)->funcs->parse_cs((p), (ib))) #define amdgpu_ring_parse_cs(r, p, ib) ((r)->funcs->parse_cs((p), (ib)))
#define amdgpu_ring_test_ring(r) (r)->funcs->test_ring((r)) #define amdgpu_ring_test_ring(r) (r)->funcs->test_ring((r))
...@@ -2387,6 +2374,7 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring) ...@@ -2387,6 +2374,7 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring)
/* Common functions */ /* Common functions */
int amdgpu_gpu_reset(struct amdgpu_device *adev); int amdgpu_gpu_reset(struct amdgpu_device *adev);
bool amdgpu_need_backup(struct amdgpu_device *adev);
void amdgpu_pci_config_reset(struct amdgpu_device *adev); void amdgpu_pci_config_reset(struct amdgpu_device *adev);
bool amdgpu_card_posted(struct amdgpu_device *adev); bool amdgpu_card_posted(struct amdgpu_device *adev);
void amdgpu_update_display_priority(struct amdgpu_device *adev); void amdgpu_update_display_priority(struct amdgpu_device *adev);
...@@ -2412,6 +2400,8 @@ uint32_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm, ...@@ -2412,6 +2400,8 @@ uint32_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm,
void amdgpu_vram_location(struct amdgpu_device *adev, struct amdgpu_mc *mc, u64 base); void amdgpu_vram_location(struct amdgpu_device *adev, struct amdgpu_mc *mc, u64 base);
void amdgpu_gtt_location(struct amdgpu_device *adev, struct amdgpu_mc *mc); void amdgpu_gtt_location(struct amdgpu_device *adev, struct amdgpu_mc *mc);
void amdgpu_ttm_set_active_vram_size(struct amdgpu_device *adev, u64 size); void amdgpu_ttm_set_active_vram_size(struct amdgpu_device *adev, u64 size);
u64 amdgpu_ttm_get_gtt_mem_size(struct amdgpu_device *adev);
int amdgpu_ttm_global_init(struct amdgpu_device *adev);
void amdgpu_program_register_sequence(struct amdgpu_device *adev, void amdgpu_program_register_sequence(struct amdgpu_device *adev,
const u32 *registers, const u32 *registers,
const u32 array_size); const u32 array_size);
......
...@@ -259,6 +259,33 @@ static const int object_connector_convert[] = { ...@@ -259,6 +259,33 @@ static const int object_connector_convert[] = {
DRM_MODE_CONNECTOR_Unknown DRM_MODE_CONNECTOR_Unknown
}; };
bool amdgpu_atombios_has_dce_engine_info(struct amdgpu_device *adev)
{
struct amdgpu_mode_info *mode_info = &adev->mode_info;
struct atom_context *ctx = mode_info->atom_context;
int index = GetIndexIntoMasterTable(DATA, Object_Header);
u16 size, data_offset;
u8 frev, crev;
ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj;
ATOM_OBJECT_HEADER *obj_header;
if (!amdgpu_atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset))
return false;
if (crev < 2)
return false;
obj_header = (ATOM_OBJECT_HEADER *) (ctx->bios + data_offset);
path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *)
(ctx->bios + data_offset +
le16_to_cpu(obj_header->usDisplayPathTableOffset));
if (path_obj->ucNumOfDispPath)
return true;
else
return false;
}
bool amdgpu_atombios_get_connector_info_from_object_table(struct amdgpu_device *adev) bool amdgpu_atombios_get_connector_info_from_object_table(struct amdgpu_device *adev)
{ {
struct amdgpu_mode_info *mode_info = &adev->mode_info; struct amdgpu_mode_info *mode_info = &adev->mode_info;
......
...@@ -140,6 +140,8 @@ struct amdgpu_i2c_bus_rec amdgpu_atombios_lookup_i2c_gpio(struct amdgpu_device * ...@@ -140,6 +140,8 @@ struct amdgpu_i2c_bus_rec amdgpu_atombios_lookup_i2c_gpio(struct amdgpu_device *
uint8_t id); uint8_t id);
void amdgpu_atombios_i2c_init(struct amdgpu_device *adev); void amdgpu_atombios_i2c_init(struct amdgpu_device *adev);
bool amdgpu_atombios_has_dce_engine_info(struct amdgpu_device *adev);
bool amdgpu_atombios_get_connector_info_from_object_table(struct amdgpu_device *adev); bool amdgpu_atombios_get_connector_info_from_object_table(struct amdgpu_device *adev);
int amdgpu_atombios_get_clock_info(struct amdgpu_device *adev); int amdgpu_atombios_get_clock_info(struct amdgpu_device *adev);
......
...@@ -39,7 +39,8 @@ static int amdgpu_benchmark_do_move(struct amdgpu_device *adev, unsigned size, ...@@ -39,7 +39,8 @@ static int amdgpu_benchmark_do_move(struct amdgpu_device *adev, unsigned size,
start_jiffies = jiffies; start_jiffies = jiffies;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring; struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;
r = amdgpu_copy_buffer(ring, saddr, daddr, size, NULL, &fence); r = amdgpu_copy_buffer(ring, saddr, daddr, size, NULL, &fence,
false);
if (r) if (r)
goto exit_do_move; goto exit_do_move;
r = fence_wait(fence, false); r = fence_wait(fence, false);
......
...@@ -1504,6 +1504,86 @@ static const struct drm_connector_funcs amdgpu_connector_edp_funcs = { ...@@ -1504,6 +1504,86 @@ static const struct drm_connector_funcs amdgpu_connector_edp_funcs = {
.force = amdgpu_connector_dvi_force, .force = amdgpu_connector_dvi_force,
}; };
static struct drm_encoder *
amdgpu_connector_virtual_encoder(struct drm_connector *connector)
{
int enc_id = connector->encoder_ids[0];
struct drm_encoder *encoder;
int i;
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
if (connector->encoder_ids[i] == 0)
break;
encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
if (!encoder)
continue;
if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL)
return encoder;
}
/* pick the first one */
if (enc_id)
return drm_encoder_find(connector->dev, enc_id);
return NULL;
}
static int amdgpu_connector_virtual_get_modes(struct drm_connector *connector)
{
struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
if (encoder) {
amdgpu_connector_add_common_modes(encoder, connector);
}
return 0;
}
static int amdgpu_connector_virtual_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
return MODE_OK;
}
int amdgpu_connector_virtual_dpms(struct drm_connector *connector, int mode)
{
return 0;
}
static enum drm_connector_status
amdgpu_connector_virtual_detect(struct drm_connector *connector, bool force)
{
return connector_status_connected;
}
int amdgpu_connector_virtual_set_property(struct drm_connector *connector,
struct drm_property *property,
uint64_t val)
{
return 0;
}
static void amdgpu_connector_virtual_force(struct drm_connector *connector)
{
return;
}
static const struct drm_connector_helper_funcs amdgpu_connector_virtual_helper_funcs = {
.get_modes = amdgpu_connector_virtual_get_modes,
.mode_valid = amdgpu_connector_virtual_mode_valid,
.best_encoder = amdgpu_connector_virtual_encoder,
};
static const struct drm_connector_funcs amdgpu_connector_virtual_funcs = {
.dpms = amdgpu_connector_virtual_dpms,
.detect = amdgpu_connector_virtual_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.set_property = amdgpu_connector_virtual_set_property,
.destroy = amdgpu_connector_destroy,
.force = amdgpu_connector_virtual_force,
};
void void
amdgpu_connector_add(struct amdgpu_device *adev, amdgpu_connector_add(struct amdgpu_device *adev,
uint32_t connector_id, uint32_t connector_id,
...@@ -1888,6 +1968,17 @@ amdgpu_connector_add(struct amdgpu_device *adev, ...@@ -1888,6 +1968,17 @@ amdgpu_connector_add(struct amdgpu_device *adev,
connector->interlace_allowed = false; connector->interlace_allowed = false;
connector->doublescan_allowed = false; connector->doublescan_allowed = false;
break; break;
case DRM_MODE_CONNECTOR_VIRTUAL:
amdgpu_dig_connector = kzalloc(sizeof(struct amdgpu_connector_atom_dig), GFP_KERNEL);
if (!amdgpu_dig_connector)
goto failed;
amdgpu_connector->con_priv = amdgpu_dig_connector;
drm_connector_init(dev, &amdgpu_connector->base, &amdgpu_connector_virtual_funcs, connector_type);
drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_virtual_helper_funcs);
subpixel_order = SubPixelHorizontalRGB;
connector->interlace_allowed = false;
connector->doublescan_allowed = false;
break;
} }
} }
......
...@@ -287,34 +287,15 @@ static u64 amdgpu_cs_get_threshold_for_moves(struct amdgpu_device *adev) ...@@ -287,34 +287,15 @@ static u64 amdgpu_cs_get_threshold_for_moves(struct amdgpu_device *adev)
return max(bytes_moved_threshold, 1024*1024ull); return max(bytes_moved_threshold, 1024*1024ull);
} }
int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p, static int amdgpu_cs_bo_validate(struct amdgpu_cs_parser *p,
struct list_head *validated) struct amdgpu_bo *bo)
{ {
struct amdgpu_bo_list_entry *lobj;
u64 initial_bytes_moved; u64 initial_bytes_moved;
int r;
list_for_each_entry(lobj, validated, tv.head) {
struct amdgpu_bo *bo = lobj->robj;
bool binding_userptr = false;
struct mm_struct *usermm;
uint32_t domain; uint32_t domain;
int r;
usermm = amdgpu_ttm_tt_get_usermm(bo->tbo.ttm);
if (usermm && usermm != current->mm)
return -EPERM;
/* Check if we have user pages and nobody bound the BO already */
if (lobj->user_pages && bo->tbo.ttm->state != tt_bound) {
size_t size = sizeof(struct page *);
size *= bo->tbo.ttm->num_pages;
memcpy(bo->tbo.ttm->pages, lobj->user_pages, size);
binding_userptr = true;
}
if (bo->pin_count) if (bo->pin_count)
continue; return 0;
/* Avoid moving this one if we have moved too many buffers /* Avoid moving this one if we have moved too many buffers
* for this IB already. * for this IB already.
...@@ -329,7 +310,7 @@ int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p, ...@@ -329,7 +310,7 @@ int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p,
else else
domain = bo->allowed_domains; domain = bo->allowed_domains;
retry: retry:
amdgpu_ttm_placement_from_domain(bo, domain); amdgpu_ttm_placement_from_domain(bo, domain);
initial_bytes_moved = atomic64_read(&bo->adev->num_bytes_moved); initial_bytes_moved = atomic64_read(&bo->adev->num_bytes_moved);
r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false); r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false);
...@@ -341,6 +322,41 @@ int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p, ...@@ -341,6 +322,41 @@ int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p,
domain = bo->allowed_domains; domain = bo->allowed_domains;
goto retry; goto retry;
} }
}
return r;
}
int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p,
struct list_head *validated)
{
struct amdgpu_bo_list_entry *lobj;
int r;
list_for_each_entry(lobj, validated, tv.head) {
struct amdgpu_bo *bo = lobj->robj;
bool binding_userptr = false;
struct mm_struct *usermm;
usermm = amdgpu_ttm_tt_get_usermm(bo->tbo.ttm);
if (usermm && usermm != current->mm)
return -EPERM;
/* Check if we have user pages and nobody bound the BO already */
if (lobj->user_pages && bo->tbo.ttm->state != tt_bound) {
size_t size = sizeof(struct page *);
size *= bo->tbo.ttm->num_pages;
memcpy(bo->tbo.ttm->pages, lobj->user_pages, size);
binding_userptr = true;
}
r = amdgpu_cs_bo_validate(p, bo);
if (r)
return r;
if (bo->shadow) {
r = amdgpu_cs_bo_validate(p, bo);
if (r)
return r; return r;
} }
...@@ -386,8 +402,10 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, ...@@ -386,8 +402,10 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
r = ttm_eu_reserve_buffers(&p->ticket, &p->validated, true, r = ttm_eu_reserve_buffers(&p->ticket, &p->validated, true,
&duplicates); &duplicates);
if (unlikely(r != 0)) if (unlikely(r != 0)) {
DRM_ERROR("ttm_eu_reserve_buffers failed.\n");
goto error_free_pages; goto error_free_pages;
}
/* Without a BO list we don't have userptr BOs */ /* Without a BO list we don't have userptr BOs */
if (!p->bo_list) if (!p->bo_list)
...@@ -427,9 +445,10 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, ...@@ -427,9 +445,10 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
/* Unreserve everything again. */ /* Unreserve everything again. */
ttm_eu_backoff_reservation(&p->ticket, &p->validated); ttm_eu_backoff_reservation(&p->ticket, &p->validated);
/* We tried to often, just abort */ /* We tried too many times, just abort */
if (!--tries) { if (!--tries) {
r = -EDEADLK; r = -EDEADLK;
DRM_ERROR("deadlock in %s\n", __func__);
goto error_free_pages; goto error_free_pages;
} }
...@@ -441,11 +460,13 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, ...@@ -441,11 +460,13 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
sizeof(struct page*)); sizeof(struct page*));
if (!e->user_pages) { if (!e->user_pages) {
r = -ENOMEM; r = -ENOMEM;
DRM_ERROR("calloc failure in %s\n", __func__);
goto error_free_pages; goto error_free_pages;
} }
r = amdgpu_ttm_tt_get_user_pages(ttm, e->user_pages); r = amdgpu_ttm_tt_get_user_pages(ttm, e->user_pages);
if (r) { if (r) {
DRM_ERROR("amdgpu_ttm_tt_get_user_pages failed.\n");
drm_free_large(e->user_pages); drm_free_large(e->user_pages);
e->user_pages = NULL; e->user_pages = NULL;
goto error_free_pages; goto error_free_pages;
...@@ -462,12 +483,16 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, ...@@ -462,12 +483,16 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
p->bytes_moved = 0; p->bytes_moved = 0;
r = amdgpu_cs_list_validate(p, &duplicates); r = amdgpu_cs_list_validate(p, &duplicates);
if (r) if (r) {
DRM_ERROR("amdgpu_cs_list_validate(duplicates) failed.\n");
goto error_validate; goto error_validate;
}
r = amdgpu_cs_list_validate(p, &p->validated); r = amdgpu_cs_list_validate(p, &p->validated);
if (r) if (r) {
DRM_ERROR("amdgpu_cs_list_validate(validated) failed.\n");
goto error_validate; goto error_validate;
}
fpriv->vm.last_eviction_counter = fpriv->vm.last_eviction_counter =
atomic64_read(&p->adev->num_evictions); atomic64_read(&p->adev->num_evictions);
...@@ -617,7 +642,7 @@ static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p, ...@@ -617,7 +642,7 @@ static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p,
if (bo_va == NULL) if (bo_va == NULL)
continue; continue;
r = amdgpu_vm_bo_update(adev, bo_va, &bo->tbo.mem); r = amdgpu_vm_bo_update(adev, bo_va, false);
if (r) if (r)
return r; return r;
......
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#endif #endif
#include "vi.h" #include "vi.h"
#include "bif/bif_4_1_d.h" #include "bif/bif_4_1_d.h"
#include <linux/pci.h>
static int amdgpu_debugfs_regs_init(struct amdgpu_device *adev); static int amdgpu_debugfs_regs_init(struct amdgpu_device *adev);
static void amdgpu_debugfs_regs_cleanup(struct amdgpu_device *adev); static void amdgpu_debugfs_regs_cleanup(struct amdgpu_device *adev);
...@@ -1181,10 +1182,38 @@ int amdgpu_ip_block_version_cmp(struct amdgpu_device *adev, ...@@ -1181,10 +1182,38 @@ int amdgpu_ip_block_version_cmp(struct amdgpu_device *adev,
return 1; return 1;
} }
static void amdgpu_whether_enable_virtual_display(struct amdgpu_device *adev)
{
adev->enable_virtual_display = false;
if (amdgpu_virtual_display) {
struct drm_device *ddev = adev->ddev;
const char *pci_address_name = pci_name(ddev->pdev);
char *pciaddstr, *pciaddstr_tmp, *pciaddname;
pciaddstr = kstrdup(amdgpu_virtual_display, GFP_KERNEL);
pciaddstr_tmp = pciaddstr;
while ((pciaddname = strsep(&pciaddstr_tmp, ";"))) {
if (!strcmp(pci_address_name, pciaddname)) {
adev->enable_virtual_display = true;
break;
}
}
DRM_INFO("virtual display string:%s, %s:virtual_display:%d\n",
amdgpu_virtual_display, pci_address_name,
adev->enable_virtual_display);
kfree(pciaddstr);
}
}
static int amdgpu_early_init(struct amdgpu_device *adev) static int amdgpu_early_init(struct amdgpu_device *adev)
{ {
int i, r; int i, r;
amdgpu_whether_enable_virtual_display(adev);
switch (adev->asic_type) { switch (adev->asic_type) {
case CHIP_TOPAZ: case CHIP_TOPAZ:
case CHIP_TONGA: case CHIP_TONGA:
...@@ -1521,6 +1550,9 @@ int amdgpu_device_init(struct amdgpu_device *adev, ...@@ -1521,6 +1550,9 @@ int amdgpu_device_init(struct amdgpu_device *adev,
spin_lock_init(&adev->gc_cac_idx_lock); spin_lock_init(&adev->gc_cac_idx_lock);
spin_lock_init(&adev->audio_endpt_idx_lock); spin_lock_init(&adev->audio_endpt_idx_lock);
INIT_LIST_HEAD(&adev->shadow_list);
mutex_init(&adev->shadow_list_lock);
adev->rmmio_base = pci_resource_start(adev->pdev, 5); adev->rmmio_base = pci_resource_start(adev->pdev, 5);
adev->rmmio_size = pci_resource_len(adev->pdev, 5); adev->rmmio_size = pci_resource_len(adev->pdev, 5);
adev->rmmio = ioremap(adev->rmmio_base, adev->rmmio_size); adev->rmmio = ioremap(adev->rmmio_base, adev->rmmio_size);
...@@ -1937,6 +1969,126 @@ int amdgpu_resume_kms(struct drm_device *dev, bool resume, bool fbcon) ...@@ -1937,6 +1969,126 @@ int amdgpu_resume_kms(struct drm_device *dev, bool resume, bool fbcon)
return 0; return 0;
} }
static bool amdgpu_check_soft_reset(struct amdgpu_device *adev)
{
int i;
bool asic_hang = false;
for (i = 0; i < adev->num_ip_blocks; i++) {
if (!adev->ip_block_status[i].valid)
continue;
if (adev->ip_blocks[i].funcs->check_soft_reset)
adev->ip_blocks[i].funcs->check_soft_reset(adev);
if (adev->ip_block_status[i].hang) {
DRM_INFO("IP block:%d is hang!\n", i);
asic_hang = true;
}
}
return asic_hang;
}
int amdgpu_pre_soft_reset(struct amdgpu_device *adev)
{
int i, r = 0;
for (i = 0; i < adev->num_ip_blocks; i++) {
if (!adev->ip_block_status[i].valid)
continue;
if (adev->ip_block_status[i].hang &&
adev->ip_blocks[i].funcs->pre_soft_reset) {
r = adev->ip_blocks[i].funcs->pre_soft_reset(adev);
if (r)
return r;
}
}
return 0;
}
static bool amdgpu_need_full_reset(struct amdgpu_device *adev)
{
if (adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang ||
adev->ip_block_status[AMD_IP_BLOCK_TYPE_SMC].hang ||
adev->ip_block_status[AMD_IP_BLOCK_TYPE_ACP].hang ||
adev->ip_block_status[AMD_IP_BLOCK_TYPE_DCE].hang) {
DRM_INFO("Some block need full reset!\n");
return true;
}
return false;
}
static int amdgpu_soft_reset(struct amdgpu_device *adev)
{
int i, r = 0;
for (i = 0; i < adev->num_ip_blocks; i++) {
if (!adev->ip_block_status[i].valid)
continue;
if (adev->ip_block_status[i].hang &&
adev->ip_blocks[i].funcs->soft_reset) {
r = adev->ip_blocks[i].funcs->soft_reset(adev);
if (r)
return r;
}
}
return 0;
}
static int amdgpu_post_soft_reset(struct amdgpu_device *adev)
{
int i, r = 0;
for (i = 0; i < adev->num_ip_blocks; i++) {
if (!adev->ip_block_status[i].valid)
continue;
if (adev->ip_block_status[i].hang &&
adev->ip_blocks[i].funcs->post_soft_reset)
r = adev->ip_blocks[i].funcs->post_soft_reset(adev);
if (r)
return r;
}
return 0;
}
bool amdgpu_need_backup(struct amdgpu_device *adev)
{
if (adev->flags & AMD_IS_APU)
return false;
return amdgpu_lockup_timeout > 0 ? true : false;
}
static int amdgpu_recover_vram_from_shadow(struct amdgpu_device *adev,
struct amdgpu_ring *ring,
struct amdgpu_bo *bo,
struct fence **fence)
{
uint32_t domain;
int r;
if (!bo->shadow)
return 0;
r = amdgpu_bo_reserve(bo, false);
if (r)
return r;
domain = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type);
/* if bo has been evicted, then no need to recover */
if (domain == AMDGPU_GEM_DOMAIN_VRAM) {
r = amdgpu_bo_restore_from_shadow(adev, ring, bo,
NULL, fence, true);
if (r) {
DRM_ERROR("recover page table failed!\n");
goto err;
}
}
err:
amdgpu_bo_unreserve(bo);
return r;
}
/** /**
* amdgpu_gpu_reset - reset the asic * amdgpu_gpu_reset - reset the asic
* *
...@@ -1949,6 +2101,12 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev) ...@@ -1949,6 +2101,12 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev)
{ {
int i, r; int i, r;
int resched; int resched;
bool need_full_reset;
if (!amdgpu_check_soft_reset(adev)) {
DRM_INFO("No hardware hang detected. Did some blocks stall?\n");
return 0;
}
atomic_inc(&adev->gpu_reset_counter); atomic_inc(&adev->gpu_reset_counter);
...@@ -1967,6 +2125,19 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev) ...@@ -1967,6 +2125,19 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev)
/* after all hw jobs are reset, hw fence is meaningless, so force_completion */ /* after all hw jobs are reset, hw fence is meaningless, so force_completion */
amdgpu_fence_driver_force_completion(adev); amdgpu_fence_driver_force_completion(adev);
need_full_reset = amdgpu_need_full_reset(adev);
if (!need_full_reset) {
amdgpu_pre_soft_reset(adev);
r = amdgpu_soft_reset(adev);
amdgpu_post_soft_reset(adev);
if (r || amdgpu_check_soft_reset(adev)) {
DRM_INFO("soft reset failed, will fallback to full reset!\n");
need_full_reset = true;
}
}
if (need_full_reset) {
/* save scratch */ /* save scratch */
amdgpu_atombios_scratch_regs_save(adev); amdgpu_atombios_scratch_regs_save(adev);
r = amdgpu_suspend(adev); r = amdgpu_suspend(adev);
...@@ -1989,18 +2160,53 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev) ...@@ -1989,18 +2160,53 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev)
} }
/* restore scratch */ /* restore scratch */
amdgpu_atombios_scratch_regs_restore(adev); amdgpu_atombios_scratch_regs_restore(adev);
}
if (!r) { if (!r) {
amdgpu_irq_gpu_reset_resume_helper(adev);
r = amdgpu_ib_ring_tests(adev); r = amdgpu_ib_ring_tests(adev);
if (r) { if (r) {
dev_err(adev->dev, "ib ring test failed (%d).\n", r); dev_err(adev->dev, "ib ring test failed (%d).\n", r);
r = amdgpu_suspend(adev); r = amdgpu_suspend(adev);
need_full_reset = true;
goto retry; goto retry;
} }
/**
* recovery vm page tables, since we cannot depend on VRAM is
* consistent after gpu full reset.
*/
if (need_full_reset && amdgpu_need_backup(adev)) {
struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;
struct amdgpu_bo *bo, *tmp;
struct fence *fence = NULL, *next = NULL;
DRM_INFO("recover vram bo from shadow\n");
mutex_lock(&adev->shadow_list_lock);
list_for_each_entry_safe(bo, tmp, &adev->shadow_list, shadow_list) {
amdgpu_recover_vram_from_shadow(adev, ring, bo, &next);
if (fence) {
r = fence_wait(fence, false);
if (r) {
WARN(r, "recovery from shadow isn't comleted\n");
break;
}
}
fence_put(fence);
fence = next;
}
mutex_unlock(&adev->shadow_list_lock);
if (fence) {
r = fence_wait(fence, false);
if (r)
WARN(r, "recovery from shadow isn't comleted\n");
}
fence_put(fence);
}
for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
struct amdgpu_ring *ring = adev->rings[i]; struct amdgpu_ring *ring = adev->rings[i];
if (!ring) if (!ring)
continue; continue;
amd_sched_job_recovery(&ring->sched); amd_sched_job_recovery(&ring->sched);
kthread_unpark(ring->sched.thread); kthread_unpark(ring->sched.thread);
} }
...@@ -2020,7 +2226,6 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev) ...@@ -2020,7 +2226,6 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev)
/* bad news, how to tell it to userspace ? */ /* bad news, how to tell it to userspace ? */
dev_info(adev->dev, "GPU reset failed\n"); dev_info(adev->dev, "GPU reset failed\n");
} }
amdgpu_irq_gpu_reset_resume_helper(adev);
return r; return r;
} }
...@@ -2178,22 +2383,26 @@ static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf, ...@@ -2178,22 +2383,26 @@ static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf,
struct amdgpu_device *adev = f->f_inode->i_private; struct amdgpu_device *adev = f->f_inode->i_private;
ssize_t result = 0; ssize_t result = 0;
int r; int r;
bool use_bank; bool pm_pg_lock, use_bank;
unsigned instance_bank, sh_bank, se_bank; unsigned instance_bank, sh_bank, se_bank;
if (size & 0x3 || *pos & 0x3) if (size & 0x3 || *pos & 0x3)
return -EINVAL; return -EINVAL;
/* are we reading registers for which a PG lock is necessary? */
pm_pg_lock = (*pos >> 23) & 1;
if (*pos & (1ULL << 62)) { if (*pos & (1ULL << 62)) {
se_bank = (*pos >> 24) & 0x3FF; se_bank = (*pos >> 24) & 0x3FF;
sh_bank = (*pos >> 34) & 0x3FF; sh_bank = (*pos >> 34) & 0x3FF;
instance_bank = (*pos >> 44) & 0x3FF; instance_bank = (*pos >> 44) & 0x3FF;
use_bank = 1; use_bank = 1;
*pos &= 0xFFFFFF;
} else { } else {
use_bank = 0; use_bank = 0;
} }
*pos &= 0x3FFFF;
if (use_bank) { if (use_bank) {
if (sh_bank >= adev->gfx.config.max_sh_per_se || if (sh_bank >= adev->gfx.config.max_sh_per_se ||
se_bank >= adev->gfx.config.max_shader_engines) se_bank >= adev->gfx.config.max_shader_engines)
...@@ -2203,6 +2412,9 @@ static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf, ...@@ -2203,6 +2412,9 @@ static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf,
sh_bank, instance_bank); sh_bank, instance_bank);
} }
if (pm_pg_lock)
mutex_lock(&adev->pm.mutex);
while (size) { while (size) {
uint32_t value; uint32_t value;
...@@ -2228,6 +2440,9 @@ static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf, ...@@ -2228,6 +2440,9 @@ static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf,
mutex_unlock(&adev->grbm_idx_mutex); mutex_unlock(&adev->grbm_idx_mutex);
} }
if (pm_pg_lock)
mutex_unlock(&adev->pm.mutex);
return result; return result;
} }
...@@ -2443,7 +2658,7 @@ static ssize_t amdgpu_debugfs_gca_config_read(struct file *f, char __user *buf, ...@@ -2443,7 +2658,7 @@ static ssize_t amdgpu_debugfs_gca_config_read(struct file *f, char __user *buf,
return -ENOMEM; return -ENOMEM;
/* version, increment each time something is added */ /* version, increment each time something is added */
config[no_regs++] = 0; config[no_regs++] = 2;
config[no_regs++] = adev->gfx.config.max_shader_engines; config[no_regs++] = adev->gfx.config.max_shader_engines;
config[no_regs++] = adev->gfx.config.max_tile_pipes; config[no_regs++] = adev->gfx.config.max_tile_pipes;
config[no_regs++] = adev->gfx.config.max_cu_per_sh; config[no_regs++] = adev->gfx.config.max_cu_per_sh;
...@@ -2468,6 +2683,15 @@ static ssize_t amdgpu_debugfs_gca_config_read(struct file *f, char __user *buf, ...@@ -2468,6 +2683,15 @@ static ssize_t amdgpu_debugfs_gca_config_read(struct file *f, char __user *buf,
config[no_regs++] = adev->gfx.config.gb_addr_config; config[no_regs++] = adev->gfx.config.gb_addr_config;
config[no_regs++] = adev->gfx.config.num_rbs; config[no_regs++] = adev->gfx.config.num_rbs;
/* rev==1 */
config[no_regs++] = adev->rev_id;
config[no_regs++] = adev->pg_flags;
config[no_regs++] = adev->cg_flags;
/* rev==2 */
config[no_regs++] = adev->family;
config[no_regs++] = adev->external_rev_id;
while (size && (*pos < no_regs * 4)) { while (size && (*pos < no_regs * 4)) {
uint32_t value; uint32_t value;
......
...@@ -41,7 +41,7 @@ static void amdgpu_flip_callback(struct fence *f, struct fence_cb *cb) ...@@ -41,7 +41,7 @@ static void amdgpu_flip_callback(struct fence *f, struct fence_cb *cb)
container_of(cb, struct amdgpu_flip_work, cb); container_of(cb, struct amdgpu_flip_work, cb);
fence_put(f); fence_put(f);
schedule_work(&work->flip_work); schedule_work(&work->flip_work.work);
} }
static bool amdgpu_flip_handle_fence(struct amdgpu_flip_work *work, static bool amdgpu_flip_handle_fence(struct amdgpu_flip_work *work,
...@@ -63,16 +63,17 @@ static bool amdgpu_flip_handle_fence(struct amdgpu_flip_work *work, ...@@ -63,16 +63,17 @@ static bool amdgpu_flip_handle_fence(struct amdgpu_flip_work *work,
static void amdgpu_flip_work_func(struct work_struct *__work) static void amdgpu_flip_work_func(struct work_struct *__work)
{ {
struct delayed_work *delayed_work =
container_of(__work, struct delayed_work, work);
struct amdgpu_flip_work *work = struct amdgpu_flip_work *work =
container_of(__work, struct amdgpu_flip_work, flip_work); container_of(delayed_work, struct amdgpu_flip_work, flip_work);
struct amdgpu_device *adev = work->adev; struct amdgpu_device *adev = work->adev;
struct amdgpu_crtc *amdgpuCrtc = adev->mode_info.crtcs[work->crtc_id]; struct amdgpu_crtc *amdgpuCrtc = adev->mode_info.crtcs[work->crtc_id];
struct drm_crtc *crtc = &amdgpuCrtc->base; struct drm_crtc *crtc = &amdgpuCrtc->base;
unsigned long flags; unsigned long flags;
unsigned i, repcnt = 4; unsigned i;
int vpos, hpos, stat, min_udelay = 0; int vpos, hpos;
struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id];
if (amdgpu_flip_handle_fence(work, &work->excl)) if (amdgpu_flip_handle_fence(work, &work->excl))
return; return;
...@@ -81,55 +82,23 @@ static void amdgpu_flip_work_func(struct work_struct *__work) ...@@ -81,55 +82,23 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
if (amdgpu_flip_handle_fence(work, &work->shared[i])) if (amdgpu_flip_handle_fence(work, &work->shared[i]))
return; return;
/* We borrow the event spin lock for protecting flip_status */ /* Wait until we're out of the vertical blank period before the one
spin_lock_irqsave(&crtc->dev->event_lock, flags); * targeted by the flip
/* If this happens to execute within the "virtually extended" vblank
* interval before the start of the real vblank interval then it needs
* to delay programming the mmio flip until the real vblank is entered.
* This prevents completing a flip too early due to the way we fudge
* our vblank counter and vblank timestamps in order to work around the
* problem that the hw fires vblank interrupts before actual start of
* vblank (when line buffer refilling is done for a frame). It
* complements the fudging logic in amdgpu_get_crtc_scanoutpos() for
* timestamping and amdgpu_get_vblank_counter_kms() for vblank counts.
*
* In practice this won't execute very often unless on very fast
* machines because the time window for this to happen is very small.
*/ */
while (amdgpuCrtc->enabled && --repcnt) { if (amdgpuCrtc->enabled &&
/* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank (amdgpu_get_crtc_scanoutpos(adev->ddev, work->crtc_id, 0,
* start in hpos, and to the "fudged earlier" vblank start in
* vpos.
*/
stat = amdgpu_get_crtc_scanoutpos(adev->ddev, work->crtc_id,
GET_DISTANCE_TO_VBLANKSTART,
&vpos, &hpos, NULL, NULL, &vpos, &hpos, NULL, NULL,
&crtc->hwmode); &crtc->hwmode)
& (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK)) ==
if ((stat & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE)) != (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK) &&
(DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE) || (int)(work->target_vblank -
!(vpos >= 0 && hpos <= 0)) amdgpu_get_vblank_counter_kms(adev->ddev, amdgpuCrtc->crtc_id)) > 0) {
break; schedule_delayed_work(&work->flip_work, usecs_to_jiffies(1000));
return;
/* Sleep at least until estimated real start of hw vblank */
min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5);
if (min_udelay > vblank->framedur_ns / 2000) {
/* Don't wait ridiculously long - something is wrong */
repcnt = 0;
break;
}
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
usleep_range(min_udelay, 2 * min_udelay);
spin_lock_irqsave(&crtc->dev->event_lock, flags);
} }
if (!repcnt) /* We borrow the event spin lock for protecting flip_status */
DRM_DEBUG_DRIVER("Delay problem on crtc %d: min_udelay %d, " spin_lock_irqsave(&crtc->dev->event_lock, flags);
"framedur %d, linedur %d, stat %d, vpos %d, "
"hpos %d\n", work->crtc_id, min_udelay,
vblank->framedur_ns / 1000,
vblank->linedur_ns / 1000, stat, vpos, hpos);
/* Do the flip (mmio) */ /* Do the flip (mmio) */
adev->mode_info.funcs->page_flip(adev, work->crtc_id, work->base, work->async); adev->mode_info.funcs->page_flip(adev, work->crtc_id, work->base, work->async);
...@@ -169,10 +138,10 @@ static void amdgpu_unpin_work_func(struct work_struct *__work) ...@@ -169,10 +138,10 @@ static void amdgpu_unpin_work_func(struct work_struct *__work)
kfree(work); kfree(work);
} }
int amdgpu_crtc_page_flip(struct drm_crtc *crtc, int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc,
struct drm_framebuffer *fb, struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event, struct drm_pending_vblank_event *event,
uint32_t page_flip_flags) uint32_t page_flip_flags, uint32_t target)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct amdgpu_device *adev = dev->dev_private; struct amdgpu_device *adev = dev->dev_private;
...@@ -191,7 +160,7 @@ int amdgpu_crtc_page_flip(struct drm_crtc *crtc, ...@@ -191,7 +160,7 @@ int amdgpu_crtc_page_flip(struct drm_crtc *crtc,
if (work == NULL) if (work == NULL)
return -ENOMEM; return -ENOMEM;
INIT_WORK(&work->flip_work, amdgpu_flip_work_func); INIT_DELAYED_WORK(&work->flip_work, amdgpu_flip_work_func);
INIT_WORK(&work->unpin_work, amdgpu_unpin_work_func); INIT_WORK(&work->unpin_work, amdgpu_unpin_work_func);
work->event = event; work->event = event;
...@@ -237,12 +206,8 @@ int amdgpu_crtc_page_flip(struct drm_crtc *crtc, ...@@ -237,12 +206,8 @@ int amdgpu_crtc_page_flip(struct drm_crtc *crtc,
amdgpu_bo_unreserve(new_rbo); amdgpu_bo_unreserve(new_rbo);
work->base = base; work->base = base;
work->target_vblank = target - drm_crtc_vblank_count(crtc) +
r = drm_crtc_vblank_get(crtc); amdgpu_get_vblank_counter_kms(dev, work->crtc_id);
if (r) {
DRM_ERROR("failed to get vblank before flip\n");
goto pflip_cleanup;
}
/* we borrow the event spin lock for protecting flip_wrok */ /* we borrow the event spin lock for protecting flip_wrok */
spin_lock_irqsave(&crtc->dev->event_lock, flags); spin_lock_irqsave(&crtc->dev->event_lock, flags);
...@@ -250,7 +215,7 @@ int amdgpu_crtc_page_flip(struct drm_crtc *crtc, ...@@ -250,7 +215,7 @@ int amdgpu_crtc_page_flip(struct drm_crtc *crtc,
DRM_DEBUG_DRIVER("flip queue: crtc already busy\n"); DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
spin_unlock_irqrestore(&crtc->dev->event_lock, flags); spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
r = -EBUSY; r = -EBUSY;
goto vblank_cleanup; goto pflip_cleanup;
} }
amdgpu_crtc->pflip_status = AMDGPU_FLIP_PENDING; amdgpu_crtc->pflip_status = AMDGPU_FLIP_PENDING;
...@@ -262,12 +227,9 @@ int amdgpu_crtc_page_flip(struct drm_crtc *crtc, ...@@ -262,12 +227,9 @@ int amdgpu_crtc_page_flip(struct drm_crtc *crtc,
/* update crtc fb */ /* update crtc fb */
crtc->primary->fb = fb; crtc->primary->fb = fb;
spin_unlock_irqrestore(&crtc->dev->event_lock, flags); spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
amdgpu_flip_work_func(&work->flip_work); amdgpu_flip_work_func(&work->flip_work.work);
return 0; return 0;
vblank_cleanup:
drm_crtc_vblank_put(crtc);
pflip_cleanup: pflip_cleanup:
if (unlikely(amdgpu_bo_reserve(new_rbo, false) != 0)) { if (unlikely(amdgpu_bo_reserve(new_rbo, false) != 0)) {
DRM_ERROR("failed to reserve new rbo in error path\n"); DRM_ERROR("failed to reserve new rbo in error path\n");
...@@ -335,7 +297,7 @@ int amdgpu_crtc_set_config(struct drm_mode_set *set) ...@@ -335,7 +297,7 @@ int amdgpu_crtc_set_config(struct drm_mode_set *set)
return ret; return ret;
} }
static const char *encoder_names[38] = { static const char *encoder_names[41] = {
"NONE", "NONE",
"INTERNAL_LVDS", "INTERNAL_LVDS",
"INTERNAL_TMDS1", "INTERNAL_TMDS1",
...@@ -374,6 +336,9 @@ static const char *encoder_names[38] = { ...@@ -374,6 +336,9 @@ static const char *encoder_names[38] = {
"TRAVIS", "TRAVIS",
"INTERNAL_VCE", "INTERNAL_VCE",
"INTERNAL_UNIPHY3", "INTERNAL_UNIPHY3",
"HDMI_ANX9805",
"INTERNAL_AMCLK",
"VIRTUAL",
}; };
static const char *hpd_names[6] = { static const char *hpd_names[6] = {
......
...@@ -53,9 +53,11 @@ ...@@ -53,9 +53,11 @@
* - 3.2.0 - GFX8: Uses EOP_TC_WB_ACTION_EN, so UMDs don't have to do the same * - 3.2.0 - GFX8: Uses EOP_TC_WB_ACTION_EN, so UMDs don't have to do the same
* at the end of IBs. * at the end of IBs.
* - 3.3.0 - Add VM support for UVD on supported hardware. * - 3.3.0 - Add VM support for UVD on supported hardware.
* - 3.4.0 - Add AMDGPU_INFO_NUM_EVICTIONS.
* - 3.5.0 - Add support for new UVD_NO_OP register.
*/ */
#define KMS_DRIVER_MAJOR 3 #define KMS_DRIVER_MAJOR 3
#define KMS_DRIVER_MINOR 3 #define KMS_DRIVER_MINOR 5
#define KMS_DRIVER_PATCHLEVEL 0 #define KMS_DRIVER_PATCHLEVEL 0
int amdgpu_vram_limit = 0; int amdgpu_vram_limit = 0;
...@@ -84,11 +86,13 @@ int amdgpu_sched_jobs = 32; ...@@ -84,11 +86,13 @@ int amdgpu_sched_jobs = 32;
int amdgpu_sched_hw_submission = 2; int amdgpu_sched_hw_submission = 2;
int amdgpu_powerplay = -1; int amdgpu_powerplay = -1;
int amdgpu_powercontainment = 1; int amdgpu_powercontainment = 1;
int amdgpu_sclk_deep_sleep_en = 1;
unsigned amdgpu_pcie_gen_cap = 0; unsigned amdgpu_pcie_gen_cap = 0;
unsigned amdgpu_pcie_lane_cap = 0; unsigned amdgpu_pcie_lane_cap = 0;
unsigned amdgpu_cg_mask = 0xffffffff; unsigned amdgpu_cg_mask = 0xffffffff;
unsigned amdgpu_pg_mask = 0xffffffff; unsigned amdgpu_pg_mask = 0xffffffff;
char *amdgpu_disable_cu = NULL; char *amdgpu_disable_cu = NULL;
char *amdgpu_virtual_display = NULL;
MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing, in megabytes"); MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing, in megabytes");
module_param_named(vramlimit, amdgpu_vram_limit, int, 0600); module_param_named(vramlimit, amdgpu_vram_limit, int, 0600);
...@@ -170,6 +174,9 @@ MODULE_PARM_DESC(powercontainment, "Power Containment (1 = enable (default), 0 = ...@@ -170,6 +174,9 @@ MODULE_PARM_DESC(powercontainment, "Power Containment (1 = enable (default), 0 =
module_param_named(powercontainment, amdgpu_powercontainment, int, 0444); module_param_named(powercontainment, amdgpu_powercontainment, int, 0444);
#endif #endif
MODULE_PARM_DESC(sclkdeepsleep, "SCLK Deep Sleep (1 = enable (default), 0 = disable)");
module_param_named(sclkdeepsleep, amdgpu_sclk_deep_sleep_en, int, 0444);
MODULE_PARM_DESC(pcie_gen_cap, "PCIE Gen Caps (0: autodetect (default))"); MODULE_PARM_DESC(pcie_gen_cap, "PCIE Gen Caps (0: autodetect (default))");
module_param_named(pcie_gen_cap, amdgpu_pcie_gen_cap, uint, 0444); module_param_named(pcie_gen_cap, amdgpu_pcie_gen_cap, uint, 0444);
...@@ -185,6 +192,9 @@ module_param_named(pg_mask, amdgpu_pg_mask, uint, 0444); ...@@ -185,6 +192,9 @@ module_param_named(pg_mask, amdgpu_pg_mask, uint, 0444);
MODULE_PARM_DESC(disable_cu, "Disable CUs (se.sh.cu,...)"); MODULE_PARM_DESC(disable_cu, "Disable CUs (se.sh.cu,...)");
module_param_named(disable_cu, amdgpu_disable_cu, charp, 0444); module_param_named(disable_cu, amdgpu_disable_cu, charp, 0444);
MODULE_PARM_DESC(virtual_display, "Enable virtual display feature (the virtual_display will be set like xxxx:xx:xx.x;xxxx:xx:xx.x)");
module_param_named(virtual_display, amdgpu_virtual_display, charp, 0444);
static const struct pci_device_id pciidlist[] = { static const struct pci_device_id pciidlist[] = {
#ifdef CONFIG_DRM_AMDGPU_CIK #ifdef CONFIG_DRM_AMDGPU_CIK
/* Kaveri */ /* Kaveri */
......
...@@ -31,14 +31,6 @@ ...@@ -31,14 +31,6 @@
#define AMDGPU_GWS_SHIFT PAGE_SHIFT #define AMDGPU_GWS_SHIFT PAGE_SHIFT
#define AMDGPU_OA_SHIFT PAGE_SHIFT #define AMDGPU_OA_SHIFT PAGE_SHIFT
#define AMDGPU_PL_GDS TTM_PL_PRIV0
#define AMDGPU_PL_GWS TTM_PL_PRIV1
#define AMDGPU_PL_OA TTM_PL_PRIV2
#define AMDGPU_PL_FLAG_GDS TTM_PL_FLAG_PRIV0
#define AMDGPU_PL_FLAG_GWS TTM_PL_FLAG_PRIV1
#define AMDGPU_PL_FLAG_OA TTM_PL_FLAG_PRIV2
struct amdgpu_ring; struct amdgpu_ring;
struct amdgpu_bo; struct amdgpu_bo;
......
...@@ -186,10 +186,8 @@ struct amdgpu_i2c_chan *amdgpu_i2c_create(struct drm_device *dev, ...@@ -186,10 +186,8 @@ struct amdgpu_i2c_chan *amdgpu_i2c_create(struct drm_device *dev,
"AMDGPU i2c hw bus %s", name); "AMDGPU i2c hw bus %s", name);
i2c->adapter.algo = &amdgpu_atombios_i2c_algo; i2c->adapter.algo = &amdgpu_atombios_i2c_algo;
ret = i2c_add_adapter(&i2c->adapter); ret = i2c_add_adapter(&i2c->adapter);
if (ret) { if (ret)
DRM_ERROR("Failed to register hw i2c %s\n", name);
goto out_free; goto out_free;
}
} else { } else {
/* set the amdgpu bit adapter */ /* set the amdgpu bit adapter */
snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), snprintf(i2c->adapter.name, sizeof(i2c->adapter.name),
......
...@@ -142,7 +142,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, ...@@ -142,7 +142,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
} }
if (!ring->ready) { if (!ring->ready) {
dev_err(adev->dev, "couldn't schedule ib\n"); dev_err(adev->dev, "couldn't schedule ib on ring <%s>\n", ring->name);
return -EINVAL; return -EINVAL;
} }
......
...@@ -40,30 +40,13 @@ static int amdgpu_ih_ring_alloc(struct amdgpu_device *adev) ...@@ -40,30 +40,13 @@ static int amdgpu_ih_ring_alloc(struct amdgpu_device *adev)
/* Allocate ring buffer */ /* Allocate ring buffer */
if (adev->irq.ih.ring_obj == NULL) { if (adev->irq.ih.ring_obj == NULL) {
r = amdgpu_bo_create(adev, adev->irq.ih.ring_size, r = amdgpu_bo_create_kernel(adev, adev->irq.ih.ring_size,
PAGE_SIZE, true, PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT,
AMDGPU_GEM_DOMAIN_GTT, 0, &adev->irq.ih.ring_obj,
NULL, NULL, &adev->irq.ih.ring_obj); &adev->irq.ih.gpu_addr,
if (r) {
DRM_ERROR("amdgpu: failed to create ih ring buffer (%d).\n", r);
return r;
}
r = amdgpu_bo_reserve(adev->irq.ih.ring_obj, false);
if (unlikely(r != 0))
return r;
r = amdgpu_bo_pin(adev->irq.ih.ring_obj,
AMDGPU_GEM_DOMAIN_GTT,
&adev->irq.ih.gpu_addr);
if (r) {
amdgpu_bo_unreserve(adev->irq.ih.ring_obj);
DRM_ERROR("amdgpu: failed to pin ih ring buffer (%d).\n", r);
return r;
}
r = amdgpu_bo_kmap(adev->irq.ih.ring_obj,
(void **)&adev->irq.ih.ring); (void **)&adev->irq.ih.ring);
amdgpu_bo_unreserve(adev->irq.ih.ring_obj);
if (r) { if (r) {
DRM_ERROR("amdgpu: failed to map ih ring buffer (%d).\n", r); DRM_ERROR("amdgpu: failed to create ih ring buffer (%d).\n", r);
return r; return r;
} }
} }
......
...@@ -70,6 +70,7 @@ struct amdgpu_irq { ...@@ -70,6 +70,7 @@ struct amdgpu_irq {
/* gen irq stuff */ /* gen irq stuff */
struct irq_domain *domain; /* GPU irq controller domain */ struct irq_domain *domain; /* GPU irq controller domain */
unsigned virq[AMDGPU_MAX_IRQ_SRC_ID]; unsigned virq[AMDGPU_MAX_IRQ_SRC_ID];
uint32_t srbm_soft_reset;
}; };
void amdgpu_irq_preinstall(struct drm_device *dev); void amdgpu_irq_preinstall(struct drm_device *dev);
......
...@@ -292,14 +292,14 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file ...@@ -292,14 +292,14 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
type = AMD_IP_BLOCK_TYPE_UVD; type = AMD_IP_BLOCK_TYPE_UVD;
ring_mask = adev->uvd.ring.ready ? 1 : 0; ring_mask = adev->uvd.ring.ready ? 1 : 0;
ib_start_alignment = AMDGPU_GPU_PAGE_SIZE; ib_start_alignment = AMDGPU_GPU_PAGE_SIZE;
ib_size_alignment = 8; ib_size_alignment = 16;
break; break;
case AMDGPU_HW_IP_VCE: case AMDGPU_HW_IP_VCE:
type = AMD_IP_BLOCK_TYPE_VCE; type = AMD_IP_BLOCK_TYPE_VCE;
for (i = 0; i < AMDGPU_MAX_VCE_RINGS; i++) for (i = 0; i < AMDGPU_MAX_VCE_RINGS; i++)
ring_mask |= ((adev->vce.ring[i].ready ? 1 : 0) << i); ring_mask |= ((adev->vce.ring[i].ready ? 1 : 0) << i);
ib_start_alignment = AMDGPU_GPU_PAGE_SIZE; ib_start_alignment = AMDGPU_GPU_PAGE_SIZE;
ib_size_alignment = 8; ib_size_alignment = 1;
break; break;
default: default:
return -EINVAL; return -EINVAL;
...@@ -373,6 +373,9 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file ...@@ -373,6 +373,9 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
case AMDGPU_INFO_NUM_BYTES_MOVED: case AMDGPU_INFO_NUM_BYTES_MOVED:
ui64 = atomic64_read(&adev->num_bytes_moved); ui64 = atomic64_read(&adev->num_bytes_moved);
return copy_to_user(out, &ui64, min(size, 8u)) ? -EFAULT : 0; return copy_to_user(out, &ui64, min(size, 8u)) ? -EFAULT : 0;
case AMDGPU_INFO_NUM_EVICTIONS:
ui64 = atomic64_read(&adev->num_evictions);
return copy_to_user(out, &ui64, min(size, 8u)) ? -EFAULT : 0;
case AMDGPU_INFO_VRAM_USAGE: case AMDGPU_INFO_VRAM_USAGE:
ui64 = atomic64_read(&adev->vram_usage); ui64 = atomic64_read(&adev->vram_usage);
return copy_to_user(out, &ui64, min(size, 8u)) ? -EFAULT : 0; return copy_to_user(out, &ui64, min(size, 8u)) ? -EFAULT : 0;
......
...@@ -39,6 +39,8 @@ ...@@ -39,6 +39,8 @@
#include <drm/drm_plane_helper.h> #include <drm/drm_plane_helper.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-algo-bit.h> #include <linux/i2c-algo-bit.h>
#include <linux/hrtimer.h>
#include "amdgpu_irq.h"
struct amdgpu_bo; struct amdgpu_bo;
struct amdgpu_device; struct amdgpu_device;
...@@ -339,6 +341,8 @@ struct amdgpu_mode_info { ...@@ -339,6 +341,8 @@ struct amdgpu_mode_info {
int num_dig; /* number of dig blocks */ int num_dig; /* number of dig blocks */
int disp_priority; int disp_priority;
const struct amdgpu_display_funcs *funcs; const struct amdgpu_display_funcs *funcs;
struct hrtimer vblank_timer;
enum amdgpu_interrupt_state vsync_timer_enabled;
}; };
#define AMDGPU_MAX_BL_LEVEL 0xFF #define AMDGPU_MAX_BL_LEVEL 0xFF
...@@ -587,10 +591,10 @@ int amdgpu_align_pitch(struct amdgpu_device *adev, int width, int bpp, bool tile ...@@ -587,10 +591,10 @@ int amdgpu_align_pitch(struct amdgpu_device *adev, int width, int bpp, bool tile
void amdgpu_print_display_setup(struct drm_device *dev); void amdgpu_print_display_setup(struct drm_device *dev);
int amdgpu_modeset_create_props(struct amdgpu_device *adev); int amdgpu_modeset_create_props(struct amdgpu_device *adev);
int amdgpu_crtc_set_config(struct drm_mode_set *set); int amdgpu_crtc_set_config(struct drm_mode_set *set);
int amdgpu_crtc_page_flip(struct drm_crtc *crtc, int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc,
struct drm_framebuffer *fb, struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event, struct drm_pending_vblank_event *event,
uint32_t page_flip_flags); uint32_t page_flip_flags, uint32_t target);
extern const struct drm_mode_config_funcs amdgpu_mode_funcs; extern const struct drm_mode_config_funcs amdgpu_mode_funcs;
#endif #endif
...@@ -44,14 +44,13 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev); ...@@ -44,14 +44,13 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev);
static u64 amdgpu_get_vis_part_size(struct amdgpu_device *adev, static u64 amdgpu_get_vis_part_size(struct amdgpu_device *adev,
struct ttm_mem_reg *mem) struct ttm_mem_reg *mem)
{ {
u64 ret = 0; if (mem->start << PAGE_SHIFT >= adev->mc.visible_vram_size)
if (mem->start << PAGE_SHIFT < adev->mc.visible_vram_size) { return 0;
ret = (u64)((mem->start << PAGE_SHIFT) + mem->size) >
return ((mem->start << PAGE_SHIFT) + mem->size) >
adev->mc.visible_vram_size ? adev->mc.visible_vram_size ?
adev->mc.visible_vram_size - (mem->start << PAGE_SHIFT) : adev->mc.visible_vram_size - (mem->start << PAGE_SHIFT) :
mem->size; mem->size;
}
return ret;
} }
static void amdgpu_update_memory_usage(struct amdgpu_device *adev, static void amdgpu_update_memory_usage(struct amdgpu_device *adev,
...@@ -99,6 +98,11 @@ static void amdgpu_ttm_bo_destroy(struct ttm_buffer_object *tbo) ...@@ -99,6 +98,11 @@ static void amdgpu_ttm_bo_destroy(struct ttm_buffer_object *tbo)
drm_gem_object_release(&bo->gem_base); drm_gem_object_release(&bo->gem_base);
amdgpu_bo_unref(&bo->parent); amdgpu_bo_unref(&bo->parent);
if (!list_empty(&bo->shadow_list)) {
mutex_lock(&bo->adev->shadow_list_lock);
list_del_init(&bo->shadow_list);
mutex_unlock(&bo->adev->shadow_list_lock);
}
kfree(bo->metadata); kfree(bo->metadata);
kfree(bo); kfree(bo);
} }
...@@ -112,84 +116,93 @@ bool amdgpu_ttm_bo_is_amdgpu_bo(struct ttm_buffer_object *bo) ...@@ -112,84 +116,93 @@ bool amdgpu_ttm_bo_is_amdgpu_bo(struct ttm_buffer_object *bo)
static void amdgpu_ttm_placement_init(struct amdgpu_device *adev, static void amdgpu_ttm_placement_init(struct amdgpu_device *adev,
struct ttm_placement *placement, struct ttm_placement *placement,
struct ttm_place *placements, struct ttm_place *places,
u32 domain, u64 flags) u32 domain, u64 flags)
{ {
u32 c = 0, i; u32 c = 0;
placement->placement = placements;
placement->busy_placement = placements;
if (domain & AMDGPU_GEM_DOMAIN_VRAM) { if (domain & AMDGPU_GEM_DOMAIN_VRAM) {
unsigned visible_pfn = adev->mc.visible_vram_size >> PAGE_SHIFT;
if (flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS && if (flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS &&
!(flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) &&
adev->mc.visible_vram_size < adev->mc.real_vram_size) { adev->mc.visible_vram_size < adev->mc.real_vram_size) {
placements[c].fpfn = places[c].fpfn = visible_pfn;
adev->mc.visible_vram_size >> PAGE_SHIFT; places[c].lpfn = 0;
placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | places[c].flags = TTM_PL_FLAG_WC |
TTM_PL_FLAG_VRAM | TTM_PL_FLAG_TOPDOWN; TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM |
TTM_PL_FLAG_TOPDOWN;
c++;
} }
placements[c].fpfn = 0;
placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | places[c].fpfn = 0;
places[c].lpfn = 0;
places[c].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED |
TTM_PL_FLAG_VRAM; TTM_PL_FLAG_VRAM;
if (!(flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED)) if (flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED)
placements[c - 1].flags |= TTM_PL_FLAG_TOPDOWN; places[c].lpfn = visible_pfn;
else
places[c].flags |= TTM_PL_FLAG_TOPDOWN;
c++;
} }
if (domain & AMDGPU_GEM_DOMAIN_GTT) { if (domain & AMDGPU_GEM_DOMAIN_GTT) {
if (flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC) { places[c].fpfn = 0;
placements[c].fpfn = 0; places[c].lpfn = 0;
placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_TT | places[c].flags = TTM_PL_FLAG_TT;
if (flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC)
places[c].flags |= TTM_PL_FLAG_WC |
TTM_PL_FLAG_UNCACHED; TTM_PL_FLAG_UNCACHED;
} else { else
placements[c].fpfn = 0; places[c].flags |= TTM_PL_FLAG_CACHED;
placements[c++].flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_TT; c++;
}
} }
if (domain & AMDGPU_GEM_DOMAIN_CPU) { if (domain & AMDGPU_GEM_DOMAIN_CPU) {
if (flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC) { places[c].fpfn = 0;
placements[c].fpfn = 0; places[c].lpfn = 0;
placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_SYSTEM | places[c].flags = TTM_PL_FLAG_SYSTEM;
if (flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC)
places[c].flags |= TTM_PL_FLAG_WC |
TTM_PL_FLAG_UNCACHED; TTM_PL_FLAG_UNCACHED;
} else { else
placements[c].fpfn = 0; places[c].flags |= TTM_PL_FLAG_CACHED;
placements[c++].flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_SYSTEM; c++;
}
} }
if (domain & AMDGPU_GEM_DOMAIN_GDS) { if (domain & AMDGPU_GEM_DOMAIN_GDS) {
placements[c].fpfn = 0; places[c].fpfn = 0;
placements[c++].flags = TTM_PL_FLAG_UNCACHED | places[c].lpfn = 0;
AMDGPU_PL_FLAG_GDS; places[c].flags = TTM_PL_FLAG_UNCACHED | AMDGPU_PL_FLAG_GDS;
c++;
} }
if (domain & AMDGPU_GEM_DOMAIN_GWS) { if (domain & AMDGPU_GEM_DOMAIN_GWS) {
placements[c].fpfn = 0; places[c].fpfn = 0;
placements[c++].flags = TTM_PL_FLAG_UNCACHED | places[c].lpfn = 0;
AMDGPU_PL_FLAG_GWS; places[c].flags = TTM_PL_FLAG_UNCACHED | AMDGPU_PL_FLAG_GWS;
c++;
} }
if (domain & AMDGPU_GEM_DOMAIN_OA) { if (domain & AMDGPU_GEM_DOMAIN_OA) {
placements[c].fpfn = 0; places[c].fpfn = 0;
placements[c++].flags = TTM_PL_FLAG_UNCACHED | places[c].lpfn = 0;
AMDGPU_PL_FLAG_OA; places[c].flags = TTM_PL_FLAG_UNCACHED | AMDGPU_PL_FLAG_OA;
c++;
} }
if (!c) { if (!c) {
placements[c].fpfn = 0; places[c].fpfn = 0;
placements[c++].flags = TTM_PL_MASK_CACHING | places[c].lpfn = 0;
TTM_PL_FLAG_SYSTEM; places[c].flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
c++;
} }
placement->num_placement = c; placement->num_placement = c;
placement->num_busy_placement = c; placement->placement = places;
for (i = 0; i < c; i++) { placement->num_busy_placement = c;
if ((flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) && placement->busy_placement = places;
(placements[i].flags & TTM_PL_FLAG_VRAM) &&
!placements[i].fpfn)
placements[i].lpfn =
adev->mc.visible_vram_size >> PAGE_SHIFT;
else
placements[i].lpfn = 0;
}
} }
void amdgpu_ttm_placement_from_domain(struct amdgpu_bo *rbo, u32 domain) void amdgpu_ttm_placement_from_domain(struct amdgpu_bo *rbo, u32 domain)
...@@ -211,6 +224,69 @@ static void amdgpu_fill_placement_to_bo(struct amdgpu_bo *bo, ...@@ -211,6 +224,69 @@ static void amdgpu_fill_placement_to_bo(struct amdgpu_bo *bo,
bo->placement.busy_placement = bo->placements; bo->placement.busy_placement = bo->placements;
} }
/**
* amdgpu_bo_create_kernel - create BO for kernel use
*
* @adev: amdgpu device object
* @size: size for the new BO
* @align: alignment for the new BO
* @domain: where to place it
* @bo_ptr: resulting BO
* @gpu_addr: GPU addr of the pinned BO
* @cpu_addr: optional CPU address mapping
*
* Allocates and pins a BO for kernel internal use.
*
* Returns 0 on success, negative error code otherwise.
*/
int amdgpu_bo_create_kernel(struct amdgpu_device *adev,
unsigned long size, int align,
u32 domain, struct amdgpu_bo **bo_ptr,
u64 *gpu_addr, void **cpu_addr)
{
int r;
r = amdgpu_bo_create(adev, size, align, true, domain,
AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
NULL, NULL, bo_ptr);
if (r) {
dev_err(adev->dev, "(%d) failed to allocate kernel bo\n", r);
return r;
}
r = amdgpu_bo_reserve(*bo_ptr, false);
if (r) {
dev_err(adev->dev, "(%d) failed to reserve kernel bo\n", r);
goto error_free;
}
r = amdgpu_bo_pin(*bo_ptr, domain, gpu_addr);
if (r) {
dev_err(adev->dev, "(%d) kernel bo pin failed\n", r);
goto error_unreserve;
}
if (cpu_addr) {
r = amdgpu_bo_kmap(*bo_ptr, cpu_addr);
if (r) {
dev_err(adev->dev, "(%d) kernel bo map failed\n", r);
goto error_unreserve;
}
}
amdgpu_bo_unreserve(*bo_ptr);
return 0;
error_unreserve:
amdgpu_bo_unreserve(*bo_ptr);
error_free:
amdgpu_bo_unref(bo_ptr);
return r;
}
int amdgpu_bo_create_restricted(struct amdgpu_device *adev, int amdgpu_bo_create_restricted(struct amdgpu_device *adev,
unsigned long size, int byte_align, unsigned long size, int byte_align,
bool kernel, u32 domain, u64 flags, bool kernel, u32 domain, u64 flags,
...@@ -250,6 +326,7 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev, ...@@ -250,6 +326,7 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev,
} }
bo->adev = adev; bo->adev = adev;
INIT_LIST_HEAD(&bo->list); INIT_LIST_HEAD(&bo->list);
INIT_LIST_HEAD(&bo->shadow_list);
INIT_LIST_HEAD(&bo->va); INIT_LIST_HEAD(&bo->va);
bo->prefered_domains = domain & (AMDGPU_GEM_DOMAIN_VRAM | bo->prefered_domains = domain & (AMDGPU_GEM_DOMAIN_VRAM |
AMDGPU_GEM_DOMAIN_GTT | AMDGPU_GEM_DOMAIN_GTT |
...@@ -277,11 +354,79 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev, ...@@ -277,11 +354,79 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev,
if (unlikely(r != 0)) { if (unlikely(r != 0)) {
return r; return r;
} }
if (flags & AMDGPU_GEM_CREATE_VRAM_CLEARED &&
bo->tbo.mem.placement & TTM_PL_FLAG_VRAM) {
struct fence *fence;
if (adev->mman.buffer_funcs_ring == NULL ||
!adev->mman.buffer_funcs_ring->ready) {
r = -EBUSY;
goto fail_free;
}
r = amdgpu_bo_reserve(bo, false);
if (unlikely(r != 0))
goto fail_free;
amdgpu_ttm_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_VRAM);
r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
if (unlikely(r != 0))
goto fail_unreserve;
amdgpu_fill_buffer(bo, 0, bo->tbo.resv, &fence);
amdgpu_bo_fence(bo, fence, false);
amdgpu_bo_unreserve(bo);
fence_put(bo->tbo.moving);
bo->tbo.moving = fence_get(fence);
fence_put(fence);
}
*bo_ptr = bo; *bo_ptr = bo;
trace_amdgpu_bo_create(bo); trace_amdgpu_bo_create(bo);
return 0; return 0;
fail_unreserve:
amdgpu_bo_unreserve(bo);
fail_free:
amdgpu_bo_unref(&bo);
return r;
}
static int amdgpu_bo_create_shadow(struct amdgpu_device *adev,
unsigned long size, int byte_align,
struct amdgpu_bo *bo)
{
struct ttm_placement placement = {0};
struct ttm_place placements[AMDGPU_GEM_DOMAIN_MAX + 1];
int r;
if (bo->shadow)
return 0;
bo->flags |= AMDGPU_GEM_CREATE_SHADOW;
memset(&placements, 0,
(AMDGPU_GEM_DOMAIN_MAX + 1) * sizeof(struct ttm_place));
amdgpu_ttm_placement_init(adev, &placement,
placements, AMDGPU_GEM_DOMAIN_GTT,
AMDGPU_GEM_CREATE_CPU_GTT_USWC);
r = amdgpu_bo_create_restricted(adev, size, byte_align, true,
AMDGPU_GEM_DOMAIN_GTT,
AMDGPU_GEM_CREATE_CPU_GTT_USWC,
NULL, &placement,
bo->tbo.resv,
&bo->shadow);
if (!r) {
bo->shadow->parent = amdgpu_bo_ref(bo);
mutex_lock(&adev->shadow_list_lock);
list_add_tail(&bo->shadow_list, &adev->shadow_list);
mutex_unlock(&adev->shadow_list_lock);
}
return r;
} }
int amdgpu_bo_create(struct amdgpu_device *adev, int amdgpu_bo_create(struct amdgpu_device *adev,
...@@ -293,6 +438,7 @@ int amdgpu_bo_create(struct amdgpu_device *adev, ...@@ -293,6 +438,7 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
{ {
struct ttm_placement placement = {0}; struct ttm_placement placement = {0};
struct ttm_place placements[AMDGPU_GEM_DOMAIN_MAX + 1]; struct ttm_place placements[AMDGPU_GEM_DOMAIN_MAX + 1];
int r;
memset(&placements, 0, memset(&placements, 0,
(AMDGPU_GEM_DOMAIN_MAX + 1) * sizeof(struct ttm_place)); (AMDGPU_GEM_DOMAIN_MAX + 1) * sizeof(struct ttm_place));
...@@ -300,9 +446,83 @@ int amdgpu_bo_create(struct amdgpu_device *adev, ...@@ -300,9 +446,83 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
amdgpu_ttm_placement_init(adev, &placement, amdgpu_ttm_placement_init(adev, &placement,
placements, domain, flags); placements, domain, flags);
return amdgpu_bo_create_restricted(adev, size, byte_align, kernel, r = amdgpu_bo_create_restricted(adev, size, byte_align, kernel,
domain, flags, sg, &placement, domain, flags, sg, &placement,
resv, bo_ptr); resv, bo_ptr);
if (r)
return r;
if (amdgpu_need_backup(adev) && (flags & AMDGPU_GEM_CREATE_SHADOW)) {
r = amdgpu_bo_create_shadow(adev, size, byte_align, (*bo_ptr));
if (r)
amdgpu_bo_unref(bo_ptr);
}
return r;
}
int amdgpu_bo_backup_to_shadow(struct amdgpu_device *adev,
struct amdgpu_ring *ring,
struct amdgpu_bo *bo,
struct reservation_object *resv,
struct fence **fence,
bool direct)
{
struct amdgpu_bo *shadow = bo->shadow;
uint64_t bo_addr, shadow_addr;
int r;
if (!shadow)
return -EINVAL;
bo_addr = amdgpu_bo_gpu_offset(bo);
shadow_addr = amdgpu_bo_gpu_offset(bo->shadow);
r = reservation_object_reserve_shared(bo->tbo.resv);
if (r)
goto err;
r = amdgpu_copy_buffer(ring, bo_addr, shadow_addr,
amdgpu_bo_size(bo), resv, fence,
direct);
if (!r)
amdgpu_bo_fence(bo, *fence, true);
err:
return r;
}
int amdgpu_bo_restore_from_shadow(struct amdgpu_device *adev,
struct amdgpu_ring *ring,
struct amdgpu_bo *bo,
struct reservation_object *resv,
struct fence **fence,
bool direct)
{
struct amdgpu_bo *shadow = bo->shadow;
uint64_t bo_addr, shadow_addr;
int r;
if (!shadow)
return -EINVAL;
bo_addr = amdgpu_bo_gpu_offset(bo);
shadow_addr = amdgpu_bo_gpu_offset(bo->shadow);
r = reservation_object_reserve_shared(bo->tbo.resv);
if (r)
goto err;
r = amdgpu_copy_buffer(ring, shadow_addr, bo_addr,
amdgpu_bo_size(bo), resv, fence,
direct);
if (!r)
amdgpu_bo_fence(bo, *fence, true);
err:
return r;
} }
int amdgpu_bo_kmap(struct amdgpu_bo *bo, void **ptr) int amdgpu_bo_kmap(struct amdgpu_bo *bo, void **ptr)
...@@ -380,16 +600,17 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, ...@@ -380,16 +600,17 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
return -EINVAL; return -EINVAL;
if (bo->pin_count) { if (bo->pin_count) {
uint32_t mem_type = bo->tbo.mem.mem_type;
if (domain != amdgpu_mem_type_to_domain(mem_type))
return -EINVAL;
bo->pin_count++; bo->pin_count++;
if (gpu_addr) if (gpu_addr)
*gpu_addr = amdgpu_bo_gpu_offset(bo); *gpu_addr = amdgpu_bo_gpu_offset(bo);
if (max_offset != 0) { if (max_offset != 0) {
u64 domain_start; u64 domain_start = bo->tbo.bdev->man[mem_type].gpu_offset;
if (domain == AMDGPU_GEM_DOMAIN_VRAM)
domain_start = bo->adev->mc.vram_start;
else
domain_start = bo->adev->mc.gtt_start;
WARN_ON_ONCE(max_offset < WARN_ON_ONCE(max_offset <
(amdgpu_bo_gpu_offset(bo) - domain_start)); (amdgpu_bo_gpu_offset(bo) - domain_start));
} }
...@@ -401,7 +622,8 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, ...@@ -401,7 +622,8 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
/* force to pin into visible video ram */ /* force to pin into visible video ram */
if ((bo->placements[i].flags & TTM_PL_FLAG_VRAM) && if ((bo->placements[i].flags & TTM_PL_FLAG_VRAM) &&
!(bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS) && !(bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS) &&
(!max_offset || max_offset > bo->adev->mc.visible_vram_size)) { (!max_offset || max_offset >
bo->adev->mc.visible_vram_size)) {
if (WARN_ON_ONCE(min_offset > if (WARN_ON_ONCE(min_offset >
bo->adev->mc.visible_vram_size)) bo->adev->mc.visible_vram_size))
return -EINVAL; return -EINVAL;
...@@ -420,7 +642,11 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, ...@@ -420,7 +642,11 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
} }
r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false); r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
if (likely(r == 0)) { if (unlikely(r)) {
dev_err(bo->adev->dev, "%p pin failed\n", bo);
goto error;
}
bo->pin_count = 1; bo->pin_count = 1;
if (gpu_addr != NULL) if (gpu_addr != NULL)
*gpu_addr = amdgpu_bo_gpu_offset(bo); *gpu_addr = amdgpu_bo_gpu_offset(bo);
...@@ -428,11 +654,11 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, ...@@ -428,11 +654,11 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
bo->adev->vram_pin_size += amdgpu_bo_size(bo); bo->adev->vram_pin_size += amdgpu_bo_size(bo);
if (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS) if (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)
bo->adev->invisible_pin_size += amdgpu_bo_size(bo); bo->adev->invisible_pin_size += amdgpu_bo_size(bo);
} else } else if (domain == AMDGPU_GEM_DOMAIN_GTT) {
bo->adev->gart_pin_size += amdgpu_bo_size(bo); bo->adev->gart_pin_size += amdgpu_bo_size(bo);
} else {
dev_err(bo->adev->dev, "%p pin failed\n", bo);
} }
error:
return r; return r;
} }
...@@ -457,16 +683,20 @@ int amdgpu_bo_unpin(struct amdgpu_bo *bo) ...@@ -457,16 +683,20 @@ int amdgpu_bo_unpin(struct amdgpu_bo *bo)
bo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT; bo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT;
} }
r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false); r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
if (likely(r == 0)) { if (unlikely(r)) {
dev_err(bo->adev->dev, "%p validate failed for unpin\n", bo);
goto error;
}
if (bo->tbo.mem.mem_type == TTM_PL_VRAM) { if (bo->tbo.mem.mem_type == TTM_PL_VRAM) {
bo->adev->vram_pin_size -= amdgpu_bo_size(bo); bo->adev->vram_pin_size -= amdgpu_bo_size(bo);
if (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS) if (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)
bo->adev->invisible_pin_size -= amdgpu_bo_size(bo); bo->adev->invisible_pin_size -= amdgpu_bo_size(bo);
} else
bo->adev->gart_pin_size -= amdgpu_bo_size(bo);
} else { } else {
dev_err(bo->adev->dev, "%p validate failed for unpin\n", bo); bo->adev->gart_pin_size -= amdgpu_bo_size(bo);
} }
error:
return r; return r;
} }
...@@ -637,7 +867,8 @@ int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) ...@@ -637,7 +867,8 @@ int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
for (i = 0; i < abo->placement.num_placement; i++) { for (i = 0; i < abo->placement.num_placement; i++) {
/* Force into visible VRAM */ /* Force into visible VRAM */
if ((abo->placements[i].flags & TTM_PL_FLAG_VRAM) && if ((abo->placements[i].flags & TTM_PL_FLAG_VRAM) &&
(!abo->placements[i].lpfn || abo->placements[i].lpfn > lpfn)) (!abo->placements[i].lpfn ||
abo->placements[i].lpfn > lpfn))
abo->placements[i].lpfn = lpfn; abo->placements[i].lpfn = lpfn;
} }
r = ttm_bo_validate(bo, &abo->placement, false, false); r = ttm_bo_validate(bo, &abo->placement, false, false);
...@@ -674,3 +905,21 @@ void amdgpu_bo_fence(struct amdgpu_bo *bo, struct fence *fence, ...@@ -674,3 +905,21 @@ void amdgpu_bo_fence(struct amdgpu_bo *bo, struct fence *fence,
else else
reservation_object_add_excl_fence(resv, fence); reservation_object_add_excl_fence(resv, fence);
} }
/**
* amdgpu_bo_gpu_offset - return GPU offset of bo
* @bo: amdgpu object for which we query the offset
*
* Returns current GPU offset of the object.
*
* Note: object should either be pinned or reserved when calling this
* function, it might be useful to add check for this for debugging.
*/
u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo)
{
WARN_ON_ONCE(bo->tbo.mem.mem_type == TTM_PL_SYSTEM);
WARN_ON_ONCE(!ww_mutex_is_locked(&bo->tbo.resv->lock) &&
!bo->pin_count);
return bo->tbo.offset;
}
...@@ -85,21 +85,6 @@ static inline void amdgpu_bo_unreserve(struct amdgpu_bo *bo) ...@@ -85,21 +85,6 @@ static inline void amdgpu_bo_unreserve(struct amdgpu_bo *bo)
ttm_bo_unreserve(&bo->tbo); ttm_bo_unreserve(&bo->tbo);
} }
/**
* amdgpu_bo_gpu_offset - return GPU offset of bo
* @bo: amdgpu object for which we query the offset
*
* Returns current GPU offset of the object.
*
* Note: object should either be pinned or reserved when calling this
* function, it might be useful to add check for this for debugging.
*/
static inline u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo)
{
WARN_ON_ONCE(bo->tbo.mem.mem_type == TTM_PL_SYSTEM);
return bo->tbo.offset;
}
static inline unsigned long amdgpu_bo_size(struct amdgpu_bo *bo) static inline unsigned long amdgpu_bo_size(struct amdgpu_bo *bo)
{ {
return bo->tbo.num_pages << PAGE_SHIFT; return bo->tbo.num_pages << PAGE_SHIFT;
...@@ -139,6 +124,10 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev, ...@@ -139,6 +124,10 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev,
struct ttm_placement *placement, struct ttm_placement *placement,
struct reservation_object *resv, struct reservation_object *resv,
struct amdgpu_bo **bo_ptr); struct amdgpu_bo **bo_ptr);
int amdgpu_bo_create_kernel(struct amdgpu_device *adev,
unsigned long size, int align,
u32 domain, struct amdgpu_bo **bo_ptr,
u64 *gpu_addr, void **cpu_addr);
int amdgpu_bo_kmap(struct amdgpu_bo *bo, void **ptr); int amdgpu_bo_kmap(struct amdgpu_bo *bo, void **ptr);
void amdgpu_bo_kunmap(struct amdgpu_bo *bo); void amdgpu_bo_kunmap(struct amdgpu_bo *bo);
struct amdgpu_bo *amdgpu_bo_ref(struct amdgpu_bo *bo); struct amdgpu_bo *amdgpu_bo_ref(struct amdgpu_bo *bo);
...@@ -165,6 +154,19 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, ...@@ -165,6 +154,19 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo); int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo);
void amdgpu_bo_fence(struct amdgpu_bo *bo, struct fence *fence, void amdgpu_bo_fence(struct amdgpu_bo *bo, struct fence *fence,
bool shared); bool shared);
u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo);
int amdgpu_bo_backup_to_shadow(struct amdgpu_device *adev,
struct amdgpu_ring *ring,
struct amdgpu_bo *bo,
struct reservation_object *resv,
struct fence **fence, bool direct);
int amdgpu_bo_restore_from_shadow(struct amdgpu_device *adev,
struct amdgpu_ring *ring,
struct amdgpu_bo *bo,
struct reservation_object *resv,
struct fence **fence,
bool direct);
/* /*
* sub allocation * sub allocation
......
...@@ -1103,12 +1103,9 @@ static void amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) ...@@ -1103,12 +1103,9 @@ static void amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev)
void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable) void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable)
{ {
if (adev->pp_enabled) if (adev->pp_enabled || adev->pm.funcs->powergate_uvd) {
amdgpu_dpm_powergate_uvd(adev, !enable);
else {
if (adev->pm.funcs->powergate_uvd) {
mutex_lock(&adev->pm.mutex);
/* enable/disable UVD */ /* enable/disable UVD */
mutex_lock(&adev->pm.mutex);
amdgpu_dpm_powergate_uvd(adev, !enable); amdgpu_dpm_powergate_uvd(adev, !enable);
mutex_unlock(&adev->pm.mutex); mutex_unlock(&adev->pm.mutex);
} else { } else {
...@@ -1124,16 +1121,12 @@ void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable) ...@@ -1124,16 +1121,12 @@ void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable)
} }
amdgpu_pm_compute_clocks(adev); amdgpu_pm_compute_clocks(adev);
} }
}
} }
void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable) void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable)
{ {
if (adev->pp_enabled) if (adev->pp_enabled || adev->pm.funcs->powergate_vce) {
amdgpu_dpm_powergate_vce(adev, !enable); /* enable/disable VCE */
else {
if (adev->pm.funcs->powergate_vce) {
mutex_lock(&adev->pm.mutex); mutex_lock(&adev->pm.mutex);
amdgpu_dpm_powergate_vce(adev, !enable); amdgpu_dpm_powergate_vce(adev, !enable);
mutex_unlock(&adev->pm.mutex); mutex_unlock(&adev->pm.mutex);
...@@ -1151,7 +1144,6 @@ void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable) ...@@ -1151,7 +1144,6 @@ void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable)
} }
amdgpu_pm_compute_clocks(adev); amdgpu_pm_compute_clocks(adev);
} }
}
} }
void amdgpu_pm_print_power_states(struct amdgpu_device *adev) void amdgpu_pm_print_power_states(struct amdgpu_device *adev)
......
...@@ -52,7 +52,9 @@ static int amdgpu_powerplay_init(struct amdgpu_device *adev) ...@@ -52,7 +52,9 @@ static int amdgpu_powerplay_init(struct amdgpu_device *adev)
pp_init->chip_family = adev->family; pp_init->chip_family = adev->family;
pp_init->chip_id = adev->asic_type; pp_init->chip_id = adev->asic_type;
pp_init->device = amdgpu_cgs_create_device(adev); pp_init->device = amdgpu_cgs_create_device(adev);
pp_init->powercontainment_enabled = amdgpu_powercontainment; pp_init->rev_id = adev->pdev->revision;
pp_init->sub_sys_id = adev->pdev->subsystem_device;
pp_init->sub_vendor_id = adev->pdev->subsystem_vendor;
ret = amd_powerplay_init(pp_init, amd_pp); ret = amd_powerplay_init(pp_init, amd_pp);
kfree(pp_init); kfree(pp_init);
...@@ -106,11 +108,10 @@ static int amdgpu_pp_early_init(void *handle) ...@@ -106,11 +108,10 @@ static int amdgpu_pp_early_init(void *handle)
break; break;
case CHIP_TONGA: case CHIP_TONGA:
case CHIP_FIJI: case CHIP_FIJI:
adev->pp_enabled = (amdgpu_powerplay == 0) ? false : true; case CHIP_TOPAZ:
break;
case CHIP_CARRIZO: case CHIP_CARRIZO:
case CHIP_STONEY: case CHIP_STONEY:
adev->pp_enabled = (amdgpu_powerplay > 0) ? true : false; adev->pp_enabled = (amdgpu_powerplay == 0) ? false : true;
break; break;
/* These chips don't have powerplay implemenations */ /* These chips don't have powerplay implemenations */
case CHIP_BONAIRE: case CHIP_BONAIRE:
...@@ -118,7 +119,6 @@ static int amdgpu_pp_early_init(void *handle) ...@@ -118,7 +119,6 @@ static int amdgpu_pp_early_init(void *handle)
case CHIP_KABINI: case CHIP_KABINI:
case CHIP_MULLINS: case CHIP_MULLINS:
case CHIP_KAVERI: case CHIP_KAVERI:
case CHIP_TOPAZ:
default: default:
adev->pp_enabled = false; adev->pp_enabled = false;
break; break;
......
...@@ -222,33 +222,16 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, ...@@ -222,33 +222,16 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
/* Allocate ring buffer */ /* Allocate ring buffer */
if (ring->ring_obj == NULL) { if (ring->ring_obj == NULL) {
r = amdgpu_bo_create(adev, ring->ring_size, PAGE_SIZE, true, r = amdgpu_bo_create_kernel(adev, ring->ring_size, PAGE_SIZE,
AMDGPU_GEM_DOMAIN_GTT, 0, AMDGPU_GEM_DOMAIN_GTT,
NULL, NULL, &ring->ring_obj); &ring->ring_obj,
&ring->gpu_addr,
(void **)&ring->ring);
if (r) { if (r) {
dev_err(adev->dev, "(%d) ring create failed\n", r); dev_err(adev->dev, "(%d) ring create failed\n", r);
return r; return r;
} }
r = amdgpu_bo_reserve(ring->ring_obj, false);
if (unlikely(r != 0))
return r;
r = amdgpu_bo_pin(ring->ring_obj, AMDGPU_GEM_DOMAIN_GTT,
&ring->gpu_addr);
if (r) {
amdgpu_bo_unreserve(ring->ring_obj);
dev_err(adev->dev, "(%d) ring pin failed\n", r);
return r;
}
r = amdgpu_bo_kmap(ring->ring_obj,
(void **)&ring->ring);
memset((void *)ring->ring, 0, ring->ring_size); memset((void *)ring->ring, 0, ring->ring_size);
amdgpu_bo_unreserve(ring->ring_obj);
if (r) {
dev_err(adev->dev, "(%d) ring map failed\n", r);
return r;
}
} }
ring->ptr_mask = (ring->ring_size / 4) - 1; ring->ptr_mask = (ring->ring_size / 4) - 1;
ring->max_dw = max_dw; ring->max_dw = max_dw;
......
...@@ -111,7 +111,7 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev) ...@@ -111,7 +111,7 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev)
amdgpu_bo_kunmap(gtt_obj[i]); amdgpu_bo_kunmap(gtt_obj[i]);
r = amdgpu_copy_buffer(ring, gtt_addr, vram_addr, r = amdgpu_copy_buffer(ring, gtt_addr, vram_addr,
size, NULL, &fence); size, NULL, &fence, false);
if (r) { if (r) {
DRM_ERROR("Failed GTT->VRAM copy %d\n", i); DRM_ERROR("Failed GTT->VRAM copy %d\n", i);
...@@ -156,7 +156,7 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev) ...@@ -156,7 +156,7 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev)
amdgpu_bo_kunmap(vram_obj); amdgpu_bo_kunmap(vram_obj);
r = amdgpu_copy_buffer(ring, vram_addr, gtt_addr, r = amdgpu_copy_buffer(ring, vram_addr, gtt_addr,
size, NULL, &fence); size, NULL, &fence, false);
if (r) { if (r) {
DRM_ERROR("Failed VRAM->GTT copy %d\n", i); DRM_ERROR("Failed VRAM->GTT copy %d\n", i);
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <ttm/ttm_placement.h> #include <ttm/ttm_placement.h>
#include <ttm/ttm_module.h> #include <ttm/ttm_module.h>
#include <ttm/ttm_page_alloc.h> #include <ttm/ttm_page_alloc.h>
#include <ttm/ttm_memory.h>
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/amdgpu_drm.h> #include <drm/amdgpu_drm.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
...@@ -74,7 +75,7 @@ static void amdgpu_ttm_mem_global_release(struct drm_global_reference *ref) ...@@ -74,7 +75,7 @@ static void amdgpu_ttm_mem_global_release(struct drm_global_reference *ref)
ttm_mem_global_release(ref->object); ttm_mem_global_release(ref->object);
} }
static int amdgpu_ttm_global_init(struct amdgpu_device *adev) int amdgpu_ttm_global_init(struct amdgpu_device *adev)
{ {
struct drm_global_reference *global_ref; struct drm_global_reference *global_ref;
struct amdgpu_ring *ring; struct amdgpu_ring *ring;
...@@ -256,10 +257,8 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo, ...@@ -256,10 +257,8 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo,
switch (old_mem->mem_type) { switch (old_mem->mem_type) {
case TTM_PL_VRAM: case TTM_PL_VRAM:
old_start += adev->mc.vram_start;
break;
case TTM_PL_TT: case TTM_PL_TT:
old_start += adev->mc.gtt_start; old_start += bo->bdev->man[old_mem->mem_type].gpu_offset;
break; break;
default: default:
DRM_ERROR("Unknown placement %d\n", old_mem->mem_type); DRM_ERROR("Unknown placement %d\n", old_mem->mem_type);
...@@ -267,10 +266,8 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo, ...@@ -267,10 +266,8 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo,
} }
switch (new_mem->mem_type) { switch (new_mem->mem_type) {
case TTM_PL_VRAM: case TTM_PL_VRAM:
new_start += adev->mc.vram_start;
break;
case TTM_PL_TT: case TTM_PL_TT:
new_start += adev->mc.gtt_start; new_start += bo->bdev->man[new_mem->mem_type].gpu_offset;
break; break;
default: default:
DRM_ERROR("Unknown placement %d\n", old_mem->mem_type); DRM_ERROR("Unknown placement %d\n", old_mem->mem_type);
...@@ -285,7 +282,7 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo, ...@@ -285,7 +282,7 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo,
r = amdgpu_copy_buffer(ring, old_start, new_start, r = amdgpu_copy_buffer(ring, old_start, new_start,
new_mem->num_pages * PAGE_SIZE, /* bytes */ new_mem->num_pages * PAGE_SIZE, /* bytes */
bo->resv, &fence); bo->resv, &fence, false);
if (r) if (r)
return r; return r;
...@@ -335,7 +332,7 @@ static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo, ...@@ -335,7 +332,7 @@ static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo,
if (unlikely(r)) { if (unlikely(r)) {
goto out_cleanup; goto out_cleanup;
} }
r = ttm_bo_move_ttm(bo, true, interruptible, no_wait_gpu, new_mem); r = ttm_bo_move_ttm(bo, interruptible, no_wait_gpu, new_mem);
out_cleanup: out_cleanup:
ttm_bo_mem_put(bo, &tmp_mem); ttm_bo_mem_put(bo, &tmp_mem);
return r; return r;
...@@ -368,7 +365,7 @@ static int amdgpu_move_ram_vram(struct ttm_buffer_object *bo, ...@@ -368,7 +365,7 @@ static int amdgpu_move_ram_vram(struct ttm_buffer_object *bo,
if (unlikely(r)) { if (unlikely(r)) {
return r; return r;
} }
r = ttm_bo_move_ttm(bo, true, interruptible, no_wait_gpu, &tmp_mem); r = ttm_bo_move_ttm(bo, interruptible, no_wait_gpu, &tmp_mem);
if (unlikely(r)) { if (unlikely(r)) {
goto out_cleanup; goto out_cleanup;
} }
...@@ -435,8 +432,7 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, ...@@ -435,8 +432,7 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo,
if (r) { if (r) {
memcpy: memcpy:
r = ttm_bo_move_memcpy(bo, evict, interruptible, r = ttm_bo_move_memcpy(bo, interruptible, no_wait_gpu, new_mem);
no_wait_gpu, new_mem);
if (r) { if (r) {
return r; return r;
} }
...@@ -950,6 +946,8 @@ static struct list_head *amdgpu_ttm_lru_tail(struct ttm_buffer_object *tbo) ...@@ -950,6 +946,8 @@ static struct list_head *amdgpu_ttm_lru_tail(struct ttm_buffer_object *tbo)
struct list_head *res = lru->lru[tbo->mem.mem_type]; struct list_head *res = lru->lru[tbo->mem.mem_type];
lru->lru[tbo->mem.mem_type] = &tbo->lru; lru->lru[tbo->mem.mem_type] = &tbo->lru;
while ((++lru)->lru[tbo->mem.mem_type] == res)
lru->lru[tbo->mem.mem_type] = &tbo->lru;
return res; return res;
} }
...@@ -960,6 +958,8 @@ static struct list_head *amdgpu_ttm_swap_lru_tail(struct ttm_buffer_object *tbo) ...@@ -960,6 +958,8 @@ static struct list_head *amdgpu_ttm_swap_lru_tail(struct ttm_buffer_object *tbo)
struct list_head *res = lru->swap_lru; struct list_head *res = lru->swap_lru;
lru->swap_lru = &tbo->swap; lru->swap_lru = &tbo->swap;
while ((++lru)->swap_lru == res)
lru->swap_lru = &tbo->swap;
return res; return res;
} }
...@@ -987,10 +987,6 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) ...@@ -987,10 +987,6 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
unsigned i, j; unsigned i, j;
int r; int r;
r = amdgpu_ttm_global_init(adev);
if (r) {
return r;
}
/* No others user of address space so set it to 0 */ /* No others user of address space so set it to 0 */
r = ttm_bo_device_init(&adev->mman.bdev, r = ttm_bo_device_init(&adev->mman.bdev,
adev->mman.bo_global_ref.ref.object, adev->mman.bo_global_ref.ref.object,
...@@ -1011,6 +1007,10 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) ...@@ -1011,6 +1007,10 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
lru->swap_lru = &adev->mman.bdev.glob->swap_lru; lru->swap_lru = &adev->mman.bdev.glob->swap_lru;
} }
for (j = 0; j < TTM_NUM_MEM_TYPES; ++j)
adev->mman.guard.lru[j] = NULL;
adev->mman.guard.swap_lru = NULL;
adev->mman.initialized = true; adev->mman.initialized = true;
r = ttm_bo_init_mm(&adev->mman.bdev, TTM_PL_VRAM, r = ttm_bo_init_mm(&adev->mman.bdev, TTM_PL_VRAM,
adev->mc.real_vram_size >> PAGE_SHIFT); adev->mc.real_vram_size >> PAGE_SHIFT);
...@@ -1151,7 +1151,7 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring, ...@@ -1151,7 +1151,7 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring,
uint64_t dst_offset, uint64_t dst_offset,
uint32_t byte_count, uint32_t byte_count,
struct reservation_object *resv, struct reservation_object *resv,
struct fence **fence) struct fence **fence, bool direct_submit)
{ {
struct amdgpu_device *adev = ring->adev; struct amdgpu_device *adev = ring->adev;
struct amdgpu_job *job; struct amdgpu_job *job;
...@@ -1193,6 +1193,77 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring, ...@@ -1193,6 +1193,77 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring,
byte_count -= cur_size_in_bytes; byte_count -= cur_size_in_bytes;
} }
amdgpu_ring_pad_ib(ring, &job->ibs[0]);
WARN_ON(job->ibs[0].length_dw > num_dw);
if (direct_submit) {
r = amdgpu_ib_schedule(ring, job->num_ibs, job->ibs,
NULL, NULL, fence);
job->fence = fence_get(*fence);
if (r)
DRM_ERROR("Error scheduling IBs (%d)\n", r);
amdgpu_job_free(job);
} else {
r = amdgpu_job_submit(job, ring, &adev->mman.entity,
AMDGPU_FENCE_OWNER_UNDEFINED, fence);
if (r)
goto error_free;
}
return r;
error_free:
amdgpu_job_free(job);
return r;
}
int amdgpu_fill_buffer(struct amdgpu_bo *bo,
uint32_t src_data,
struct reservation_object *resv,
struct fence **fence)
{
struct amdgpu_device *adev = bo->adev;
struct amdgpu_job *job;
struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;
uint32_t max_bytes, byte_count;
uint64_t dst_offset;
unsigned int num_loops, num_dw;
unsigned int i;
int r;
byte_count = bo->tbo.num_pages << PAGE_SHIFT;
max_bytes = adev->mman.buffer_funcs->fill_max_bytes;
num_loops = DIV_ROUND_UP(byte_count, max_bytes);
num_dw = num_loops * adev->mman.buffer_funcs->fill_num_dw;
/* for IB padding */
while (num_dw & 0x7)
num_dw++;
r = amdgpu_job_alloc_with_ib(adev, num_dw * 4, &job);
if (r)
return r;
if (resv) {
r = amdgpu_sync_resv(adev, &job->sync, resv,
AMDGPU_FENCE_OWNER_UNDEFINED);
if (r) {
DRM_ERROR("sync failed (%d).\n", r);
goto error_free;
}
}
dst_offset = bo->tbo.mem.start << PAGE_SHIFT;
for (i = 0; i < num_loops; i++) {
uint32_t cur_size_in_bytes = min(byte_count, max_bytes);
amdgpu_emit_fill_buffer(adev, &job->ibs[0], src_data,
dst_offset, cur_size_in_bytes);
dst_offset += cur_size_in_bytes;
byte_count -= cur_size_in_bytes;
}
amdgpu_ring_pad_ib(ring, &job->ibs[0]); amdgpu_ring_pad_ib(ring, &job->ibs[0]);
WARN_ON(job->ibs[0].length_dw > num_dw); WARN_ON(job->ibs[0].length_dw > num_dw);
r = amdgpu_job_submit(job, ring, &adev->mman.entity, r = amdgpu_job_submit(job, ring, &adev->mman.entity,
...@@ -1387,3 +1458,8 @@ static void amdgpu_ttm_debugfs_fini(struct amdgpu_device *adev) ...@@ -1387,3 +1458,8 @@ static void amdgpu_ttm_debugfs_fini(struct amdgpu_device *adev)
#endif #endif
} }
u64 amdgpu_ttm_get_gtt_mem_size(struct amdgpu_device *adev)
{
return ttm_get_kernel_zone_memory_size(adev->mman.mem_global_ref.object);
}
/*
* Copyright 2016 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef __AMDGPU_TTM_H__
#define __AMDGPU_TTM_H__
#include "gpu_scheduler.h"
#define AMDGPU_PL_GDS TTM_PL_PRIV0
#define AMDGPU_PL_GWS TTM_PL_PRIV1
#define AMDGPU_PL_OA TTM_PL_PRIV2
#define AMDGPU_PL_FLAG_GDS TTM_PL_FLAG_PRIV0
#define AMDGPU_PL_FLAG_GWS TTM_PL_FLAG_PRIV1
#define AMDGPU_PL_FLAG_OA TTM_PL_FLAG_PRIV2
#define AMDGPU_TTM_LRU_SIZE 20
struct amdgpu_mman_lru {
struct list_head *lru[TTM_NUM_MEM_TYPES];
struct list_head *swap_lru;
};
struct amdgpu_mman {
struct ttm_bo_global_ref bo_global_ref;
struct drm_global_reference mem_global_ref;
struct ttm_bo_device bdev;
bool mem_global_referenced;
bool initialized;
#if defined(CONFIG_DEBUG_FS)
struct dentry *vram;
struct dentry *gtt;
#endif
/* buffer handling */
const struct amdgpu_buffer_funcs *buffer_funcs;
struct amdgpu_ring *buffer_funcs_ring;
/* Scheduler entity for buffer moves */
struct amd_sched_entity entity;
/* custom LRU management */
struct amdgpu_mman_lru log2_size[AMDGPU_TTM_LRU_SIZE];
/* guard for log2_size array, don't add anything in between */
struct amdgpu_mman_lru guard;
};
int amdgpu_copy_buffer(struct amdgpu_ring *ring,
uint64_t src_offset,
uint64_t dst_offset,
uint32_t byte_count,
struct reservation_object *resv,
struct fence **fence, bool direct_submit);
int amdgpu_fill_buffer(struct amdgpu_bo *bo,
uint32_t src_data,
struct reservation_object *resv,
struct fence **fence);
int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma);
#endif
...@@ -201,39 +201,14 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev) ...@@ -201,39 +201,14 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
bo_size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8) bo_size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8)
+ AMDGPU_UVD_STACK_SIZE + AMDGPU_UVD_HEAP_SIZE + AMDGPU_UVD_STACK_SIZE + AMDGPU_UVD_HEAP_SIZE
+ AMDGPU_UVD_SESSION_SIZE * adev->uvd.max_handles; + AMDGPU_UVD_SESSION_SIZE * adev->uvd.max_handles;
r = amdgpu_bo_create(adev, bo_size, PAGE_SIZE, true, r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE,
AMDGPU_GEM_DOMAIN_VRAM, AMDGPU_GEM_DOMAIN_VRAM, &adev->uvd.vcpu_bo,
AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, &adev->uvd.gpu_addr, &adev->uvd.cpu_addr);
NULL, NULL, &adev->uvd.vcpu_bo);
if (r) { if (r) {
dev_err(adev->dev, "(%d) failed to allocate UVD bo\n", r); dev_err(adev->dev, "(%d) failed to allocate UVD bo\n", r);
return r; return r;
} }
r = amdgpu_bo_reserve(adev->uvd.vcpu_bo, false);
if (r) {
amdgpu_bo_unref(&adev->uvd.vcpu_bo);
dev_err(adev->dev, "(%d) failed to reserve UVD bo\n", r);
return r;
}
r = amdgpu_bo_pin(adev->uvd.vcpu_bo, AMDGPU_GEM_DOMAIN_VRAM,
&adev->uvd.gpu_addr);
if (r) {
amdgpu_bo_unreserve(adev->uvd.vcpu_bo);
amdgpu_bo_unref(&adev->uvd.vcpu_bo);
dev_err(adev->dev, "(%d) UVD bo pin failed\n", r);
return r;
}
r = amdgpu_bo_kmap(adev->uvd.vcpu_bo, &adev->uvd.cpu_addr);
if (r) {
dev_err(adev->dev, "(%d) UVD map failed\n", r);
return r;
}
amdgpu_bo_unreserve(adev->uvd.vcpu_bo);
ring = &adev->uvd.ring; ring = &adev->uvd.ring;
rq = &ring->sched.sched_rq[AMD_SCHED_PRIORITY_NORMAL]; rq = &ring->sched.sched_rq[AMD_SCHED_PRIORITY_NORMAL];
r = amd_sched_entity_init(&ring->sched, &adev->uvd.entity, r = amd_sched_entity_init(&ring->sched, &adev->uvd.entity,
...@@ -323,7 +298,7 @@ int amdgpu_uvd_suspend(struct amdgpu_device *adev) ...@@ -323,7 +298,7 @@ int amdgpu_uvd_suspend(struct amdgpu_device *adev)
if (!adev->uvd.saved_bo) if (!adev->uvd.saved_bo)
return -ENOMEM; return -ENOMEM;
memcpy(adev->uvd.saved_bo, ptr, size); memcpy_fromio(adev->uvd.saved_bo, ptr, size);
return 0; return 0;
} }
...@@ -340,7 +315,7 @@ int amdgpu_uvd_resume(struct amdgpu_device *adev) ...@@ -340,7 +315,7 @@ int amdgpu_uvd_resume(struct amdgpu_device *adev)
ptr = adev->uvd.cpu_addr; ptr = adev->uvd.cpu_addr;
if (adev->uvd.saved_bo != NULL) { if (adev->uvd.saved_bo != NULL) {
memcpy(ptr, adev->uvd.saved_bo, size); memcpy_toio(ptr, adev->uvd.saved_bo, size);
kfree(adev->uvd.saved_bo); kfree(adev->uvd.saved_bo);
adev->uvd.saved_bo = NULL; adev->uvd.saved_bo = NULL;
} else { } else {
...@@ -349,11 +324,11 @@ int amdgpu_uvd_resume(struct amdgpu_device *adev) ...@@ -349,11 +324,11 @@ int amdgpu_uvd_resume(struct amdgpu_device *adev)
hdr = (const struct common_firmware_header *)adev->uvd.fw->data; hdr = (const struct common_firmware_header *)adev->uvd.fw->data;
offset = le32_to_cpu(hdr->ucode_array_offset_bytes); offset = le32_to_cpu(hdr->ucode_array_offset_bytes);
memcpy(adev->uvd.cpu_addr, (adev->uvd.fw->data) + offset, memcpy_toio(adev->uvd.cpu_addr, adev->uvd.fw->data + offset,
(adev->uvd.fw->size) - offset); le32_to_cpu(hdr->ucode_size_bytes));
size -= le32_to_cpu(hdr->ucode_size_bytes); size -= le32_to_cpu(hdr->ucode_size_bytes);
ptr += le32_to_cpu(hdr->ucode_size_bytes); ptr += le32_to_cpu(hdr->ucode_size_bytes);
memset(ptr, 0, size); memset_io(ptr, 0, size);
} }
return 0; return 0;
...@@ -843,6 +818,7 @@ static int amdgpu_uvd_cs_reg(struct amdgpu_uvd_cs_ctx *ctx, ...@@ -843,6 +818,7 @@ static int amdgpu_uvd_cs_reg(struct amdgpu_uvd_cs_ctx *ctx,
return r; return r;
break; break;
case mmUVD_ENGINE_CNTL: case mmUVD_ENGINE_CNTL:
case mmUVD_NO_OP:
break; break;
default: default:
DRM_ERROR("Invalid reg 0x%X!\n", reg); DRM_ERROR("Invalid reg 0x%X!\n", reg);
...@@ -981,8 +957,10 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo, ...@@ -981,8 +957,10 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo,
ib->ptr[3] = addr >> 32; ib->ptr[3] = addr >> 32;
ib->ptr[4] = PACKET0(mmUVD_GPCOM_VCPU_CMD, 0); ib->ptr[4] = PACKET0(mmUVD_GPCOM_VCPU_CMD, 0);
ib->ptr[5] = 0; ib->ptr[5] = 0;
for (i = 6; i < 16; ++i) for (i = 6; i < 16; i += 2) {
ib->ptr[i] = PACKET2(0); ib->ptr[i] = PACKET0(mmUVD_NO_OP, 0);
ib->ptr[i+1] = 0;
}
ib->length_dw = 16; ib->length_dw = 16;
if (direct) { if (direct) {
...@@ -1114,15 +1092,9 @@ static void amdgpu_uvd_idle_work_handler(struct work_struct *work) ...@@ -1114,15 +1092,9 @@ static void amdgpu_uvd_idle_work_handler(struct work_struct *work)
{ {
struct amdgpu_device *adev = struct amdgpu_device *adev =
container_of(work, struct amdgpu_device, uvd.idle_work.work); container_of(work, struct amdgpu_device, uvd.idle_work.work);
unsigned i, fences, handles = 0; unsigned fences = amdgpu_fence_count_emitted(&adev->uvd.ring);
fences = amdgpu_fence_count_emitted(&adev->uvd.ring);
for (i = 0; i < adev->uvd.max_handles; ++i)
if (atomic_read(&adev->uvd.handles[i]))
++handles;
if (fences == 0 && handles == 0) { if (fences == 0) {
if (adev->pm.dpm_enabled) { if (adev->pm.dpm_enabled) {
amdgpu_dpm_enable_uvd(adev, false); amdgpu_dpm_enable_uvd(adev, false);
} else { } else {
......
...@@ -282,8 +282,8 @@ int amdgpu_vce_resume(struct amdgpu_device *adev) ...@@ -282,8 +282,8 @@ int amdgpu_vce_resume(struct amdgpu_device *adev)
hdr = (const struct common_firmware_header *)adev->vce.fw->data; hdr = (const struct common_firmware_header *)adev->vce.fw->data;
offset = le32_to_cpu(hdr->ucode_array_offset_bytes); offset = le32_to_cpu(hdr->ucode_array_offset_bytes);
memcpy(cpu_addr, (adev->vce.fw->data) + offset, memcpy_toio(cpu_addr, adev->vce.fw->data + offset,
(adev->vce.fw->size) - offset); adev->vce.fw->size - offset);
amdgpu_bo_kunmap(adev->vce.vcpu_bo); amdgpu_bo_kunmap(adev->vce.vcpu_bo);
......
...@@ -88,7 +88,6 @@ static int amdgpu_atombios_dp_process_aux_ch(struct amdgpu_i2c_chan *chan, ...@@ -88,7 +88,6 @@ static int amdgpu_atombios_dp_process_aux_ch(struct amdgpu_i2c_chan *chan,
/* timeout */ /* timeout */
if (args.v2.ucReplyStatus == 1) { if (args.v2.ucReplyStatus == 1) {
DRM_DEBUG_KMS("dp_aux_ch timeout\n");
r = -ETIMEDOUT; r = -ETIMEDOUT;
goto done; goto done;
} }
...@@ -339,11 +338,10 @@ int amdgpu_atombios_dp_get_dpcd(struct amdgpu_connector *amdgpu_connector) ...@@ -339,11 +338,10 @@ int amdgpu_atombios_dp_get_dpcd(struct amdgpu_connector *amdgpu_connector)
{ {
struct amdgpu_connector_atom_dig *dig_connector = amdgpu_connector->con_priv; struct amdgpu_connector_atom_dig *dig_connector = amdgpu_connector->con_priv;
u8 msg[DP_DPCD_SIZE]; u8 msg[DP_DPCD_SIZE];
int ret, i; int ret;
for (i = 0; i < 7; i++) { ret = drm_dp_dpcd_read(&amdgpu_connector->ddc_bus->aux, DP_DPCD_REV,
ret = drm_dp_dpcd_read(&amdgpu_connector->ddc_bus->aux, DP_DPCD_REV, msg, msg, DP_DPCD_SIZE);
DP_DPCD_SIZE);
if (ret == DP_DPCD_SIZE) { if (ret == DP_DPCD_SIZE) {
memcpy(dig_connector->dpcd, msg, DP_DPCD_SIZE); memcpy(dig_connector->dpcd, msg, DP_DPCD_SIZE);
...@@ -354,7 +352,7 @@ int amdgpu_atombios_dp_get_dpcd(struct amdgpu_connector *amdgpu_connector) ...@@ -354,7 +352,7 @@ int amdgpu_atombios_dp_get_dpcd(struct amdgpu_connector *amdgpu_connector)
return 0; return 0;
} }
}
dig_connector->dpcd[0] = 0; dig_connector->dpcd[0] = 0;
return -EINVAL; return -EINVAL;
} }
......
...@@ -5874,7 +5874,10 @@ static int ci_dpm_init(struct amdgpu_device *adev) ...@@ -5874,7 +5874,10 @@ static int ci_dpm_init(struct amdgpu_device *adev)
pi->pcie_dpm_key_disabled = 0; pi->pcie_dpm_key_disabled = 0;
pi->thermal_sclk_dpm_enabled = 0; pi->thermal_sclk_dpm_enabled = 0;
if (amdgpu_sclk_deep_sleep_en)
pi->caps_sclk_ds = true; pi->caps_sclk_ds = true;
else
pi->caps_sclk_ds = false;
pi->mclk_strobe_mode_threshold = 40000; pi->mclk_strobe_mode_threshold = 40000;
pi->mclk_stutter_mode_threshold = 40000; pi->mclk_stutter_mode_threshold = 40000;
......
...@@ -67,6 +67,7 @@ ...@@ -67,6 +67,7 @@
#include "amdgpu_amdkfd.h" #include "amdgpu_amdkfd.h"
#include "amdgpu_powerplay.h" #include "amdgpu_powerplay.h"
#include "dce_virtual.h"
/* /*
* Indirect registers accessor * Indirect registers accessor
...@@ -1708,6 +1709,74 @@ static const struct amdgpu_ip_block_version bonaire_ip_blocks[] = ...@@ -1708,6 +1709,74 @@ static const struct amdgpu_ip_block_version bonaire_ip_blocks[] =
}, },
}; };
static const struct amdgpu_ip_block_version bonaire_ip_blocks_vd[] =
{
/* ORDER MATTERS! */
{
.type = AMD_IP_BLOCK_TYPE_COMMON,
.major = 1,
.minor = 0,
.rev = 0,
.funcs = &cik_common_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_GMC,
.major = 7,
.minor = 0,
.rev = 0,
.funcs = &gmc_v7_0_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_IH,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &cik_ih_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_SMC,
.major = 7,
.minor = 0,
.rev = 0,
.funcs = &amdgpu_pp_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_DCE,
.major = 8,
.minor = 2,
.rev = 0,
.funcs = &dce_virtual_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_GFX,
.major = 7,
.minor = 2,
.rev = 0,
.funcs = &gfx_v7_0_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_SDMA,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &cik_sdma_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_UVD,
.major = 4,
.minor = 2,
.rev = 0,
.funcs = &uvd_v4_2_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_VCE,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &vce_v2_0_ip_funcs,
},
};
static const struct amdgpu_ip_block_version hawaii_ip_blocks[] = static const struct amdgpu_ip_block_version hawaii_ip_blocks[] =
{ {
/* ORDER MATTERS! */ /* ORDER MATTERS! */
...@@ -1776,6 +1845,74 @@ static const struct amdgpu_ip_block_version hawaii_ip_blocks[] = ...@@ -1776,6 +1845,74 @@ static const struct amdgpu_ip_block_version hawaii_ip_blocks[] =
}, },
}; };
static const struct amdgpu_ip_block_version hawaii_ip_blocks_vd[] =
{
/* ORDER MATTERS! */
{
.type = AMD_IP_BLOCK_TYPE_COMMON,
.major = 1,
.minor = 0,
.rev = 0,
.funcs = &cik_common_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_GMC,
.major = 7,
.minor = 0,
.rev = 0,
.funcs = &gmc_v7_0_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_IH,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &cik_ih_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_SMC,
.major = 7,
.minor = 0,
.rev = 0,
.funcs = &amdgpu_pp_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_DCE,
.major = 8,
.minor = 5,
.rev = 0,
.funcs = &dce_virtual_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_GFX,
.major = 7,
.minor = 3,
.rev = 0,
.funcs = &gfx_v7_0_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_SDMA,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &cik_sdma_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_UVD,
.major = 4,
.minor = 2,
.rev = 0,
.funcs = &uvd_v4_2_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_VCE,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &vce_v2_0_ip_funcs,
},
};
static const struct amdgpu_ip_block_version kabini_ip_blocks[] = static const struct amdgpu_ip_block_version kabini_ip_blocks[] =
{ {
/* ORDER MATTERS! */ /* ORDER MATTERS! */
...@@ -1844,6 +1981,74 @@ static const struct amdgpu_ip_block_version kabini_ip_blocks[] = ...@@ -1844,6 +1981,74 @@ static const struct amdgpu_ip_block_version kabini_ip_blocks[] =
}, },
}; };
static const struct amdgpu_ip_block_version kabini_ip_blocks_vd[] =
{
/* ORDER MATTERS! */
{
.type = AMD_IP_BLOCK_TYPE_COMMON,
.major = 1,
.minor = 0,
.rev = 0,
.funcs = &cik_common_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_GMC,
.major = 7,
.minor = 0,
.rev = 0,
.funcs = &gmc_v7_0_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_IH,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &cik_ih_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_SMC,
.major = 7,
.minor = 0,
.rev = 0,
.funcs = &amdgpu_pp_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_DCE,
.major = 8,
.minor = 3,
.rev = 0,
.funcs = &dce_virtual_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_GFX,
.major = 7,
.minor = 2,
.rev = 0,
.funcs = &gfx_v7_0_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_SDMA,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &cik_sdma_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_UVD,
.major = 4,
.minor = 2,
.rev = 0,
.funcs = &uvd_v4_2_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_VCE,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &vce_v2_0_ip_funcs,
},
};
static const struct amdgpu_ip_block_version mullins_ip_blocks[] = static const struct amdgpu_ip_block_version mullins_ip_blocks[] =
{ {
/* ORDER MATTERS! */ /* ORDER MATTERS! */
...@@ -1912,6 +2117,74 @@ static const struct amdgpu_ip_block_version mullins_ip_blocks[] = ...@@ -1912,6 +2117,74 @@ static const struct amdgpu_ip_block_version mullins_ip_blocks[] =
}, },
}; };
static const struct amdgpu_ip_block_version mullins_ip_blocks_vd[] =
{
/* ORDER MATTERS! */
{
.type = AMD_IP_BLOCK_TYPE_COMMON,
.major = 1,
.minor = 0,
.rev = 0,
.funcs = &cik_common_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_GMC,
.major = 7,
.minor = 0,
.rev = 0,
.funcs = &gmc_v7_0_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_IH,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &cik_ih_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_SMC,
.major = 7,
.minor = 0,
.rev = 0,
.funcs = &amdgpu_pp_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_DCE,
.major = 8,
.minor = 3,
.rev = 0,
.funcs = &dce_virtual_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_GFX,
.major = 7,
.minor = 2,
.rev = 0,
.funcs = &gfx_v7_0_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_SDMA,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &cik_sdma_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_UVD,
.major = 4,
.minor = 2,
.rev = 0,
.funcs = &uvd_v4_2_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_VCE,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &vce_v2_0_ip_funcs,
},
};
static const struct amdgpu_ip_block_version kaveri_ip_blocks[] = static const struct amdgpu_ip_block_version kaveri_ip_blocks[] =
{ {
/* ORDER MATTERS! */ /* ORDER MATTERS! */
...@@ -1980,8 +2253,103 @@ static const struct amdgpu_ip_block_version kaveri_ip_blocks[] = ...@@ -1980,8 +2253,103 @@ static const struct amdgpu_ip_block_version kaveri_ip_blocks[] =
}, },
}; };
static const struct amdgpu_ip_block_version kaveri_ip_blocks_vd[] =
{
/* ORDER MATTERS! */
{
.type = AMD_IP_BLOCK_TYPE_COMMON,
.major = 1,
.minor = 0,
.rev = 0,
.funcs = &cik_common_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_GMC,
.major = 7,
.minor = 0,
.rev = 0,
.funcs = &gmc_v7_0_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_IH,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &cik_ih_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_SMC,
.major = 7,
.minor = 0,
.rev = 0,
.funcs = &amdgpu_pp_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_DCE,
.major = 8,
.minor = 1,
.rev = 0,
.funcs = &dce_virtual_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_GFX,
.major = 7,
.minor = 1,
.rev = 0,
.funcs = &gfx_v7_0_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_SDMA,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &cik_sdma_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_UVD,
.major = 4,
.minor = 2,
.rev = 0,
.funcs = &uvd_v4_2_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_VCE,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &vce_v2_0_ip_funcs,
},
};
int cik_set_ip_blocks(struct amdgpu_device *adev) int cik_set_ip_blocks(struct amdgpu_device *adev)
{ {
if (adev->enable_virtual_display) {
switch (adev->asic_type) {
case CHIP_BONAIRE:
adev->ip_blocks = bonaire_ip_blocks_vd;
adev->num_ip_blocks = ARRAY_SIZE(bonaire_ip_blocks_vd);
break;
case CHIP_HAWAII:
adev->ip_blocks = hawaii_ip_blocks_vd;
adev->num_ip_blocks = ARRAY_SIZE(hawaii_ip_blocks_vd);
break;
case CHIP_KAVERI:
adev->ip_blocks = kaveri_ip_blocks_vd;
adev->num_ip_blocks = ARRAY_SIZE(kaveri_ip_blocks_vd);
break;
case CHIP_KABINI:
adev->ip_blocks = kabini_ip_blocks_vd;
adev->num_ip_blocks = ARRAY_SIZE(kabini_ip_blocks_vd);
break;
case CHIP_MULLINS:
adev->ip_blocks = mullins_ip_blocks_vd;
adev->num_ip_blocks = ARRAY_SIZE(mullins_ip_blocks_vd);
break;
default:
/* FIXME: not supported yet */
return -EINVAL;
}
} else {
switch (adev->asic_type) { switch (adev->asic_type) {
case CHIP_BONAIRE: case CHIP_BONAIRE:
adev->ip_blocks = bonaire_ip_blocks; adev->ip_blocks = bonaire_ip_blocks;
...@@ -2007,6 +2375,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev) ...@@ -2007,6 +2375,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
/* FIXME: not supported yet */ /* FIXME: not supported yet */
return -EINVAL; return -EINVAL;
} }
}
return 0; return 0;
} }
......
...@@ -694,10 +694,7 @@ static void cik_sdma_vm_copy_pte(struct amdgpu_ib *ib, ...@@ -694,10 +694,7 @@ static void cik_sdma_vm_copy_pte(struct amdgpu_ib *ib,
uint64_t pe, uint64_t src, uint64_t pe, uint64_t src,
unsigned count) unsigned count)
{ {
while (count) {
unsigned bytes = count * 8; unsigned bytes = count * 8;
if (bytes > 0x1FFFF8)
bytes = 0x1FFFF8;
ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_COPY, ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_COPY,
SDMA_WRITE_SUB_OPCODE_LINEAR, 0); SDMA_WRITE_SUB_OPCODE_LINEAR, 0);
...@@ -707,11 +704,6 @@ static void cik_sdma_vm_copy_pte(struct amdgpu_ib *ib, ...@@ -707,11 +704,6 @@ static void cik_sdma_vm_copy_pte(struct amdgpu_ib *ib,
ib->ptr[ib->length_dw++] = upper_32_bits(src); ib->ptr[ib->length_dw++] = upper_32_bits(src);
ib->ptr[ib->length_dw++] = lower_32_bits(pe); ib->ptr[ib->length_dw++] = lower_32_bits(pe);
ib->ptr[ib->length_dw++] = upper_32_bits(pe); ib->ptr[ib->length_dw++] = upper_32_bits(pe);
pe += bytes;
src += bytes;
count -= bytes / 8;
}
} }
/** /**
...@@ -719,39 +711,27 @@ static void cik_sdma_vm_copy_pte(struct amdgpu_ib *ib, ...@@ -719,39 +711,27 @@ static void cik_sdma_vm_copy_pte(struct amdgpu_ib *ib,
* *
* @ib: indirect buffer to fill with commands * @ib: indirect buffer to fill with commands
* @pe: addr of the page entry * @pe: addr of the page entry
* @addr: dst addr to write into pe * @value: dst addr to write into pe
* @count: number of page entries to update * @count: number of page entries to update
* @incr: increase next addr by incr bytes * @incr: increase next addr by incr bytes
* @flags: access flags
* *
* Update PTEs by writing them manually using sDMA (CIK). * Update PTEs by writing them manually using sDMA (CIK).
*/ */
static void cik_sdma_vm_write_pte(struct amdgpu_ib *ib, static void cik_sdma_vm_write_pte(struct amdgpu_ib *ib, uint64_t pe,
const dma_addr_t *pages_addr, uint64_t pe, uint64_t value, unsigned count,
uint64_t addr, unsigned count, uint32_t incr)
uint32_t incr, uint32_t flags)
{ {
uint64_t value; unsigned ndw = count * 2;
unsigned ndw;
while (count) {
ndw = count * 2;
if (ndw > 0xFFFFE)
ndw = 0xFFFFE;
/* for non-physically contiguous pages (system) */
ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_WRITE, ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_WRITE,
SDMA_WRITE_SUB_OPCODE_LINEAR, 0); SDMA_WRITE_SUB_OPCODE_LINEAR, 0);
ib->ptr[ib->length_dw++] = pe; ib->ptr[ib->length_dw++] = lower_32_bits(pe);
ib->ptr[ib->length_dw++] = upper_32_bits(pe); ib->ptr[ib->length_dw++] = upper_32_bits(pe);
ib->ptr[ib->length_dw++] = ndw; ib->ptr[ib->length_dw++] = ndw;
for (; ndw > 0; ndw -= 2, --count, pe += 8) { for (; ndw > 0; ndw -= 2) {
value = amdgpu_vm_map_gart(pages_addr, addr); ib->ptr[ib->length_dw++] = lower_32_bits(value);
addr += incr;
value |= flags;
ib->ptr[ib->length_dw++] = value;
ib->ptr[ib->length_dw++] = upper_32_bits(value); ib->ptr[ib->length_dw++] = upper_32_bits(value);
} value += incr;
} }
} }
...@@ -767,40 +747,21 @@ static void cik_sdma_vm_write_pte(struct amdgpu_ib *ib, ...@@ -767,40 +747,21 @@ static void cik_sdma_vm_write_pte(struct amdgpu_ib *ib,
* *
* Update the page tables using sDMA (CIK). * Update the page tables using sDMA (CIK).
*/ */
static void cik_sdma_vm_set_pte_pde(struct amdgpu_ib *ib, static void cik_sdma_vm_set_pte_pde(struct amdgpu_ib *ib, uint64_t pe,
uint64_t pe,
uint64_t addr, unsigned count, uint64_t addr, unsigned count,
uint32_t incr, uint32_t flags) uint32_t incr, uint32_t flags)
{ {
uint64_t value;
unsigned ndw;
while (count) {
ndw = count;
if (ndw > 0x7FFFF)
ndw = 0x7FFFF;
if (flags & AMDGPU_PTE_VALID)
value = addr;
else
value = 0;
/* for physically contiguous pages (vram) */ /* for physically contiguous pages (vram) */
ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_GENERATE_PTE_PDE, 0, 0); ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_GENERATE_PTE_PDE, 0, 0);
ib->ptr[ib->length_dw++] = pe; /* dst addr */ ib->ptr[ib->length_dw++] = lower_32_bits(pe); /* dst addr */
ib->ptr[ib->length_dw++] = upper_32_bits(pe); ib->ptr[ib->length_dw++] = upper_32_bits(pe);
ib->ptr[ib->length_dw++] = flags; /* mask */ ib->ptr[ib->length_dw++] = flags; /* mask */
ib->ptr[ib->length_dw++] = 0; ib->ptr[ib->length_dw++] = 0;
ib->ptr[ib->length_dw++] = value; /* value */ ib->ptr[ib->length_dw++] = lower_32_bits(addr); /* value */
ib->ptr[ib->length_dw++] = upper_32_bits(value); ib->ptr[ib->length_dw++] = upper_32_bits(addr);
ib->ptr[ib->length_dw++] = incr; /* increment size */ ib->ptr[ib->length_dw++] = incr; /* increment size */
ib->ptr[ib->length_dw++] = 0; ib->ptr[ib->length_dw++] = 0;
ib->ptr[ib->length_dw++] = ndw; /* number of entries */ ib->ptr[ib->length_dw++] = count; /* number of entries */
pe += ndw * 8;
addr += ndw * incr;
count -= ndw;
}
} }
/** /**
......
...@@ -435,7 +435,11 @@ static int cz_dpm_init(struct amdgpu_device *adev) ...@@ -435,7 +435,11 @@ static int cz_dpm_init(struct amdgpu_device *adev)
pi->caps_td_ramping = true; pi->caps_td_ramping = true;
pi->caps_tcp_ramping = true; pi->caps_tcp_ramping = true;
} }
if (amdgpu_sclk_deep_sleep_en)
pi->caps_sclk_ds = true; pi->caps_sclk_ds = true;
else
pi->caps_sclk_ds = false;
pi->voting_clients = 0x00c00033; pi->voting_clients = 0x00c00033;
pi->auto_thermal_throttling_enabled = true; pi->auto_thermal_throttling_enabled = true;
pi->bapm_enabled = false; pi->bapm_enabled = false;
...@@ -2108,29 +2112,58 @@ static void cz_dpm_powergate_uvd(struct amdgpu_device *adev, bool gate) ...@@ -2108,29 +2112,58 @@ static void cz_dpm_powergate_uvd(struct amdgpu_device *adev, bool gate)
/* disable clockgating so we can properly shut down the block */ /* disable clockgating so we can properly shut down the block */
ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD, ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
AMD_CG_STATE_UNGATE); AMD_CG_STATE_UNGATE);
if (ret) {
DRM_ERROR("UVD DPM Power Gating failed to set clockgating state\n");
return;
}
/* shutdown the UVD block */ /* shutdown the UVD block */
ret = amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD, ret = amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
AMD_PG_STATE_GATE); AMD_PG_STATE_GATE);
/* XXX: check for errors */
if (ret) {
DRM_ERROR("UVD DPM Power Gating failed to set powergating state\n");
return;
}
} }
cz_update_uvd_dpm(adev, gate); cz_update_uvd_dpm(adev, gate);
if (pi->caps_uvd_pg) if (pi->caps_uvd_pg) {
/* power off the UVD block */ /* power off the UVD block */
cz_send_msg_to_smc(adev, PPSMC_MSG_UVDPowerOFF); ret = cz_send_msg_to_smc(adev, PPSMC_MSG_UVDPowerOFF);
if (ret) {
DRM_ERROR("UVD DPM Power Gating failed to send SMU PowerOFF message\n");
return;
}
}
} else { } else {
if (pi->caps_uvd_pg) { if (pi->caps_uvd_pg) {
/* power on the UVD block */ /* power on the UVD block */
if (pi->uvd_dynamic_pg) if (pi->uvd_dynamic_pg)
cz_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_UVDPowerON, 1); ret = cz_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_UVDPowerON, 1);
else else
cz_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_UVDPowerON, 0); ret = cz_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_UVDPowerON, 0);
if (ret) {
DRM_ERROR("UVD DPM Power Gating Failed to send SMU PowerON message\n");
return;
}
/* re-init the UVD block */ /* re-init the UVD block */
ret = amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD, ret = amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
AMD_PG_STATE_UNGATE); AMD_PG_STATE_UNGATE);
if (ret) {
DRM_ERROR("UVD DPM Power Gating Failed to set powergating state\n");
return;
}
/* enable clockgating. hw will dynamically gate/ungate clocks on the fly */ /* enable clockgating. hw will dynamically gate/ungate clocks on the fly */
ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD, ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
AMD_CG_STATE_GATE); AMD_CG_STATE_GATE);
/* XXX: check for errors */ if (ret) {
DRM_ERROR("UVD DPM Power Gating Failed to set clockgating state\n");
return;
}
} }
cz_update_uvd_dpm(adev, gate); cz_update_uvd_dpm(adev, gate);
} }
......
...@@ -646,8 +646,8 @@ static void dce_v10_0_resume_mc_access(struct amdgpu_device *adev, ...@@ -646,8 +646,8 @@ static void dce_v10_0_resume_mc_access(struct amdgpu_device *adev,
if (save->crtc_enabled[i]) { if (save->crtc_enabled[i]) {
tmp = RREG32(mmMASTER_UPDATE_MODE + crtc_offsets[i]); tmp = RREG32(mmMASTER_UPDATE_MODE + crtc_offsets[i]);
if (REG_GET_FIELD(tmp, MASTER_UPDATE_MODE, MASTER_UPDATE_MODE) != 3) { if (REG_GET_FIELD(tmp, MASTER_UPDATE_MODE, MASTER_UPDATE_MODE) != 0) {
tmp = REG_SET_FIELD(tmp, MASTER_UPDATE_MODE, MASTER_UPDATE_MODE, 3); tmp = REG_SET_FIELD(tmp, MASTER_UPDATE_MODE, MASTER_UPDATE_MODE, 0);
WREG32(mmMASTER_UPDATE_MODE + crtc_offsets[i], tmp); WREG32(mmMASTER_UPDATE_MODE + crtc_offsets[i], tmp);
} }
tmp = RREG32(mmGRPH_UPDATE + crtc_offsets[i]); tmp = RREG32(mmGRPH_UPDATE + crtc_offsets[i]);
...@@ -712,6 +712,45 @@ static void dce_v10_0_set_vga_render_state(struct amdgpu_device *adev, ...@@ -712,6 +712,45 @@ static void dce_v10_0_set_vga_render_state(struct amdgpu_device *adev,
WREG32(mmVGA_RENDER_CONTROL, tmp); WREG32(mmVGA_RENDER_CONTROL, tmp);
} }
static int dce_v10_0_get_num_crtc(struct amdgpu_device *adev)
{
int num_crtc = 0;
switch (adev->asic_type) {
case CHIP_FIJI:
case CHIP_TONGA:
num_crtc = 6;
break;
default:
num_crtc = 0;
}
return num_crtc;
}
void dce_v10_0_disable_dce(struct amdgpu_device *adev)
{
/*Disable VGA render and enabled crtc, if has DCE engine*/
if (amdgpu_atombios_has_dce_engine_info(adev)) {
u32 tmp;
int crtc_enabled, i;
dce_v10_0_set_vga_render_state(adev, false);
/*Disable crtc*/
for (i = 0; i < dce_v10_0_get_num_crtc(adev); i++) {
crtc_enabled = REG_GET_FIELD(RREG32(mmCRTC_CONTROL + crtc_offsets[i]),
CRTC_CONTROL, CRTC_MASTER_EN);
if (crtc_enabled) {
WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 1);
tmp = RREG32(mmCRTC_CONTROL + crtc_offsets[i]);
tmp = REG_SET_FIELD(tmp, CRTC_CONTROL, CRTC_MASTER_EN, 0);
WREG32(mmCRTC_CONTROL + crtc_offsets[i], tmp);
WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 0);
}
}
}
}
static void dce_v10_0_program_fmt(struct drm_encoder *encoder) static void dce_v10_0_program_fmt(struct drm_encoder *encoder)
{ {
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
...@@ -2277,8 +2316,8 @@ static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc, ...@@ -2277,8 +2316,8 @@ static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc,
WREG32(mmVIEWPORT_SIZE + amdgpu_crtc->crtc_offset, WREG32(mmVIEWPORT_SIZE + amdgpu_crtc->crtc_offset,
(viewport_w << 16) | viewport_h); (viewport_w << 16) | viewport_h);
/* set pageflip to happen only at start of vblank interval (front porch) */ /* set pageflip to happen anywhere in vblank interval */
WREG32(mmMASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 3); WREG32(mmMASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 0);
if (!atomic && fb && fb != crtc->primary->fb) { if (!atomic && fb && fb != crtc->primary->fb) {
amdgpu_fb = to_amdgpu_framebuffer(fb); amdgpu_fb = to_amdgpu_framebuffer(fb);
...@@ -2700,7 +2739,7 @@ static const struct drm_crtc_funcs dce_v10_0_crtc_funcs = { ...@@ -2700,7 +2739,7 @@ static const struct drm_crtc_funcs dce_v10_0_crtc_funcs = {
.gamma_set = dce_v10_0_crtc_gamma_set, .gamma_set = dce_v10_0_crtc_gamma_set,
.set_config = amdgpu_crtc_set_config, .set_config = amdgpu_crtc_set_config,
.destroy = dce_v10_0_crtc_destroy, .destroy = dce_v10_0_crtc_destroy,
.page_flip = amdgpu_crtc_page_flip, .page_flip_target = amdgpu_crtc_page_flip_target,
}; };
static void dce_v10_0_crtc_dpms(struct drm_crtc *crtc, int mode) static void dce_v10_0_crtc_dpms(struct drm_crtc *crtc, int mode)
...@@ -2964,10 +3003,11 @@ static int dce_v10_0_early_init(void *handle) ...@@ -2964,10 +3003,11 @@ static int dce_v10_0_early_init(void *handle)
dce_v10_0_set_display_funcs(adev); dce_v10_0_set_display_funcs(adev);
dce_v10_0_set_irq_funcs(adev); dce_v10_0_set_irq_funcs(adev);
adev->mode_info.num_crtc = dce_v10_0_get_num_crtc(adev);
switch (adev->asic_type) { switch (adev->asic_type) {
case CHIP_FIJI: case CHIP_FIJI:
case CHIP_TONGA: case CHIP_TONGA:
adev->mode_info.num_crtc = 6; /* XXX 7??? */
adev->mode_info.num_hpd = 6; adev->mode_info.num_hpd = 6;
adev->mode_info.num_dig = 7; adev->mode_info.num_dig = 7;
break; break;
...@@ -3143,11 +3183,26 @@ static int dce_v10_0_wait_for_idle(void *handle) ...@@ -3143,11 +3183,26 @@ static int dce_v10_0_wait_for_idle(void *handle)
return 0; return 0;
} }
static int dce_v10_0_check_soft_reset(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
if (dce_v10_0_is_display_hung(adev))
adev->ip_block_status[AMD_IP_BLOCK_TYPE_DCE].hang = true;
else
adev->ip_block_status[AMD_IP_BLOCK_TYPE_DCE].hang = false;
return 0;
}
static int dce_v10_0_soft_reset(void *handle) static int dce_v10_0_soft_reset(void *handle)
{ {
u32 srbm_soft_reset = 0, tmp; u32 srbm_soft_reset = 0, tmp;
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_DCE].hang)
return 0;
if (dce_v10_0_is_display_hung(adev)) if (dce_v10_0_is_display_hung(adev))
srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_DC_MASK; srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_DC_MASK;
...@@ -3514,6 +3569,7 @@ const struct amd_ip_funcs dce_v10_0_ip_funcs = { ...@@ -3514,6 +3569,7 @@ const struct amd_ip_funcs dce_v10_0_ip_funcs = {
.resume = dce_v10_0_resume, .resume = dce_v10_0_resume,
.is_idle = dce_v10_0_is_idle, .is_idle = dce_v10_0_is_idle,
.wait_for_idle = dce_v10_0_wait_for_idle, .wait_for_idle = dce_v10_0_wait_for_idle,
.check_soft_reset = dce_v10_0_check_soft_reset,
.soft_reset = dce_v10_0_soft_reset, .soft_reset = dce_v10_0_soft_reset,
.set_clockgating_state = dce_v10_0_set_clockgating_state, .set_clockgating_state = dce_v10_0_set_clockgating_state,
.set_powergating_state = dce_v10_0_set_powergating_state, .set_powergating_state = dce_v10_0_set_powergating_state,
......
...@@ -26,4 +26,6 @@ ...@@ -26,4 +26,6 @@
extern const struct amd_ip_funcs dce_v10_0_ip_funcs; extern const struct amd_ip_funcs dce_v10_0_ip_funcs;
void dce_v10_0_disable_dce(struct amdgpu_device *adev);
#endif #endif
...@@ -673,6 +673,53 @@ static void dce_v11_0_set_vga_render_state(struct amdgpu_device *adev, ...@@ -673,6 +673,53 @@ static void dce_v11_0_set_vga_render_state(struct amdgpu_device *adev,
WREG32(mmVGA_RENDER_CONTROL, tmp); WREG32(mmVGA_RENDER_CONTROL, tmp);
} }
static int dce_v11_0_get_num_crtc (struct amdgpu_device *adev)
{
int num_crtc = 0;
switch (adev->asic_type) {
case CHIP_CARRIZO:
num_crtc = 3;
break;
case CHIP_STONEY:
num_crtc = 2;
break;
case CHIP_POLARIS10:
num_crtc = 6;
break;
case CHIP_POLARIS11:
num_crtc = 5;
break;
default:
num_crtc = 0;
}
return num_crtc;
}
void dce_v11_0_disable_dce(struct amdgpu_device *adev)
{
/*Disable VGA render and enabled crtc, if has DCE engine*/
if (amdgpu_atombios_has_dce_engine_info(adev)) {
u32 tmp;
int crtc_enabled, i;
dce_v11_0_set_vga_render_state(adev, false);
/*Disable crtc*/
for (i = 0; i < dce_v11_0_get_num_crtc(adev); i++) {
crtc_enabled = REG_GET_FIELD(RREG32(mmCRTC_CONTROL + crtc_offsets[i]),
CRTC_CONTROL, CRTC_MASTER_EN);
if (crtc_enabled) {
WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 1);
tmp = RREG32(mmCRTC_CONTROL + crtc_offsets[i]);
tmp = REG_SET_FIELD(tmp, CRTC_CONTROL, CRTC_MASTER_EN, 0);
WREG32(mmCRTC_CONTROL + crtc_offsets[i], tmp);
WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 0);
}
}
}
}
static void dce_v11_0_program_fmt(struct drm_encoder *encoder) static void dce_v11_0_program_fmt(struct drm_encoder *encoder)
{ {
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
...@@ -2252,8 +2299,8 @@ static int dce_v11_0_crtc_do_set_base(struct drm_crtc *crtc, ...@@ -2252,8 +2299,8 @@ static int dce_v11_0_crtc_do_set_base(struct drm_crtc *crtc,
WREG32(mmVIEWPORT_SIZE + amdgpu_crtc->crtc_offset, WREG32(mmVIEWPORT_SIZE + amdgpu_crtc->crtc_offset,
(viewport_w << 16) | viewport_h); (viewport_w << 16) | viewport_h);
/* set pageflip to happen only at start of vblank interval (front porch) */ /* set pageflip to happen anywhere in vblank interval */
WREG32(mmCRTC_MASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 3); WREG32(mmCRTC_MASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 0);
if (!atomic && fb && fb != crtc->primary->fb) { if (!atomic && fb && fb != crtc->primary->fb) {
amdgpu_fb = to_amdgpu_framebuffer(fb); amdgpu_fb = to_amdgpu_framebuffer(fb);
...@@ -2710,7 +2757,7 @@ static const struct drm_crtc_funcs dce_v11_0_crtc_funcs = { ...@@ -2710,7 +2757,7 @@ static const struct drm_crtc_funcs dce_v11_0_crtc_funcs = {
.gamma_set = dce_v11_0_crtc_gamma_set, .gamma_set = dce_v11_0_crtc_gamma_set,
.set_config = amdgpu_crtc_set_config, .set_config = amdgpu_crtc_set_config,
.destroy = dce_v11_0_crtc_destroy, .destroy = dce_v11_0_crtc_destroy,
.page_flip = amdgpu_crtc_page_flip, .page_flip_target = amdgpu_crtc_page_flip_target,
}; };
static void dce_v11_0_crtc_dpms(struct drm_crtc *crtc, int mode) static void dce_v11_0_crtc_dpms(struct drm_crtc *crtc, int mode)
...@@ -3001,24 +3048,22 @@ static int dce_v11_0_early_init(void *handle) ...@@ -3001,24 +3048,22 @@ static int dce_v11_0_early_init(void *handle)
dce_v11_0_set_display_funcs(adev); dce_v11_0_set_display_funcs(adev);
dce_v11_0_set_irq_funcs(adev); dce_v11_0_set_irq_funcs(adev);
adev->mode_info.num_crtc = dce_v11_0_get_num_crtc(adev);
switch (adev->asic_type) { switch (adev->asic_type) {
case CHIP_CARRIZO: case CHIP_CARRIZO:
adev->mode_info.num_crtc = 3;
adev->mode_info.num_hpd = 6; adev->mode_info.num_hpd = 6;
adev->mode_info.num_dig = 9; adev->mode_info.num_dig = 9;
break; break;
case CHIP_STONEY: case CHIP_STONEY:
adev->mode_info.num_crtc = 2;
adev->mode_info.num_hpd = 6; adev->mode_info.num_hpd = 6;
adev->mode_info.num_dig = 9; adev->mode_info.num_dig = 9;
break; break;
case CHIP_POLARIS10: case CHIP_POLARIS10:
adev->mode_info.num_crtc = 6;
adev->mode_info.num_hpd = 6; adev->mode_info.num_hpd = 6;
adev->mode_info.num_dig = 6; adev->mode_info.num_dig = 6;
break; break;
case CHIP_POLARIS11: case CHIP_POLARIS11:
adev->mode_info.num_crtc = 5;
adev->mode_info.num_hpd = 5; adev->mode_info.num_hpd = 5;
adev->mode_info.num_dig = 5; adev->mode_info.num_dig = 5;
break; break;
......
...@@ -26,4 +26,6 @@ ...@@ -26,4 +26,6 @@
extern const struct amd_ip_funcs dce_v11_0_ip_funcs; extern const struct amd_ip_funcs dce_v11_0_ip_funcs;
void dce_v11_0_disable_dce(struct amdgpu_device *adev);
#endif #endif
...@@ -604,6 +604,52 @@ static void dce_v8_0_set_vga_render_state(struct amdgpu_device *adev, ...@@ -604,6 +604,52 @@ static void dce_v8_0_set_vga_render_state(struct amdgpu_device *adev,
WREG32(mmVGA_RENDER_CONTROL, tmp); WREG32(mmVGA_RENDER_CONTROL, tmp);
} }
static int dce_v8_0_get_num_crtc(struct amdgpu_device *adev)
{
int num_crtc = 0;
switch (adev->asic_type) {
case CHIP_BONAIRE:
case CHIP_HAWAII:
num_crtc = 6;
break;
case CHIP_KAVERI:
num_crtc = 4;
break;
case CHIP_KABINI:
case CHIP_MULLINS:
num_crtc = 2;
break;
default:
num_crtc = 0;
}
return num_crtc;
}
void dce_v8_0_disable_dce(struct amdgpu_device *adev)
{
/*Disable VGA render and enabled crtc, if has DCE engine*/
if (amdgpu_atombios_has_dce_engine_info(adev)) {
u32 tmp;
int crtc_enabled, i;
dce_v8_0_set_vga_render_state(adev, false);
/*Disable crtc*/
for (i = 0; i < dce_v8_0_get_num_crtc(adev); i++) {
crtc_enabled = REG_GET_FIELD(RREG32(mmCRTC_CONTROL + crtc_offsets[i]),
CRTC_CONTROL, CRTC_MASTER_EN);
if (crtc_enabled) {
WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 1);
tmp = RREG32(mmCRTC_CONTROL + crtc_offsets[i]);
tmp = REG_SET_FIELD(tmp, CRTC_CONTROL, CRTC_MASTER_EN, 0);
WREG32(mmCRTC_CONTROL + crtc_offsets[i], tmp);
WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 0);
}
}
}
}
static void dce_v8_0_program_fmt(struct drm_encoder *encoder) static void dce_v8_0_program_fmt(struct drm_encoder *encoder)
{ {
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
...@@ -1613,7 +1659,7 @@ static void dce_v8_0_afmt_update_ACR(struct drm_encoder *encoder, uint32_t clock ...@@ -1613,7 +1659,7 @@ static void dce_v8_0_afmt_update_ACR(struct drm_encoder *encoder, uint32_t clock
struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv;
uint32_t offset = dig->afmt->offset; uint32_t offset = dig->afmt->offset;
WREG32(mmHDMI_ACR_32_0 + offset, (acr.cts_32khz << HDMI_ACR_44_0__HDMI_ACR_CTS_44__SHIFT)); WREG32(mmHDMI_ACR_32_0 + offset, (acr.cts_32khz << HDMI_ACR_32_0__HDMI_ACR_CTS_32__SHIFT));
WREG32(mmHDMI_ACR_32_1 + offset, acr.n_32khz); WREG32(mmHDMI_ACR_32_1 + offset, acr.n_32khz);
WREG32(mmHDMI_ACR_44_0 + offset, (acr.cts_44_1khz << HDMI_ACR_44_0__HDMI_ACR_CTS_44__SHIFT)); WREG32(mmHDMI_ACR_44_0 + offset, (acr.cts_44_1khz << HDMI_ACR_44_0__HDMI_ACR_CTS_44__SHIFT));
...@@ -1693,6 +1739,7 @@ static void dce_v8_0_afmt_setmode(struct drm_encoder *encoder, ...@@ -1693,6 +1739,7 @@ static void dce_v8_0_afmt_setmode(struct drm_encoder *encoder,
/* Silent, r600_hdmi_enable will raise WARN for us */ /* Silent, r600_hdmi_enable will raise WARN for us */
if (!dig->afmt->enabled) if (!dig->afmt->enabled)
return; return;
offset = dig->afmt->offset; offset = dig->afmt->offset;
/* hdmi deep color mode general control packets setup, if bpc > 8 */ /* hdmi deep color mode general control packets setup, if bpc > 8 */
...@@ -1817,7 +1864,7 @@ static void dce_v8_0_afmt_setmode(struct drm_encoder *encoder, ...@@ -1817,7 +1864,7 @@ static void dce_v8_0_afmt_setmode(struct drm_encoder *encoder,
WREG32_OR(mmHDMI_INFOFRAME_CONTROL0 + offset, WREG32_OR(mmHDMI_INFOFRAME_CONTROL0 + offset,
HDMI_INFOFRAME_CONTROL0__HDMI_AVI_INFO_SEND_MASK | /* enable AVI info frames */ HDMI_INFOFRAME_CONTROL0__HDMI_AVI_INFO_SEND_MASK | /* enable AVI info frames */
HDMI_INFOFRAME_CONTROL0__HDMI_AVI_INFO_SEND_MASK); /* required for audio info values to be updated */ HDMI_INFOFRAME_CONTROL0__HDMI_AVI_INFO_CONT_MASK); /* required for audio info values to be updated */
WREG32_P(mmHDMI_INFOFRAME_CONTROL1 + offset, WREG32_P(mmHDMI_INFOFRAME_CONTROL1 + offset,
(2 << HDMI_INFOFRAME_CONTROL1__HDMI_AVI_INFO_LINE__SHIFT), /* anything other than 0 */ (2 << HDMI_INFOFRAME_CONTROL1__HDMI_AVI_INFO_LINE__SHIFT), /* anything other than 0 */
...@@ -1826,13 +1873,12 @@ static void dce_v8_0_afmt_setmode(struct drm_encoder *encoder, ...@@ -1826,13 +1873,12 @@ static void dce_v8_0_afmt_setmode(struct drm_encoder *encoder,
WREG32_OR(mmAFMT_AUDIO_PACKET_CONTROL + offset, WREG32_OR(mmAFMT_AUDIO_PACKET_CONTROL + offset,
AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_SAMPLE_SEND_MASK); /* send audio packets */ AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_SAMPLE_SEND_MASK); /* send audio packets */
/* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */
WREG32(mmAFMT_RAMP_CONTROL0 + offset, 0x00FFFFFF); WREG32(mmAFMT_RAMP_CONTROL0 + offset, 0x00FFFFFF);
WREG32(mmAFMT_RAMP_CONTROL1 + offset, 0x007FFFFF); WREG32(mmAFMT_RAMP_CONTROL1 + offset, 0x007FFFFF);
WREG32(mmAFMT_RAMP_CONTROL2 + offset, 0x00000001); WREG32(mmAFMT_RAMP_CONTROL2 + offset, 0x00000001);
WREG32(mmAFMT_RAMP_CONTROL3 + offset, 0x00000001); WREG32(mmAFMT_RAMP_CONTROL3 + offset, 0x00000001);
/* enable audio after to setting up hw */ /* enable audio after setting up hw */
dce_v8_0_audio_enable(adev, dig->afmt->pin, true); dce_v8_0_audio_enable(adev, dig->afmt->pin, true);
} }
...@@ -2000,7 +2046,7 @@ static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc, ...@@ -2000,7 +2046,7 @@ static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc,
case DRM_FORMAT_XRGB4444: case DRM_FORMAT_XRGB4444:
case DRM_FORMAT_ARGB4444: case DRM_FORMAT_ARGB4444:
fb_format = ((GRPH_DEPTH_16BPP << GRPH_CONTROL__GRPH_DEPTH__SHIFT) | fb_format = ((GRPH_DEPTH_16BPP << GRPH_CONTROL__GRPH_DEPTH__SHIFT) |
(GRPH_FORMAT_ARGB1555 << GRPH_CONTROL__GRPH_FORMAT__SHIFT)); (GRPH_FORMAT_ARGB4444 << GRPH_CONTROL__GRPH_FORMAT__SHIFT));
#ifdef __BIG_ENDIAN #ifdef __BIG_ENDIAN
fb_swap = (GRPH_ENDIAN_8IN16 << GRPH_SWAP_CNTL__GRPH_ENDIAN_SWAP__SHIFT); fb_swap = (GRPH_ENDIAN_8IN16 << GRPH_SWAP_CNTL__GRPH_ENDIAN_SWAP__SHIFT);
#endif #endif
...@@ -2139,8 +2185,8 @@ static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc, ...@@ -2139,8 +2185,8 @@ static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc,
WREG32(mmVIEWPORT_SIZE + amdgpu_crtc->crtc_offset, WREG32(mmVIEWPORT_SIZE + amdgpu_crtc->crtc_offset,
(viewport_w << 16) | viewport_h); (viewport_w << 16) | viewport_h);
/* set pageflip to happen only at start of vblank interval (front porch) */ /* set pageflip to happen anywhere in vblank interval */
WREG32(mmMASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 3); WREG32(mmMASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 0);
if (!atomic && fb && fb != crtc->primary->fb) { if (!atomic && fb && fb != crtc->primary->fb) {
amdgpu_fb = to_amdgpu_framebuffer(fb); amdgpu_fb = to_amdgpu_framebuffer(fb);
...@@ -2554,7 +2600,7 @@ static const struct drm_crtc_funcs dce_v8_0_crtc_funcs = { ...@@ -2554,7 +2600,7 @@ static const struct drm_crtc_funcs dce_v8_0_crtc_funcs = {
.gamma_set = dce_v8_0_crtc_gamma_set, .gamma_set = dce_v8_0_crtc_gamma_set,
.set_config = amdgpu_crtc_set_config, .set_config = amdgpu_crtc_set_config,
.destroy = dce_v8_0_crtc_destroy, .destroy = dce_v8_0_crtc_destroy,
.page_flip = amdgpu_crtc_page_flip, .page_flip_target = amdgpu_crtc_page_flip_target,
}; };
static void dce_v8_0_crtc_dpms(struct drm_crtc *crtc, int mode) static void dce_v8_0_crtc_dpms(struct drm_crtc *crtc, int mode)
...@@ -2805,21 +2851,20 @@ static int dce_v8_0_early_init(void *handle) ...@@ -2805,21 +2851,20 @@ static int dce_v8_0_early_init(void *handle)
dce_v8_0_set_display_funcs(adev); dce_v8_0_set_display_funcs(adev);
dce_v8_0_set_irq_funcs(adev); dce_v8_0_set_irq_funcs(adev);
adev->mode_info.num_crtc = dce_v8_0_get_num_crtc(adev);
switch (adev->asic_type) { switch (adev->asic_type) {
case CHIP_BONAIRE: case CHIP_BONAIRE:
case CHIP_HAWAII: case CHIP_HAWAII:
adev->mode_info.num_crtc = 6;
adev->mode_info.num_hpd = 6; adev->mode_info.num_hpd = 6;
adev->mode_info.num_dig = 6; adev->mode_info.num_dig = 6;
break; break;
case CHIP_KAVERI: case CHIP_KAVERI:
adev->mode_info.num_crtc = 4;
adev->mode_info.num_hpd = 6; adev->mode_info.num_hpd = 6;
adev->mode_info.num_dig = 7; adev->mode_info.num_dig = 7;
break; break;
case CHIP_KABINI: case CHIP_KABINI:
case CHIP_MULLINS: case CHIP_MULLINS:
adev->mode_info.num_crtc = 2;
adev->mode_info.num_hpd = 6; adev->mode_info.num_hpd = 6;
adev->mode_info.num_dig = 6; /* ? */ adev->mode_info.num_dig = 6; /* ? */
break; break;
...@@ -3238,7 +3283,6 @@ static int dce_v8_0_crtc_irq(struct amdgpu_device *adev, ...@@ -3238,7 +3283,6 @@ static int dce_v8_0_crtc_irq(struct amdgpu_device *adev,
drm_handle_vblank(adev->ddev, crtc); drm_handle_vblank(adev->ddev, crtc);
} }
DRM_DEBUG("IH: D%d vblank\n", crtc + 1); DRM_DEBUG("IH: D%d vblank\n", crtc + 1);
break; break;
case 1: /* vline */ case 1: /* vline */
if (disp_int & interrupt_status_offsets[crtc].vline) if (disp_int & interrupt_status_offsets[crtc].vline)
...@@ -3247,7 +3291,6 @@ static int dce_v8_0_crtc_irq(struct amdgpu_device *adev, ...@@ -3247,7 +3291,6 @@ static int dce_v8_0_crtc_irq(struct amdgpu_device *adev,
DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
DRM_DEBUG("IH: D%d vline\n", crtc + 1); DRM_DEBUG("IH: D%d vline\n", crtc + 1);
break; break;
default: default:
DRM_DEBUG("Unhandled interrupt: %d %d\n", entry->src_id, entry->src_data); DRM_DEBUG("Unhandled interrupt: %d %d\n", entry->src_id, entry->src_data);
......
...@@ -26,4 +26,6 @@ ...@@ -26,4 +26,6 @@
extern const struct amd_ip_funcs dce_v8_0_ip_funcs; extern const struct amd_ip_funcs dce_v8_0_ip_funcs;
void dce_v8_0_disable_dce(struct amdgpu_device *adev);
#endif #endif
此差异已折叠。
/*
* Copyright 2014 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef __DCE_VIRTUAL_H__
#define __DCE_VIRTUAL_H__
extern const struct amd_ip_funcs dce_virtual_ip_funcs;
#define DCE_VIRTUAL_VBLANK_PERIOD 16666666
#endif
...@@ -4465,24 +4465,21 @@ static int gfx_v7_0_sw_init(void *handle) ...@@ -4465,24 +4465,21 @@ static int gfx_v7_0_sw_init(void *handle)
} }
/* reserve GDS, GWS and OA resource for gfx */ /* reserve GDS, GWS and OA resource for gfx */
r = amdgpu_bo_create(adev, adev->gds.mem.gfx_partition_size, r = amdgpu_bo_create_kernel(adev, adev->gds.mem.gfx_partition_size,
PAGE_SIZE, true, PAGE_SIZE, AMDGPU_GEM_DOMAIN_GDS,
AMDGPU_GEM_DOMAIN_GDS, 0, &adev->gds.gds_gfx_bo, NULL, NULL);
NULL, NULL, &adev->gds.gds_gfx_bo);
if (r) if (r)
return r; return r;
r = amdgpu_bo_create(adev, adev->gds.gws.gfx_partition_size, r = amdgpu_bo_create_kernel(adev, adev->gds.gws.gfx_partition_size,
PAGE_SIZE, true, PAGE_SIZE, AMDGPU_GEM_DOMAIN_GWS,
AMDGPU_GEM_DOMAIN_GWS, 0, &adev->gds.gws_gfx_bo, NULL, NULL);
NULL, NULL, &adev->gds.gws_gfx_bo);
if (r) if (r)
return r; return r;
r = amdgpu_bo_create(adev, adev->gds.oa.gfx_partition_size, r = amdgpu_bo_create_kernel(adev, adev->gds.oa.gfx_partition_size,
PAGE_SIZE, true, PAGE_SIZE, AMDGPU_GEM_DOMAIN_OA,
AMDGPU_GEM_DOMAIN_OA, 0, &adev->gds.oa_gfx_bo, NULL, NULL);
NULL, NULL, &adev->gds.oa_gfx_bo);
if (r) if (r)
return r; return r;
......
...@@ -26,6 +26,4 @@ ...@@ -26,6 +26,4 @@
extern const struct amd_ip_funcs gfx_v8_0_ip_funcs; extern const struct amd_ip_funcs gfx_v8_0_ip_funcs;
void gfx_v8_0_select_se_sh(struct amdgpu_device *adev, u32 se_num, u32 sh_num);
#endif #endif
此差异已折叠。
...@@ -116,7 +116,7 @@ static int uvd_v4_2_sw_init(void *handle) ...@@ -116,7 +116,7 @@ static int uvd_v4_2_sw_init(void *handle)
ring = &adev->uvd.ring; ring = &adev->uvd.ring;
sprintf(ring->name, "uvd"); sprintf(ring->name, "uvd");
r = amdgpu_ring_init(adev, ring, 512, CP_PACKET2, 0xf, r = amdgpu_ring_init(adev, ring, 512, PACKET0(mmUVD_NO_OP, 0), 0xf,
&adev->uvd.irq, 0, AMDGPU_RING_TYPE_UVD); &adev->uvd.irq, 0, AMDGPU_RING_TYPE_UVD);
return r; return r;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册