kfd_device.c 21.8 KB
Newer Older
O
Oded Gabbay 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/*
 * 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.
 */

#include <linux/amd-iommu.h>
#include <linux/bsearch.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include "kfd_priv.h"
28
#include "kfd_device_queue_manager.h"
29
#include "kfd_pm4_headers_vi.h"
F
Felix Kuehling 已提交
30
#include "cwsr_trap_handler_gfx8.asm"
O
Oded Gabbay 已提交
31

32 33
#define MQD_SIZE_ALIGNED 768

O
Oded Gabbay 已提交
34
static const struct kfd_device_info kaveri_device_info = {
35 36
	.asic_family = CHIP_KAVERI,
	.max_pasid_bits = 16,
37 38
	/* max num of queues for KV.TODO should be a dynamic value */
	.max_no_of_hqd	= 24,
39
	.ih_ring_entry_size = 4 * sizeof(uint32_t),
40
	.event_interrupt_class = &event_interrupt_class_cik,
41
	.num_of_watch_points = 4,
F
Felix Kuehling 已提交
42 43
	.mqd_size_aligned = MQD_SIZE_ALIGNED,
	.supports_cwsr = false,
44
	.needs_pci_atomics = false,
45 46 47 48
};

static const struct kfd_device_info carrizo_device_info = {
	.asic_family = CHIP_CARRIZO,
O
Oded Gabbay 已提交
49
	.max_pasid_bits = 16,
50 51
	/* max num of queues for CZ.TODO should be a dynamic value */
	.max_no_of_hqd	= 24,
52
	.ih_ring_entry_size = 4 * sizeof(uint32_t),
53
	.event_interrupt_class = &event_interrupt_class_cik,
54
	.num_of_watch_points = 4,
F
Felix Kuehling 已提交
55 56
	.mqd_size_aligned = MQD_SIZE_ALIGNED,
	.supports_cwsr = true,
57
	.needs_pci_atomics = false,
O
Oded Gabbay 已提交
58 59
};

60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
static const struct kfd_device_info hawaii_device_info = {
	.asic_family = CHIP_HAWAII,
	.max_pasid_bits = 16,
	/* max num of queues for KV.TODO should be a dynamic value */
	.max_no_of_hqd	= 24,
	.ih_ring_entry_size = 4 * sizeof(uint32_t),
	.event_interrupt_class = &event_interrupt_class_cik,
	.num_of_watch_points = 4,
	.mqd_size_aligned = MQD_SIZE_ALIGNED,
	.supports_cwsr = false,
	.needs_pci_atomics = false,
};

static const struct kfd_device_info tonga_device_info = {
	.asic_family = CHIP_TONGA,
	.max_pasid_bits = 16,
	.max_no_of_hqd  = 24,
	.ih_ring_entry_size = 4 * sizeof(uint32_t),
	.event_interrupt_class = &event_interrupt_class_cik,
	.num_of_watch_points = 4,
	.mqd_size_aligned = MQD_SIZE_ALIGNED,
	.supports_cwsr = false,
	.needs_pci_atomics = true,
};

static const struct kfd_device_info tonga_vf_device_info = {
	.asic_family = CHIP_TONGA,
	.max_pasid_bits = 16,
	.max_no_of_hqd  = 24,
	.ih_ring_entry_size = 4 * sizeof(uint32_t),
	.event_interrupt_class = &event_interrupt_class_cik,
	.num_of_watch_points = 4,
	.mqd_size_aligned = MQD_SIZE_ALIGNED,
	.supports_cwsr = false,
	.needs_pci_atomics = false,
};

static const struct kfd_device_info fiji_device_info = {
	.asic_family = CHIP_FIJI,
	.max_pasid_bits = 16,
	.max_no_of_hqd  = 24,
	.ih_ring_entry_size = 4 * sizeof(uint32_t),
	.event_interrupt_class = &event_interrupt_class_cik,
	.num_of_watch_points = 4,
	.mqd_size_aligned = MQD_SIZE_ALIGNED,
	.supports_cwsr = true,
	.needs_pci_atomics = true,
};

