1ca750681SFelix Kuehling /*
2ca750681SFelix Kuehling  * Copyright 2016-2018 Advanced Micro Devices, Inc.
3ca750681SFelix Kuehling  *
4ca750681SFelix Kuehling  * Permission is hereby granted, free of charge, to any person obtaining a
5ca750681SFelix Kuehling  * copy of this software and associated documentation files (the "Software"),
6ca750681SFelix Kuehling  * to deal in the Software without restriction, including without limitation
7ca750681SFelix Kuehling  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8ca750681SFelix Kuehling  * and/or sell copies of the Software, and to permit persons to whom the
9ca750681SFelix Kuehling  * Software is furnished to do so, subject to the following conditions:
10ca750681SFelix Kuehling  *
11ca750681SFelix Kuehling  * The above copyright notice and this permission notice shall be included in
12ca750681SFelix Kuehling  * all copies or substantial portions of the Software.
13ca750681SFelix Kuehling  *
14ca750681SFelix Kuehling  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15ca750681SFelix Kuehling  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16ca750681SFelix Kuehling  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17ca750681SFelix Kuehling  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18ca750681SFelix Kuehling  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19ca750681SFelix Kuehling  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20ca750681SFelix Kuehling  * OTHER DEALINGS IN THE SOFTWARE.
21ca750681SFelix Kuehling  */
22ca750681SFelix Kuehling 
23ca750681SFelix Kuehling #include "kfd_priv.h"
24ca750681SFelix Kuehling #include "kfd_events.h"
25ca750681SFelix Kuehling #include "soc15_int.h"
26ca750681SFelix Kuehling 
27ca750681SFelix Kuehling 
28ca750681SFelix Kuehling static bool event_interrupt_isr_v9(struct kfd_dev *dev,
29ca750681SFelix Kuehling 					const uint32_t *ih_ring_entry)
30ca750681SFelix Kuehling {
31ca750681SFelix Kuehling 	uint16_t source_id, client_id, pasid, vmid;
32ca750681SFelix Kuehling 
33ca750681SFelix Kuehling 	source_id = SOC15_SOURCE_ID_FROM_IH_ENTRY(ih_ring_entry);
34ca750681SFelix Kuehling 	client_id = SOC15_CLIENT_ID_FROM_IH_ENTRY(ih_ring_entry);
35ca750681SFelix Kuehling 	pasid = SOC15_PASID_FROM_IH_ENTRY(ih_ring_entry);
36ca750681SFelix Kuehling 	vmid = SOC15_VMID_FROM_IH_ENTRY(ih_ring_entry);
37ca750681SFelix Kuehling 
38ca750681SFelix Kuehling 	if (pasid) {
39ca750681SFelix Kuehling 		const uint32_t *data = ih_ring_entry;
40ca750681SFelix Kuehling 
41ca750681SFelix Kuehling 		pr_debug("client id 0x%x, source id %d, pasid 0x%x. raw data:\n",
42ca750681SFelix Kuehling 			 client_id, source_id, pasid);
43ca750681SFelix Kuehling 		pr_debug("%8X, %8X, %8X, %8X, %8X, %8X, %8X, %8X.\n",
44ca750681SFelix Kuehling 			 data[0], data[1], data[2], data[3],
45ca750681SFelix Kuehling 			 data[4], data[5], data[6], data[7]);
46ca750681SFelix Kuehling 	}
47ca750681SFelix Kuehling 
48ca750681SFelix Kuehling 	return (pasid != 0) &&
49ca750681SFelix Kuehling 		(source_id == SOC15_INTSRC_CP_END_OF_PIPE ||
50ca750681SFelix Kuehling 		 source_id == SOC15_INTSRC_SDMA_TRAP ||
51ca750681SFelix Kuehling 		 source_id == SOC15_INTSRC_SQ_INTERRUPT_MSG ||
52ca750681SFelix Kuehling 		 source_id == SOC15_INTSRC_CP_BAD_OPCODE);
53ca750681SFelix Kuehling }
54ca750681SFelix Kuehling 
55ca750681SFelix Kuehling static void event_interrupt_wq_v9(struct kfd_dev *dev,
56ca750681SFelix Kuehling 					const uint32_t *ih_ring_entry)
57ca750681SFelix Kuehling {
58ca750681SFelix Kuehling 	uint16_t source_id, client_id, pasid, vmid;
59ca750681SFelix Kuehling 	uint32_t context_id;
60ca750681SFelix Kuehling 
61ca750681SFelix Kuehling 	source_id = SOC15_SOURCE_ID_FROM_IH_ENTRY(ih_ring_entry);
62ca750681SFelix Kuehling 	client_id = SOC15_CLIENT_ID_FROM_IH_ENTRY(ih_ring_entry);
63ca750681SFelix Kuehling 	pasid = SOC15_PASID_FROM_IH_ENTRY(ih_ring_entry);
64ca750681SFelix Kuehling 	vmid = SOC15_VMID_FROM_IH_ENTRY(ih_ring_entry);
65ca750681SFelix Kuehling 	context_id = SOC15_CONTEXT_ID0_FROM_IH_ENTRY(ih_ring_entry);
66ca750681SFelix Kuehling 
67ca750681SFelix Kuehling 	if (source_id == SOC15_INTSRC_CP_END_OF_PIPE)
68ca750681SFelix Kuehling 		kfd_signal_event_interrupt(pasid, context_id, 32);
69ca750681SFelix Kuehling 	else if (source_id == SOC15_INTSRC_SDMA_TRAP)
70ca750681SFelix Kuehling 		kfd_signal_event_interrupt(pasid, context_id & 0xfffffff, 28);
71ca750681SFelix Kuehling 	else if (source_id == SOC15_INTSRC_SQ_INTERRUPT_MSG)
72ca750681SFelix Kuehling 		kfd_signal_event_interrupt(pasid, context_id & 0xffffff, 24);
73ca750681SFelix Kuehling 	else if (source_id == SOC15_INTSRC_CP_BAD_OPCODE)
74ca750681SFelix Kuehling 		kfd_signal_hw_exception_event(pasid);
75ca750681SFelix Kuehling 	else if (client_id == SOC15_IH_CLIENTID_VMC ||
76ca750681SFelix Kuehling 		 client_id == SOC15_IH_CLIENTID_UTCL2) {
77ca750681SFelix Kuehling 		/* TODO */
78ca750681SFelix Kuehling 	}
79ca750681SFelix Kuehling }
80ca750681SFelix Kuehling 
81ca750681SFelix Kuehling const struct kfd_event_interrupt_class event_interrupt_class_v9 = {
82ca750681SFelix Kuehling 	.interrupt_isr = event_interrupt_isr_v9,
83ca750681SFelix Kuehling 	.interrupt_wq = event_interrupt_wq_v9,
84ca750681SFelix Kuehling };
85