Project

General

Profile

Submit #2883 ยป dma_4gb.patch

xenu, 01/17/2016 06:54 AM

View differences:

sys/platform/pc64/x86_64/busdma_machdep.c
87 87

  
88 88
#define BUS_DMA_COULD_BOUNCE	(BUS_DMA_BOUNCE_LOWADDR | BUS_DMA_BOUNCE_ALIGN)
89 89

  
90
#define BUS_DMAMEM_KMALLOC(dmat) \
91
	((dmat)->maxsize <= PAGE_SIZE && \
92
	 (dmat)->alignment <= PAGE_SIZE && \
93
	 (dmat)->lowaddr >= ptoa(Maxmem))
94

  
95 90
struct bounce_page {
96 91
	vm_offset_t	vaddr;		/* kva of bounce buffer */
97 92
	bus_addr_t	busaddr;	/* Physical address */
......
484 479
	return (0);
485 480
}
486 481

  
487
static __inline bus_size_t
488
check_kmalloc(bus_dma_tag_t dmat, const void *vaddr0, int verify)
489
{
490
	bus_size_t maxsize = 0;
491
	uintptr_t vaddr = (uintptr_t)vaddr0;
492

  
493
	if ((vaddr ^ (vaddr + dmat->maxsize - 1)) & ~PAGE_MASK) {
494
		if (verify)
495
			panic("boundary check failed\n");
496
		if (bootverbose)
497
			kprintf("boundary check failed\n");
498
		maxsize = dmat->maxsize;
499
	}
500
	if (vaddr & (dmat->alignment - 1)) {
501
		if (verify)
502
			panic("alignment check failed\n");
503
		if (bootverbose)
504
			kprintf("alignment check failed\n");
505
		if (dmat->maxsize < dmat->alignment)
506
			maxsize = dmat->alignment;
507
		else
508
			maxsize = dmat->maxsize;
509
	}
510
	return maxsize;
511
}
512

  
513 482
/*
514 483
 * Allocate a piece of memory that can be efficiently mapped into
515 484
 * bus device space based on the constraints lited in the dma tag.
......
544 513
	else
545 514
		attr = VM_MEMATTR_DEFAULT;
546 515

  
547
	/* XXX must alloc with correct mem attribute here */
548
	if (BUS_DMAMEM_KMALLOC(dmat)) {
549
		bus_size_t maxsize;
550

  
551
		*vaddr = kmalloc(dmat->maxsize, M_DEVBUF, mflags);
516
	/*
517
	 * XXX must alloc with correct mem attribute here.
518
	 * Until we get proper IOMMU support, we have to keep buffer in first 4GB.
519
	 */
520
	*vaddr = contigmalloc(dmat->maxsize, M_DEVBUF, mflags,
521
	    0ul, 0xfffffffful, dmat->alignment, dmat->boundary);
552 522

  
553
		/*
554
		 * XXX
555
		 * Check whether the allocation
556
		 * - crossed a page boundary
557
		 * - was not aligned
558
		 * Retry with power-of-2 alignment in the above cases.
559
		 */
560
		maxsize = check_kmalloc(dmat, *vaddr, 0);
561
		if (maxsize) {
562
			kfree(*vaddr, M_DEVBUF);
563
			*vaddr = kmalloc(maxsize, M_DEVBUF,
564
			    mflags | M_POWEROF2);
565
			check_kmalloc(dmat, *vaddr, 1);
566
		}
567
	} else {
568
		/*
569
		 * XXX Use Contigmalloc until it is merged into this facility
570
		 *     and handles multi-seg allocations.  Nobody is doing
571
		 *     multi-seg allocations yet though.
572
		 */
573
		*vaddr = contigmalloc(dmat->maxsize, M_DEVBUF, mflags,
574
		    0ul, dmat->lowaddr, dmat->alignment, dmat->boundary);
575
	}
576 523
	if (*vaddr == NULL)
577 524
		return (ENOMEM);
578 525

  
......
583 530

  
584 531
/*
585 532
 * Free a piece of memory and it's allociated dmamap, that was allocated
586
 * via bus_dmamem_alloc.  Make the same choice for free/contigfree.
533
 * via bus_dmamem_alloc.
587 534
 */
588 535
void
589 536
bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map)
......
594 541
	 */
595 542
	if (map != NULL)
596 543
		panic("bus_dmamem_free: Invalid map freed");
597
	if (BUS_DMAMEM_KMALLOC(dmat))
598
		kfree(vaddr, M_DEVBUF);
599
	else
600
		contigfree(vaddr, dmat->maxsize, M_DEVBUF);
544

  
545
	contigfree(vaddr, dmat->maxsize, M_DEVBUF);
601 546
}
602 547

  
603 548
static __inline vm_paddr_t
    (1-1/1)