static const struct kfd_device_info fiji_vf_device_info = {
	.asic_family = CHIP_FIJI,
	.max_pasid_bits = 16,
	.max_no_of_hqd  = 24,
	.ih_ring_entry_size = 4 * sizeof(uint32_t),
	.event_interrupt_class = &event_interrupt_class_cik,
	.num_of_watch_points = 4,
	.mqd_size_aligned = MQD_SIZE_ALIGNED,
	.supports_cwsr = true,
	.needs_pci_atomics = false,
};


static const struct kfd_device_info polaris10_device_info = {
	.asic_family = CHIP_POLARIS10,
	.max_pasid_bits = 16,
	.max_no_of_hqd  = 24,
	.ih_ring_entry_size = 4 * sizeof(uint32_t),
	.event_interrupt_class = &event_interrupt_class_cik,
	.num_of_watch_points = 4,
	.mqd_size_aligned = MQD_SIZE_ALIGNED,
	.supports_cwsr = true,
	.needs_pci_atomics = true,
};

static const struct kfd_device_info polaris10_vf_device_info = {
	.asic_family = CHIP_POLARIS10,
	.max_pasid_bits = 16,
	.max_no_of_hqd  = 24,
	.ih_ring_entry_size = 4 * sizeof(uint32_t),
	.event_interrupt_class = &event_interrupt_class_cik,
	.num_of_watch_points = 4,
	.mqd_size_aligned = MQD_SIZE_ALIGNED,
	.supports_cwsr = true,
	.needs_pci_atomics = false,
};

static const struct kfd_device_info polaris11_device_info = {
	.asic_family = CHIP_POLARIS11,
	.max_pasid_bits = 16,
	.max_no_of_hqd  = 24,
	.ih_ring_entry_size = 4 * sizeof(uint32_t),
	.event_interrupt_class = &event_interrupt_class_cik,
	.num_of_watch_points = 4,
	.mqd_size_aligned = MQD_SIZE_ALIGNED,
	.supports_cwsr = true,
	.needs_pci_atomics = true,
};


O
Oded Gabbay 已提交
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
struct kfd_deviceid {
	unsigned short did;
	const struct kfd_device_info *device_info;
};

