Commit 9d7d0248 authored by Felix Kuehling's avatar Felix Kuehling Committed by Oded Gabbay

drm/amdkfd: Add 64-bit doorbell and wptr support to kernel queue

v2: Removed redundant 0x before %p.
Signed-off-by: default avatarFelix Kuehling <Felix.Kuehling@amd.com>
Reviewed-by: default avatarOded Gabbay <oded.gabbay@gmail.com>
Signed-off-by: default avatarOded Gabbay <oded.gabbay@gmail.com>
parent bebfd2f4
...@@ -214,6 +214,16 @@ void write_kernel_doorbell(void __iomem *db, u32 value) ...@@ -214,6 +214,16 @@ void write_kernel_doorbell(void __iomem *db, u32 value)
} }
} }
void write_kernel_doorbell64(void __iomem *db, u64 value)
{
if (db) {
WARN(((unsigned long)db & 7) != 0,
"Unaligned 64-bit doorbell");
writeq(value, (u64 __iomem *)db);
pr_debug("writing %llu to doorbell address %p\n", value, db);
}
}
unsigned int kfd_doorbell_id_to_offset(struct kfd_dev *kfd, unsigned int kfd_doorbell_id_to_offset(struct kfd_dev *kfd,
struct kfd_process *process, struct kfd_process *process,
unsigned int doorbell_id) unsigned int doorbell_id)
......
...@@ -99,7 +99,7 @@ static bool initialize(struct kernel_queue *kq, struct kfd_dev *dev, ...@@ -99,7 +99,7 @@ static bool initialize(struct kernel_queue *kq, struct kfd_dev *dev,
kq->rptr_kernel = kq->rptr_mem->cpu_ptr; kq->rptr_kernel = kq->rptr_mem->cpu_ptr;
kq->rptr_gpu_addr = kq->rptr_mem->gpu_addr; kq->rptr_gpu_addr = kq->rptr_mem->gpu_addr;
retval = kfd_gtt_sa_allocate(dev, sizeof(*kq->wptr_kernel), retval = kfd_gtt_sa_allocate(dev, dev->device_info->doorbell_size,
&kq->wptr_mem); &kq->wptr_mem);
if (retval != 0) if (retval != 0)
...@@ -208,6 +208,7 @@ static int acquire_packet_buffer(struct kernel_queue *kq, ...@@ -208,6 +208,7 @@ static int acquire_packet_buffer(struct kernel_queue *kq,
size_t available_size; size_t available_size;
size_t queue_size_dwords; size_t queue_size_dwords;
uint32_t wptr, rptr; uint32_t wptr, rptr;
uint64_t wptr64;
unsigned int *queue_address; unsigned int *queue_address;
/* When rptr == wptr, the buffer is empty. /* When rptr == wptr, the buffer is empty.
...@@ -216,7 +217,8 @@ static int acquire_packet_buffer(struct kernel_queue *kq, ...@@ -216,7 +217,8 @@ static int acquire_packet_buffer(struct kernel_queue *kq,
* the opposite. So we can only use up to queue_size_dwords - 1 dwords. * the opposite. So we can only use up to queue_size_dwords - 1 dwords.
*/ */
rptr = *kq->rptr_kernel; rptr = *kq->rptr_kernel;
wptr = *kq->wptr_kernel; wptr = kq->pending_wptr;
wptr64 = kq->pending_wptr64;
queue_address = (unsigned int *)kq->pq_kernel_addr; queue_address = (unsigned int *)kq->pq_kernel_addr;
queue_size_dwords = kq->queue->properties.queue_size / 4; queue_size_dwords = kq->queue->properties.queue_size / 4;
...@@ -246,11 +248,13 @@ static int acquire_packet_buffer(struct kernel_queue *kq, ...@@ -246,11 +248,13 @@ static int acquire_packet_buffer(struct kernel_queue *kq,
while (wptr > 0) { while (wptr > 0) {
queue_address[wptr] = kq->nop_packet; queue_address[wptr] = kq->nop_packet;
wptr = (wptr + 1) % queue_size_dwords; wptr = (wptr + 1) % queue_size_dwords;
wptr64++;
} }
} }
*buffer_ptr = &queue_address[wptr]; *buffer_ptr = &queue_address[wptr];
kq->pending_wptr = wptr + packet_size_in_dwords; kq->pending_wptr = wptr + packet_size_in_dwords;
kq->pending_wptr64 = wptr64 + packet_size_in_dwords;
return 0; return 0;
...@@ -272,14 +276,18 @@ static void submit_packet(struct kernel_queue *kq) ...@@ -272,14 +276,18 @@ static void submit_packet(struct kernel_queue *kq)
pr_debug("\n"); pr_debug("\n");
#endif #endif
*kq->wptr_kernel = kq->pending_wptr; kq->ops_asic_specific.submit_packet(kq);
write_kernel_doorbell(kq->queue->properties.doorbell_ptr,
kq->pending_wptr);
} }
static void rollback_packet(struct kernel_queue *kq) static void rollback_packet(struct kernel_queue *kq)
{ {
kq->pending_wptr = *kq->wptr_kernel; if (kq->dev->device_info->doorbell_size == 8) {
kq->pending_wptr64 = *kq->wptr64_kernel;
kq->pending_wptr = *kq->wptr_kernel %
(kq->queue->properties.queue_size / 4);
} else {
kq->pending_wptr = *kq->wptr_kernel;
}
} }
struct kernel_queue *kernel_queue_init(struct kfd_dev *dev, struct kernel_queue *kernel_queue_init(struct kfd_dev *dev,
...@@ -310,6 +318,11 @@ struct kernel_queue *kernel_queue_init(struct kfd_dev *dev, ...@@ -310,6 +318,11 @@ struct kernel_queue *kernel_queue_init(struct kfd_dev *dev,
case CHIP_HAWAII: case CHIP_HAWAII:
kernel_queue_init_cik(&kq->ops_asic_specific); kernel_queue_init_cik(&kq->ops_asic_specific);
break; break;
case CHIP_VEGA10:
case CHIP_RAVEN:
kernel_queue_init_v9(&kq->ops_asic_specific);
break;
default: default:
WARN(1, "Unexpected ASIC family %u", WARN(1, "Unexpected ASIC family %u",
dev->device_info->asic_family); dev->device_info->asic_family);
......
...@@ -72,6 +72,7 @@ struct kernel_queue { ...@@ -72,6 +72,7 @@ struct kernel_queue {
struct kfd_dev *dev; struct kfd_dev *dev;
struct mqd_manager *mqd; struct mqd_manager *mqd;
struct queue *queue; struct queue *queue;
uint64_t pending_wptr64;
uint32_t pending_wptr; uint32_t pending_wptr;
unsigned int nop_packet; unsigned int nop_packet;
...@@ -79,7 +80,10 @@ struct kernel_queue { ...@@ -79,7 +80,10 @@ struct kernel_queue {
uint32_t *rptr_kernel; uint32_t *rptr_kernel;
uint64_t rptr_gpu_addr; uint64_t rptr_gpu_addr;
struct kfd_mem_obj *wptr_mem; struct kfd_mem_obj *wptr_mem;
uint32_t *wptr_kernel; union {
uint64_t *wptr64_kernel;
uint32_t *wptr_kernel;
};
uint64_t wptr_gpu_addr; uint64_t wptr_gpu_addr;
struct kfd_mem_obj *pq; struct kfd_mem_obj *pq;
uint64_t pq_gpu_addr; uint64_t pq_gpu_addr;
...@@ -97,5 +101,6 @@ struct kernel_queue { ...@@ -97,5 +101,6 @@ struct kernel_queue {
void kernel_queue_init_cik(struct kernel_queue_ops *ops); void kernel_queue_init_cik(struct kernel_queue_ops *ops);
void kernel_queue_init_vi(struct kernel_queue_ops *ops); void kernel_queue_init_vi(struct kernel_queue_ops *ops);
void kernel_queue_init_v9(struct kernel_queue_ops *ops);
#endif /* KFD_KERNEL_QUEUE_H_ */ #endif /* KFD_KERNEL_QUEUE_H_ */
...@@ -26,11 +26,13 @@ ...@@ -26,11 +26,13 @@
static bool initialize_cik(struct kernel_queue *kq, struct kfd_dev *dev, static bool initialize_cik(struct kernel_queue *kq, struct kfd_dev *dev,
enum kfd_queue_type type, unsigned int queue_size); enum kfd_queue_type type, unsigned int queue_size);
static void uninitialize_cik(struct kernel_queue *kq); static void uninitialize_cik(struct kernel_queue *kq);
static void submit_packet_cik(struct kernel_queue *kq);
void kernel_queue_init_cik(struct kernel_queue_ops *ops) void kernel_queue_init_cik(struct kernel_queue_ops *ops)
{ {
ops->initialize = initialize_cik; ops->initialize = initialize_cik;
ops->uninitialize = uninitialize_cik; ops->uninitialize = uninitialize_cik;
ops->submit_packet = submit_packet_cik;
} }
static bool initialize_cik(struct kernel_queue *kq, struct kfd_dev *dev, static bool initialize_cik(struct kernel_queue *kq, struct kfd_dev *dev,
...@@ -42,3 +44,10 @@ static bool initialize_cik(struct kernel_queue *kq, struct kfd_dev *dev, ...@@ -42,3 +44,10 @@ static bool initialize_cik(struct kernel_queue *kq, struct kfd_dev *dev,
static void uninitialize_cik(struct kernel_queue *kq) static void uninitialize_cik(struct kernel_queue *kq)
{ {
} }
static void submit_packet_cik(struct kernel_queue *kq)
{
*kq->wptr_kernel = kq->pending_wptr;
write_kernel_doorbell(kq->queue->properties.doorbell_ptr,
kq->pending_wptr);
}
...@@ -29,11 +29,13 @@ ...@@ -29,11 +29,13 @@
static bool initialize_v9(struct kernel_queue *kq, struct kfd_dev *dev, static bool initialize_v9(struct kernel_queue *kq, struct kfd_dev *dev,
enum kfd_queue_type type, unsigned int queue_size); enum kfd_queue_type type, unsigned int queue_size);
static void uninitialize_v9(struct kernel_queue *kq); static void uninitialize_v9(struct kernel_queue *kq);
static void submit_packet_v9(struct kernel_queue *kq);
void kernel_queue_init_v9(struct kernel_queue_ops *ops) void kernel_queue_init_v9(struct kernel_queue_ops *ops)
{ {
ops->initialize = initialize_v9; ops->initialize = initialize_v9;
ops->uninitialize = uninitialize_v9; ops->uninitialize = uninitialize_v9;
ops->submit_packet = submit_packet_v9;
} }
static bool initialize_v9(struct kernel_queue *kq, struct kfd_dev *dev, static bool initialize_v9(struct kernel_queue *kq, struct kfd_dev *dev,
...@@ -58,6 +60,13 @@ static void uninitialize_v9(struct kernel_queue *kq) ...@@ -58,6 +60,13 @@ static void uninitialize_v9(struct kernel_queue *kq)
kfd_gtt_sa_free(kq->dev, kq->eop_mem); kfd_gtt_sa_free(kq->dev, kq->eop_mem);
} }
static void submit_packet_v9(struct kernel_queue *kq)
{
*kq->wptr64_kernel = kq->pending_wptr64;
write_kernel_doorbell64(kq->queue->properties.doorbell_ptr,
kq->pending_wptr64);
}
static int pm_map_process_v9(struct packet_manager *pm, static int pm_map_process_v9(struct packet_manager *pm,
uint32_t *buffer, struct qcm_process_device *qpd) uint32_t *buffer, struct qcm_process_device *qpd)
{ {
......
...@@ -29,11 +29,13 @@ ...@@ -29,11 +29,13 @@
static bool initialize_vi(struct kernel_queue *kq, struct kfd_dev *dev, static bool initialize_vi(struct kernel_queue *kq, struct kfd_dev *dev,
enum kfd_queue_type type, unsigned int queue_size); enum kfd_queue_type type, unsigned int queue_size);
static void uninitialize_vi(struct kernel_queue *kq); static void uninitialize_vi(struct kernel_queue *kq);
static void submit_packet_vi(struct kernel_queue *kq);
void kernel_queue_init_vi(struct kernel_queue_ops *ops) void kernel_queue_init_vi(struct kernel_queue_ops *ops)
{ {
ops->initialize = initialize_vi; ops->initialize = initialize_vi;
ops->uninitialize = uninitialize_vi; ops->uninitialize = uninitialize_vi;
ops->submit_packet = submit_packet_vi;
} }
static bool initialize_vi(struct kernel_queue *kq, struct kfd_dev *dev, static bool initialize_vi(struct kernel_queue *kq, struct kfd_dev *dev,
...@@ -58,6 +60,13 @@ static void uninitialize_vi(struct kernel_queue *kq) ...@@ -58,6 +60,13 @@ static void uninitialize_vi(struct kernel_queue *kq)
kfd_gtt_sa_free(kq->dev, kq->eop_mem); kfd_gtt_sa_free(kq->dev, kq->eop_mem);
} }
static void submit_packet_vi(struct kernel_queue *kq)
{
*kq->wptr_kernel = kq->pending_wptr;
write_kernel_doorbell(kq->queue->properties.doorbell_ptr,
kq->pending_wptr);
}
unsigned int pm_build_pm4_header(unsigned int opcode, size_t packet_size) unsigned int pm_build_pm4_header(unsigned int opcode, size_t packet_size)
{ {
union PM4_MES_TYPE_3_HEADER header; union PM4_MES_TYPE_3_HEADER header;
......
...@@ -769,6 +769,7 @@ void __iomem *kfd_get_kernel_doorbell(struct kfd_dev *kfd, ...@@ -769,6 +769,7 @@ void __iomem *kfd_get_kernel_doorbell(struct kfd_dev *kfd,
void kfd_release_kernel_doorbell(struct kfd_dev *kfd, u32 __iomem *db_addr); void kfd_release_kernel_doorbell(struct kfd_dev *kfd, u32 __iomem *db_addr);
u32 read_kernel_doorbell(u32 __iomem *db); u32 read_kernel_doorbell(u32 __iomem *db);
void write_kernel_doorbell(void __iomem *db, u32 value); void write_kernel_doorbell(void __iomem *db, u32 value);
void write_kernel_doorbell64(void __iomem *db, u64 value);
unsigned int kfd_doorbell_id_to_offset(struct kfd_dev *kfd, unsigned int kfd_doorbell_id_to_offset(struct kfd_dev *kfd,
struct kfd_process *process, struct kfd_process *process,
unsigned int doorbell_id); unsigned int doorbell_id);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment