Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pci-dma.c
Go to the documentation of this file.
1 /*
2  * arch/xtensa/kernel/pci-dma.c
3  *
4  * DMA coherent memory allocation.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the
8  * Free Software Foundation; either version 2 of the License, or (at your
9  * option) any later version.
10  *
11  * Copyright (C) 2002 - 2005 Tensilica Inc.
12  *
13  * Based on version for i386.
14  *
15  * Chris Zankel <[email protected]>
17  */
18 
19 #include <linux/types.h>
20 #include <linux/mm.h>
21 #include <linux/string.h>
22 #include <linux/pci.h>
23 #include <linux/gfp.h>
24 #include <linux/module.h>
25 #include <asm/io.h>
26 #include <asm/cacheflush.h>
27 
28 /*
29  * Note: We assume that the full memory space is always mapped to 'kseg'
30  * Otherwise we have to use page attributes (not implemented).
31  */
32 
33 void *
35 {
36  unsigned long ret;
37  unsigned long uncached = 0;
38 
39  /* ignore region speicifiers */
40 
41  flag &= ~(__GFP_DMA | __GFP_HIGHMEM);
42 
43  if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
44  flag |= GFP_DMA;
45  ret = (unsigned long)__get_free_pages(flag, get_order(size));
46 
47  if (ret == 0)
48  return NULL;
49 
50  /* We currently don't support coherent memory outside KSEG */
51 
52  if (ret < XCHAL_KSEG_CACHED_VADDR
54  BUG();
55 
56 
57  if (ret != 0) {
58  memset((void*) ret, 0, size);
60  *handle = virt_to_bus((void*)ret);
61  __flush_invalidate_dcache_range(ret, size);
62  }
63 
64  return (void*)uncached;
65 }
67 
68 void dma_free_coherent(struct device *hwdev, size_t size,
70 {
72 
73  if (addr < 0 || addr >= XCHAL_KSEG_SIZE)
74  BUG();
75 
76  free_pages(addr, get_order(size));
77 }
79 
80 
81 void consistent_sync(void *vaddr, size_t size, int direction)
82 {
83  switch (direction) {
84  case PCI_DMA_NONE:
85  BUG();
86  case PCI_DMA_FROMDEVICE: /* invalidate only */
87  __invalidate_dcache_range((unsigned long)vaddr,
88  (unsigned long)size);
89  break;
90 
91  case PCI_DMA_TODEVICE: /* writeback only */
92  case PCI_DMA_BIDIRECTIONAL: /* writeback and invalidate */
93  __flush_invalidate_dcache_range((unsigned long)vaddr,
94  (unsigned long)size);
95  break;
96  }
97 }