static const struct kfd_deviceid supported_devices[] = {
	{ 0x1304, &kaveri_device_info },	/* Kaveri */
	{ 0x1305, &kaveri_device_info },	/* Kaveri */
	{ 0x1306, &kaveri_device_info },	/* Kaveri */
	{ 0x1307, &kaveri_device_info },	/* Kaveri */
	{ 0x1309, &kaveri_device_info },	/* Kaveri */
	{ 0x130A, &kaveri_device_info },	/* Kaveri */
	{ 0x130B, &kaveri_device_info },	/* Kaveri */
	{ 0x130C, &kaveri_device_info },	/* Kaveri */
	{ 0x130D, &kaveri_device_info },	/* Kaveri */
	{ 0x130E, &kaveri_device_info },	/* Kaveri */
	{ 0x130F, &kaveri_device_info },	/* Kaveri */
	{ 0x1310, &kaveri_device_info },	/* Kaveri */
	{ 0x1311, &kaveri_device_info },	/* Kaveri */
	{ 0x1312, &kaveri_device_info },	/* Kaveri */
	{ 0x1313, &kaveri_device_info },	/* Kaveri */
	{ 0x1315, &kaveri_device_info },	/* Kaveri */
	{ 0x1316, &kaveri_device_info },	/* Kaveri */
	{ 0x1317, &kaveri_device_info },	/* Kaveri */
	{ 0x1318, &kaveri_device_info },	/* Kaveri */
	{ 0x131B, &kaveri_device_info },	/* Kaveri */
	{ 0x131C, &kaveri_device_info },	/* Kaveri */
186 187 188 189 190
	{ 0x131D, &kaveri_device_info },	/* Kaveri */
	{ 0x9870, &carrizo_device_info },	/* Carrizo */
	{ 0x9874, &carrizo_device_info },	/* Carrizo */
	{ 0x9875, &carrizo_device_info },	/* Carrizo */
	{ 0x9876, &carrizo_device_info },	/* Carrizo */
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
	{ 0x9877, &carrizo_device_info },	/* Carrizo */
	{ 0x67A0, &hawaii_device_info },	/* Hawaii */
	{ 0x67A1, &hawaii_device_info },	/* Hawaii */
	{ 0x67A2, &hawaii_device_info },	/* Hawaii */
	{ 0x67A8, &hawaii_device_info },	/* Hawaii */
	{ 0x67A9, &hawaii_device_info },	/* Hawaii */
	{ 0x67AA, &hawaii_device_info },	/* Hawaii */
	{ 0x67B0, &hawaii_device_info },	/* Hawaii */
	{ 0x67B1, &hawaii_device_info },	/* Hawaii */
	{ 0x67B8, &hawaii_device_info },	/* Hawaii */
	{ 0x67B9, &hawaii_device_info },	/* Hawaii */
	{ 0x67BA, &hawaii_device_info },	/* Hawaii */
	{ 0x67BE, &hawaii_device_info },	/* Hawaii */
	{ 0x6920, &tonga_device_info },		/* Tonga */
	{ 0x6921, &tonga_device_info },		/* Tonga */
	{ 0x6928, &tonga_device_info },		/* Tonga */
	{ 0x6929, &tonga_device_info },		/* Tonga */
	{ 0x692B, &tonga_device_info },		/* Tonga */
	{ 0x692F, &tonga_vf_device_info },	/* Tonga vf */
	{ 0x6938, &tonga_device_info },		/* Tonga */
	{ 0x6939, &tonga_device_info },		/* Tonga */
	{ 0x7300, &fiji_device_info },		/* Fiji */
	{ 0x730F, &fiji_vf_device_info },	/* Fiji vf*/
	{ 0x67C0, &polaris10_device_info },	/* Polaris10 */
	{ 0x67C1, &polaris10_device_info },	/* Polaris10 */
	{ 0x67C2, &polaris10_device_info },	/* Polaris10 */
	{ 0x67C4, &polaris10_device_info },	/* Polaris10 */
	{ 0x67C7, &polaris10_device_info },	/* Polaris10 */
	{ 0x67C8, &polaris10_device_info },	/* Polaris10 */
	{ 0x67C9, &polaris10_device_info },	/* Polaris10 */
	{ 0x67CA, &polaris10_device_info },	/* Polaris10 */
	{ 0x67CC, &polaris10_device_info },	/* Polaris10 */
	{ 0x67CF, &polaris10_device_info },	/* Polaris10 */
	{ 0x67D0, &polaris10_vf_device_info },	/* Polaris10 vf*/
	{ 0x67DF, &polaris10_device_info },	/* Polaris10 */
	{ 0x67E0, &polaris11_device_info },	/* Polaris11 */
	{ 0x67E1, &polaris11_device_info },	/* Polaris11 */
	{ 0x67E3, &polaris11_device_info },	/* Polaris11 */
	{ 0x67E7, &polaris11_device_info },	/* Polaris11 */
	{ 0x67E8, &polaris11_device_info },	/* Polaris11 */
	{ 0x67E9, &polaris11_device_info },	/* Polaris11 */
	{ 0x67EB, &polaris11_device_info },	/* Polaris11 */
	{ 0x67EF, &polaris11_device_info },	/* Polaris11 */
	{ 0x67FF, &polaris11_device_info },	/* Polaris11 */
O
Oded Gabbay 已提交
235 236
};

237 238 239 240
static int kfd_gtt_sa_init(struct kfd_dev *kfd, unsigned int buf_size,
				unsigned int chunk_size);
static void kfd_gtt_sa_fini(struct kfd_dev *kfd);

241 242
static int kfd_resume(struct kfd_dev *kfd);

O
Oded Gabbay 已提交
243 244 245 246 247 248
static const struct kfd_device_info *lookup_device_info(unsigned short did)
{
	size_t i;

	for (i = 0; i < ARRAY_SIZE(supported_devices); i++) {
		if (supported_devices[i].did == did) {
249
			WARN_ON(!supported_devices[i].device_info);
O
Oded Gabbay 已提交
250 251 252 253
			return supported_devices[i].device_info;
		}
	}

254 255 256
	dev_warn(kfd_device, "DID %04x is missing in supported_devices\n",
		 did);

O
Oded Gabbay 已提交
257 258 259
	return NULL;
}

