Merge branches 'pm-cpufreq', 'pm-cpuidle', 'pm-devfreq', 'pm-opp' and 'pm-tools'
[linux-drm-fsl-dcu.git] / drivers / gpu / drm / amd / amdkfd / kfd_device.c
1 /*
2  * Copyright 2014 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  */
22
23 #include <linux/amd-iommu.h>
24 #include <linux/bsearch.h>
25 #include <linux/pci.h>
26 #include <linux/slab.h>
27 #include "kfd_priv.h"
28 #include "kfd_device_queue_manager.h"
29 #include "kfd_pm4_headers.h"
30
31 #define MQD_SIZE_ALIGNED 768
32
33 static const struct kfd_device_info kaveri_device_info = {
34         .max_pasid_bits = 16,
35         .ih_ring_entry_size = 4 * sizeof(uint32_t),
36         .mqd_size_aligned = MQD_SIZE_ALIGNED
37 };
38
39 struct kfd_deviceid {
40         unsigned short did;
41         const struct kfd_device_info *device_info;
42 };
43
44 /* Please keep this sorted by increasing device id. */
45 static const struct kfd_deviceid supported_devices[] = {
46         { 0x1304, &kaveri_device_info },        /* Kaveri */
47         { 0x1305, &kaveri_device_info },        /* Kaveri */
48         { 0x1306, &kaveri_device_info },        /* Kaveri */
49         { 0x1307, &kaveri_device_info },        /* Kaveri */
50         { 0x1309, &kaveri_device_info },        /* Kaveri */
51         { 0x130A, &kaveri_device_info },        /* Kaveri */
52         { 0x130B, &kaveri_device_info },        /* Kaveri */
53         { 0x130C, &kaveri_device_info },        /* Kaveri */
54         { 0x130D, &kaveri_device_info },        /* Kaveri */
55         { 0x130E, &kaveri_device_info },        /* Kaveri */
56         { 0x130F, &kaveri_device_info },        /* Kaveri */
57         { 0x1310, &kaveri_device_info },        /* Kaveri */
58         { 0x1311, &kaveri_device_info },        /* Kaveri */
59         { 0x1312, &kaveri_device_info },        /* Kaveri */
60         { 0x1313, &kaveri_device_info },        /* Kaveri */
61         { 0x1315, &kaveri_device_info },        /* Kaveri */
62         { 0x1316, &kaveri_device_info },        /* Kaveri */
63         { 0x1317, &kaveri_device_info },        /* Kaveri */
64         { 0x1318, &kaveri_device_info },        /* Kaveri */
65         { 0x131B, &kaveri_device_info },        /* Kaveri */
66         { 0x131C, &kaveri_device_info },        /* Kaveri */
67         { 0x131D, &kaveri_device_info },        /* Kaveri */
68 };
69
70 static const struct kfd_device_info *lookup_device_info(unsigned short did)
71 {
72         size_t i;
73
74         for (i = 0; i < ARRAY_SIZE(supported_devices); i++) {
75                 if (supported_devices[i].did == did) {
76                         BUG_ON(supported_devices[i].device_info == NULL);
77                         return supported_devices[i].device_info;
78                 }
79         }
80
81         return NULL;
82 }
83
84 struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd, struct pci_dev *pdev)
85 {
86         struct kfd_dev *kfd;
87
88         const struct kfd_device_info *device_info =
89                                         lookup_device_info(pdev->device);
90
91         if (!device_info)
92                 return NULL;
93
94         kfd = kzalloc(sizeof(*kfd), GFP_KERNEL);
95         if (!kfd)
96                 return NULL;
97
98         kfd->kgd = kgd;
99         kfd->device_info = device_info;
100         kfd->pdev = pdev;
101         kfd->init_complete = false;
102
103         return kfd;
104 }
105
106 static bool device_iommu_pasid_init(struct kfd_dev *kfd)
107 {
108         const u32 required_iommu_flags = AMD_IOMMU_DEVICE_FLAG_ATS_SUP |
109                                         AMD_IOMMU_DEVICE_FLAG_PRI_SUP |
110                                         AMD_IOMMU_DEVICE_FLAG_PASID_SUP;
111
112         struct amd_iommu_device_info iommu_info;
113         unsigned int pasid_limit;
114         int err;
115
116         err = amd_iommu_device_info(kfd->pdev, &iommu_info);
117         if (err < 0) {
118                 dev_err(kfd_device,
119                         "error getting iommu info. is the iommu enabled?\n");
120                 return false;
121         }
122
123         if ((iommu_info.flags & required_iommu_flags) != required_iommu_flags) {
124                 dev_err(kfd_device, "error required iommu flags ats(%i), pri(%i), pasid(%i)\n",
125                        (iommu_info.flags & AMD_IOMMU_DEVICE_FLAG_ATS_SUP) != 0,
126                        (iommu_info.flags & AMD_IOMMU_DEVICE_FLAG_PRI_SUP) != 0,
127                        (iommu_info.flags & AMD_IOMMU_DEVICE_FLAG_PASID_SUP) != 0);
128                 return false;
129         }
130
131         pasid_limit = min_t(unsigned int,
132                         (unsigned int)1 << kfd->device_info->max_pasid_bits,
133                         iommu_info.max_pasids);
134         /*
135          * last pasid is used for kernel queues doorbells
136          * in the future the last pasid might be used for a kernel thread.
137          */
138         pasid_limit = min_t(unsigned int,
139                                 pasid_limit,
140                                 kfd->doorbell_process_limit - 1);
141
142         err = amd_iommu_init_device(kfd->pdev, pasid_limit);
143         if (err < 0) {
144                 dev_err(kfd_device, "error initializing iommu device\n");
145                 return false;
146         }
147
148         if (!kfd_set_pasid_limit(pasid_limit)) {
149                 dev_err(kfd_device, "error setting pasid limit\n");
150                 amd_iommu_free_device(kfd->pdev);
151                 return false;
152         }
153
154         return true;
155 }
156
157 static void iommu_pasid_shutdown_callback(struct pci_dev *pdev, int pasid)
158 {
159         struct kfd_dev *dev = kfd_device_by_pci_dev(pdev);
160
161         if (dev)
162                 kfd_unbind_process_from_device(dev, pasid);
163 }
164
165 bool kgd2kfd_device_init(struct kfd_dev *kfd,
166                          const struct kgd2kfd_shared_resources *gpu_resources)
167 {
168         unsigned int size;
169
170         kfd->shared_resources = *gpu_resources;
171
172         /* calculate max size of mqds needed for queues */
173         size = max_num_of_queues_per_device *
174                         kfd->device_info->mqd_size_aligned;
175
176         /* add another 512KB for all other allocations on gart */
177         size += 512 * 1024;
178
179         if (kfd2kgd->init_sa_manager(kfd->kgd, size)) {
180                 dev_err(kfd_device,
181                         "Error initializing sa manager for device (%x:%x)\n",
182                         kfd->pdev->vendor, kfd->pdev->device);
183                 goto out;
184         }
185
186         kfd_doorbell_init(kfd);
187
188         if (kfd_topology_add_device(kfd) != 0) {
189                 dev_err(kfd_device,
190                         "Error adding device (%x:%x) to topology\n",
191                         kfd->pdev->vendor, kfd->pdev->device);
192                 goto kfd_topology_add_device_error;
193         }
194
195         if (!device_iommu_pasid_init(kfd)) {
196                 dev_err(kfd_device,
197                         "Error initializing iommuv2 for device (%x:%x)\n",
198                         kfd->pdev->vendor, kfd->pdev->device);
199                 goto device_iommu_pasid_error;
200         }
201         amd_iommu_set_invalidate_ctx_cb(kfd->pdev,
202                                                 iommu_pasid_shutdown_callback);
203
204         kfd->dqm = device_queue_manager_init(kfd);
205         if (!kfd->dqm) {
206                 dev_err(kfd_device,
207                         "Error initializing queue manager for device (%x:%x)\n",
208                         kfd->pdev->vendor, kfd->pdev->device);
209                 goto device_queue_manager_error;
210         }
211
212         if (kfd->dqm->start(kfd->dqm) != 0) {
213                 dev_err(kfd_device,
214                         "Error starting queuen manager for device (%x:%x)\n",
215                         kfd->pdev->vendor, kfd->pdev->device);
216                 goto dqm_start_error;
217         }
218
219         kfd->init_complete = true;
220         dev_info(kfd_device, "added device (%x:%x)\n", kfd->pdev->vendor,
221                  kfd->pdev->device);
222
223         pr_debug("kfd: Starting kfd with the following scheduling policy %d\n",
224                 sched_policy);
225
226         goto out;
227
228 dqm_start_error:
229         device_queue_manager_uninit(kfd->dqm);
230 device_queue_manager_error:
231         amd_iommu_free_device(kfd->pdev);
232 device_iommu_pasid_error:
233         kfd_topology_remove_device(kfd);
234 kfd_topology_add_device_error:
235         kfd2kgd->fini_sa_manager(kfd->kgd);
236         dev_err(kfd_device,
237                 "device (%x:%x) NOT added due to errors\n",
238                 kfd->pdev->vendor, kfd->pdev->device);
239 out:
240         return kfd->init_complete;
241 }
242
243 void kgd2kfd_device_exit(struct kfd_dev *kfd)
244 {
245         if (kfd->init_complete) {
246                 device_queue_manager_uninit(kfd->dqm);
247                 amd_iommu_free_device(kfd->pdev);
248                 kfd_topology_remove_device(kfd);
249         }
250
251         kfree(kfd);
252 }
253
254 void kgd2kfd_suspend(struct kfd_dev *kfd)
255 {
256         BUG_ON(kfd == NULL);
257
258         if (kfd->init_complete) {
259                 kfd->dqm->stop(kfd->dqm);
260                 amd_iommu_set_invalidate_ctx_cb(kfd->pdev, NULL);
261                 amd_iommu_free_device(kfd->pdev);
262         }
263 }
264
265 int kgd2kfd_resume(struct kfd_dev *kfd)
266 {
267         unsigned int pasid_limit;
268         int err;
269
270         BUG_ON(kfd == NULL);
271
272         pasid_limit = kfd_get_pasid_limit();
273
274         if (kfd->init_complete) {
275                 err = amd_iommu_init_device(kfd->pdev, pasid_limit);
276                 if (err < 0)
277                         return -ENXIO;
278                 amd_iommu_set_invalidate_ctx_cb(kfd->pdev,
279                                                 iommu_pasid_shutdown_callback);
280                 kfd->dqm->start(kfd->dqm);
281         }
282
283         return 0;
284 }
285
286 /* This is called directly from KGD at ISR. */
287 void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry)
288 {
289         /* Process interrupts / schedule work as necessary */
290 }