260 261
struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd,
	struct pci_dev *pdev, const struct kfd2kgd_calls *f2g)
O
Oded Gabbay 已提交
262 263 264 265 266 267
{
	struct kfd_dev *kfd;

	const struct kfd_device_info *device_info =
					lookup_device_info(pdev->device);

268 269
	if (!device_info) {
		dev_err(kfd_device, "kgd2kfd_probe failed\n");
O
Oded Gabbay 已提交
270
		return NULL;
271
	}
O
Oded Gabbay 已提交
272

273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
	if (device_info->needs_pci_atomics) {
		/* Allow BIF to recode atomics to PCIe 3.0
		 * AtomicOps. 32 and 64-bit requests are possible and
		 * must be supported.
		 */
		if (pci_enable_atomic_ops_to_root(pdev,
				PCI_EXP_DEVCAP2_ATOMIC_COMP32 |
				PCI_EXP_DEVCAP2_ATOMIC_COMP64) < 0) {
			dev_info(kfd_device,
				"skipped device %x:%x, PCI rejects atomics",
				 pdev->vendor, pdev->device);
			return NULL;
		}
	}

O
Oded Gabbay 已提交
288 289 290 291 292 293 294
	kfd = kzalloc(sizeof(*kfd), GFP_KERNEL);
	if (!kfd)
		return NULL;

	kfd->kgd = kgd;
	kfd->device_info = device_info;
	kfd->pdev = pdev;
295
	kfd->init_complete = false;
296 297 298 299 300
	kfd->kfd2kgd = f2g;

	mutex_init(&kfd->doorbell_mutex);
	memset(&kfd->doorbell_available_index, 0,
		sizeof(kfd->doorbell_available_index));
O
Oded Gabbay 已提交
301 302 303 304

	return kfd;
}

305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322
static bool device_iommu_pasid_init(struct kfd_dev *kfd)
{
	const u32 required_iommu_flags = AMD_IOMMU_DEVICE_FLAG_ATS_SUP |
					AMD_IOMMU_DEVICE_FLAG_PRI_SUP |
					AMD_IOMMU_DEVICE_FLAG_PASID_SUP;

	struct amd_iommu_device_info iommu_info;
	unsigned int pasid_limit;
	int err;

	err = amd_iommu_device_info(kfd->pdev, &iommu_info);
	if (err < 0) {
		dev_err(kfd_device,
			"error getting iommu info. is the iommu enabled?\n");
		return false;
	}

	if ((iommu_info.flags & required_iommu_flags) != required_iommu_flags) {
323
		dev_err(kfd_device, "error required iommu flags ats %i, pri %i, pasid %i\n",
324 325
		       (iommu_info.flags & AMD_IOMMU_DEVICE_FLAG_ATS_SUP) != 0,
		       (iommu_info.flags & AMD_IOMMU_DEVICE_FLAG_PRI_SUP) != 0,
326 327
		       (iommu_info.flags & AMD_IOMMU_DEVICE_FLAG_PASID_SUP)
									!= 0);
328 329 330 331
		return false;
	}

	pasid_limit = min_t(unsigned int,
332
			(unsigned int)(1 << kfd->device_info->max_pasid_bits),
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
			iommu_info.max_pasids);

	if (!kfd_set_pasid_limit(pasid_limit)) {
		dev_err(kfd_device, "error setting pasid limit\n");
		return false;
	}

	return true;
}

static void iommu_pasid_shutdown_callback(struct pci_dev *pdev, int pasid)
{
	struct kfd_dev *dev = kfd_device_by_pci_dev(pdev);

	if (dev)
348
		kfd_process_iommu_unbind_callback(dev, pasid);
349 350
}

351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368
/*
 * This function called by IOMMU driver on PPR failure
 */
static int iommu_invalid_ppr_cb(struct pci_dev *pdev, int pasid,
		unsigned long address, u16 flags)
{
	struct kfd_dev *dev;

	dev_warn(kfd_device,
			"Invalid PPR device %x:%x.%x pasid %d address 0x%lX flags 0x%X",
			PCI_BUS_NUM(pdev->devfn),
			PCI_SLOT(pdev->devfn),
			PCI_FUNC(pdev->devfn),
			pasid,
			address,
			flags);

	dev = kfd_device_by_pci_dev(pdev);
369 370
	if (!WARN_ON(!dev))
		kfd_signal_iommu_event(dev, pasid, address,
371 372 373 374 375
			flags & PPR_FAULT_WRITE, flags & PPR_FAULT_EXEC);

	return AMD_IOMMU_INV_PRI_RSP_INVALID;
}

F
Felix Kuehling 已提交
376 377 378 379 380 381 382 383 384 385 386
static void kfd_cwsr_init(struct kfd_dev *kfd)
{
	if (cwsr_enable && kfd->device_info->supports_cwsr) {
		BUILD_BUG_ON(sizeof(cwsr_trap_gfx8_hex) > PAGE_SIZE);

		kfd->cwsr_isa = cwsr_trap_gfx8_hex;
		kfd->cwsr_isa_size = sizeof(cwsr_trap_gfx8_hex);
		kfd->cwsr_enabled = true;
	}
}

O
Oded Gabbay 已提交
387 388 389
bool kgd2kfd_device_init(struct kfd_dev *kfd,
			 const struct kgd2kfd_shared_resources *gpu_resources)
{
390 391
	unsigned int size;

O
Oded Gabbay 已提交
392 393
	kfd->shared_resources = *gpu_resources;

394 395 396 397 398
	kfd->vm_info.first_vmid_kfd = ffs(gpu_resources->compute_vmid_bitmap)-1;
	kfd->vm_info.last_vmid_kfd = fls(gpu_resources->compute_vmid_bitmap)-1;
	kfd->vm_info.vmid_num_kfd = kfd->vm_info.last_vmid_kfd
			- kfd->vm_info.first_vmid_kfd + 1;

399 400 401 402 403 404 405 406 407 408 409
	/* Verify module parameters regarding mapped process number*/
	if ((hws_max_conc_proc < 0)
			|| (hws_max_conc_proc > kfd->vm_info.vmid_num_kfd)) {
		dev_err(kfd_device,
			"hws_max_conc_proc %d must be between 0 and %d, use %d instead\n",
			hws_max_conc_proc, kfd->vm_info.vmid_num_kfd,
			kfd->vm_info.vmid_num_kfd);
		kfd->max_proc_per_quantum = kfd->vm_info.vmid_num_kfd;
	} else
		kfd->max_proc_per_quantum = hws_max_conc_proc;

410
	/* calculate max size of mqds needed for queues */
411 412
	size = max_num_of_queues_per_device *
			kfd->device_info->mqd_size_aligned;
413

414 415 416 417
	/*
	 * calculate max size of runlist packet.
	 * There can be only 2 packets at once
	 */
418 419 420
	size += (KFD_MAX_NUM_OF_PROCESSES * sizeof(struct pm4_mes_map_process) +
		max_num_of_queues_per_device * sizeof(struct pm4_mes_map_queues)
		+ sizeof(struct pm4_mes_runlist)) * 2;
421 422 423 424 425

	/* Add size of HIQ & DIQ */
	size += KFD_KERNEL_QUEUE_SIZE * 2;

	/* add another 512KB for all other allocations on gart (HPD, fences) */
426 427
	size += 512 * 1024;

428 429 430
	if (kfd->kfd2kgd->init_gtt_mem_allocation(
			kfd->kgd, size, &kfd->gtt_mem,
			&kfd->gtt_start_gpu_addr, &kfd->gtt_start_cpu_ptr)){
431
		dev_err(kfd_device, "Could not allocate %d bytes\n", size);
432 433 434
		goto out;
	}

435
	dev_info(kfd_device, "Allocated %d bytes on gart\n", size);
436

437 438
	/* Initialize GTT sa with 512 byte chunk size */
	if (kfd_gtt_sa_init(kfd, size, 512) != 0) {
439
		dev_err(kfd_device, "Error initializing gtt sub-allocator\n");
440 441 442
		goto kfd_gtt_sa_init_error;
	}

443 444 445 446 447
	if (kfd_doorbell_init(kfd)) {
		dev_err(kfd_device,
			"Error initializing doorbell aperture\n");
		goto kfd_doorbell_error;
	}
448

449
	if (kfd_topology_add_device(kfd)) {
450
		dev_err(kfd_device, "Error adding device to topology\n");
451 452 453
		goto kfd_topology_add_device_error;
	}

454
	if (kfd_interrupt_init(kfd)) {
455
		dev_err(kfd_device, "Error initializing interrupts\n");
456 457 458
		goto kfd_interrupt_error;
	}

459 460
	kfd->dqm = device_queue_manager_init(kfd);
	if (!kfd->dqm) {
461
		dev_err(kfd_device, "Error initializing queue manager\n");
462 463 464
		goto device_queue_manager_error;
	}

465
	if (!device_iommu_pasid_init(kfd)) {
466
		dev_err(kfd_device,
467
			"Error initializing iommuv2 for device %x:%x\n",
468
			kfd->pdev->vendor, kfd->pdev->device);
469
		goto device_iommu_pasid_error;
470 471
	}

F
Felix Kuehling 已提交
472 473
	kfd_cwsr_init(kfd);

474 475 476
	if (kfd_resume(kfd))
		goto kfd_resume_error;

477 478
	kfd->dbgmgr = NULL;

O
Oded Gabbay 已提交
479
	kfd->init_complete = true;
480
	dev_info(kfd_device, "added device %x:%x\n", kfd->pdev->vendor,
O
Oded Gabbay 已提交
481 482
		 kfd->pdev->device);

483
	pr_debug("Starting kfd with the following scheduling policy %d\n",
484
		kfd->dqm->sched_policy);
485

486 487
	goto out;

488 489
kfd_resume_error:
device_iommu_pasid_error:
490 491
	device_queue_manager_uninit(kfd->dqm);
device_queue_manager_error:
492 493
	kfd_interrupt_exit(kfd);
kfd_interrupt_error:
494
	kfd_topology_remove_device(kfd);
495
kfd_topology_add_device_error:
496 497
	kfd_doorbell_fini(kfd);
kfd_doorbell_error:
498 499
	kfd_gtt_sa_fini(kfd);
kfd_gtt_sa_init_error:
500
	kfd->kfd2kgd->free_gtt_mem(kfd->kgd, kfd->gtt_mem);
501
	dev_err(kfd_device,
502
		"device %x:%x NOT added due to errors\n",
503 504 505
		kfd->pdev->vendor, kfd->pdev->device);
out:
	return kfd->init_complete;
O
Oded Gabbay 已提交
506 507 508 509
}

void kgd2kfd_device_exit(struct kfd_dev *kfd)
{
510
	if (kfd->init_complete) {
511
		kgd2kfd_suspend(kfd);
512
		device_queue_manager_uninit(kfd->dqm);
513
		kfd_interrupt_exit(kfd);
514
		kfd_topology_remove_device(kfd);
515
		kfd_doorbell_fini(kfd);
516
		kfd_gtt_sa_fini(kfd);
517
		kfd->kfd2kgd->free_gtt_mem(kfd->kgd, kfd->gtt_mem);
518
	}
519

O
Oded Gabbay 已提交
520 521 522 523 524
	kfree(kfd);
}

void kgd2kfd_suspend(struct kfd_dev *kfd)
{
525 526 527 528 529 530 531 532 533 534
	if (!kfd->init_complete)
		return;

	kfd->dqm->ops.stop(kfd->dqm);

	kfd_unbind_processes_from_device(kfd);

	amd_iommu_set_invalidate_ctx_cb(kfd->pdev, NULL);
	amd_iommu_set_invalid_ppr_cb(kfd->pdev, NULL);
	amd_iommu_free_device(kfd->pdev);
O
Oded Gabbay 已提交
535 536 537 538
}

int kgd2kfd_resume(struct kfd_dev *kfd)
{
539 540
	if (!kfd->init_complete)
		return 0;
541

542
	return kfd_resume(kfd);
543

544 545 546 547 548 549
}

static int kfd_resume(struct kfd_dev *kfd)
{
	int err = 0;
	unsigned int pasid_limit = kfd_get_pasid_limit();
550

551 552 553 554 555 556 557 558
	err = amd_iommu_init_device(kfd->pdev, pasid_limit);
	if (err)
		return -ENXIO;
	amd_iommu_set_invalidate_ctx_cb(kfd->pdev,
					iommu_pasid_shutdown_callback);
	amd_iommu_set_invalid_ppr_cb(kfd->pdev,
				     iommu_invalid_ppr_cb);

559 560 561 562
	err = kfd_bind_processes_to_device(kfd);
	if (err)
		goto processes_bind_error;

563 564 565 566 567 568
	err = kfd->dqm->ops.start(kfd->dqm);
	if (err) {
		dev_err(kfd_device,
			"Error starting queue manager for device %x:%x\n",
			kfd->pdev->vendor, kfd->pdev->device);
		goto dqm_start_error;
569 570
	}

571 572 573
	return err;

dqm_start_error:
574
processes_bind_error:
575 576 577
	amd_iommu_free_device(kfd->pdev);

	return err;
O
Oded Gabbay 已提交
578 579
}

580 581
/* This is called directly from KGD at ISR. */
void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry)
O
Oded Gabbay 已提交
582
{
583 584 585 586 587 588 589 590
	if (!kfd->init_complete)
		return;

	spin_lock(&kfd->interrupt_lock);

	if (kfd->interrupts_active
	    && interrupt_is_wanted(kfd, ih_ring_entry)
	    && enqueue_ih_ring_entry(kfd, ih_ring_entry))
591
		queue_work(kfd->ih_wq, &kfd->interrupt_work);
592 593

	spin_unlock(&kfd->interrupt_lock);
O
Oded Gabbay 已提交
594
}
595 596 597 598

static int kfd_gtt_sa_init(struct kfd_dev *kfd, unsigned int buf_size,
				unsigned int chunk_size)
{
599
	unsigned int num_of_longs;
600

601 602 603 604 605 606
	if (WARN_ON(buf_size < chunk_size))
		return -EINVAL;
	if (WARN_ON(buf_size == 0))
		return -EINVAL;
	if (WARN_ON(chunk_size == 0))
		return -EINVAL;
607 608 609 610

	kfd->gtt_sa_chunk_size = chunk_size;
	kfd->gtt_sa_num_of_chunks = buf_size / chunk_size;

611 612
	num_of_longs = (kfd->gtt_sa_num_of_chunks + BITS_PER_LONG - 1) /
		BITS_PER_LONG;
613

614
	kfd->gtt_sa_bitmap = kcalloc(num_of_longs, sizeof(long), GFP_KERNEL);
615 616 617 618

	if (!kfd->gtt_sa_bitmap)
		return -ENOMEM;

619
	pr_debug("gtt_sa_num_of_chunks = %d, gtt_sa_bitmap = %p\n",
620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662
			kfd->gtt_sa_num_of_chunks, kfd->gtt_sa_bitmap);

	mutex_init(&kfd->gtt_sa_lock);

	return 0;

}

static void kfd_gtt_sa_fini(struct kfd_dev *kfd)
{
	mutex_destroy(&kfd->gtt_sa_lock);
	kfree(kfd->gtt_sa_bitmap);
}

static inline uint64_t kfd_gtt_sa_calc_gpu_addr(uint64_t start_addr,
						unsigned int bit_num,
						unsigned int chunk_size)
{
	return start_addr + bit_num * chunk_size;
}

static inline uint32_t *kfd_gtt_sa_calc_cpu_addr(void *start_addr,
						unsigned int bit_num,
						unsigned int chunk_size)
{
	return (uint32_t *) ((uint64_t) start_addr + bit_num * chunk_size);
}

int kfd_gtt_sa_allocate(struct kfd_dev *kfd, unsigned int size,
			struct kfd_mem_obj **mem_obj)
{
	unsigned int found, start_search, cur_size;

	if (size == 0)
		return -EINVAL;

	if (size > kfd->gtt_sa_num_of_chunks * kfd->gtt_sa_chunk_size)
		return -ENOMEM;

	*mem_obj = kmalloc(sizeof(struct kfd_mem_obj), GFP_KERNEL);
	if ((*mem_obj) == NULL)
		return -ENOMEM;

663
	pr_debug("Allocated mem_obj = %p for size = %d\n", *mem_obj, size);
664 665 666 667 668 669 670 671 672 673 674

	start_search = 0;

	mutex_lock(&kfd->gtt_sa_lock);

kfd_gtt_restart_search:
	/* Find the first chunk that is free */
	found = find_next_zero_bit(kfd->gtt_sa_bitmap,
					kfd->gtt_sa_num_of_chunks,
					start_search);

675
	pr_debug("Found = %d\n", found);
676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692

	/* If there wasn't any free chunk, bail out */
	if (found == kfd->gtt_sa_num_of_chunks)
		goto kfd_gtt_no_free_chunk;

	/* Update fields of mem_obj */
	(*mem_obj)->range_start = found;
	(*mem_obj)->range_end = found;
	(*mem_obj)->gpu_addr = kfd_gtt_sa_calc_gpu_addr(
					kfd->gtt_start_gpu_addr,
					found,
					kfd->gtt_sa_chunk_size);
	(*mem_obj)->cpu_ptr = kfd_gtt_sa_calc_cpu_addr(
					kfd->gtt_start_cpu_ptr,
					found,
					kfd->gtt_sa_chunk_size);

693
	pr_debug("gpu_addr = %p, cpu_addr = %p\n",
694 695 696 697
			(uint64_t *) (*mem_obj)->gpu_addr, (*mem_obj)->cpu_ptr);

	/* If we need only one chunk, mark it as allocated and get out */
	if (size <= kfd->gtt_sa_chunk_size) {
698
		pr_debug("Single bit\n");
699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732
		set_bit(found, kfd->gtt_sa_bitmap);
		goto kfd_gtt_out;
	}

	/* Otherwise, try to see if we have enough contiguous chunks */
	cur_size = size - kfd->gtt_sa_chunk_size;
	do {
		(*mem_obj)->range_end =
			find_next_zero_bit(kfd->gtt_sa_bitmap,
					kfd->gtt_sa_num_of_chunks, ++found);
		/*
		 * If next free chunk is not contiguous than we need to
		 * restart our search from the last free chunk we found (which
		 * wasn't contiguous to the previous ones
		 */
		if ((*mem_obj)->range_end != found) {
			start_search = found;
			goto kfd_gtt_restart_search;
		}

		/*
		 * If we reached end of buffer, bail out with error
		 */
		if (found == kfd->gtt_sa_num_of_chunks)
			goto kfd_gtt_no_free_chunk;

		/* Check if we don't need another chunk */
		if (cur_size <= kfd->gtt_sa_chunk_size)
			cur_size = 0;
		else
			cur_size -= kfd->gtt_sa_chunk_size;

	} while (cur_size > 0);

733
	pr_debug("range_start = %d, range_end = %d\n",
734 735 736 737 738 739 740 741 742 743 744 745 746
		(*mem_obj)->range_start, (*mem_obj)->range_end);

	/* Mark the chunks as allocated */
	for (found = (*mem_obj)->range_start;
		found <= (*mem_obj)->range_end;
		found++)
		set_bit(found, kfd->gtt_sa_bitmap);

kfd_gtt_out:
	mutex_unlock(&kfd->gtt_sa_lock);
	return 0;

kfd_gtt_no_free_chunk:
747
	pr_debug("Allocation failed with mem_obj = %p\n", mem_obj);
748 749 750 751 752 753 754 755 756
	mutex_unlock(&kfd->gtt_sa_lock);
	kfree(mem_obj);
	return -ENOMEM;
}

int kfd_gtt_sa_free(struct kfd_dev *kfd, struct kfd_mem_obj *mem_obj)
{
	unsigned int bit;

757 758 759
	/* Act like kfree when trying to free a NULL object */
	if (!mem_obj)
		return 0;
760

761
	pr_debug("Free mem_obj = %p, range_start = %d, range_end = %d\n",
762 763 764 765 766 767 768 769 770 771 772 773 774 775 776
			mem_obj, mem_obj->range_start, mem_obj->range_end);

	mutex_lock(&kfd->gtt_sa_lock);

	/* Mark the chunks as free */
	for (bit = mem_obj->range_start;
		bit <= mem_obj->range_end;
		bit++)
		clear_bit(bit, kfd->gtt_sa_bitmap);

	mutex_unlock(&kfd->gtt_sa_lock);

	kfree(mem_obj);
	return 0;
}