PageRenderTime 24ms CodeModel.GetById 13ms app.highlight 7ms RepoModel.GetById 1ms app.codeStats 1ms

/arch/ppc64/kernel/pci_iommu.c

https://bitbucket.org/evzijst/gittest
C | 139 lines | 81 code | 19 blank | 39 comment | 2 complexity | 4a4a96aa2f5e2da4677daf7efa189c5d MD5 | raw file
  1/*
  2 * arch/ppc64/kernel/pci_iommu.c
  3 * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
  4 * 
  5 * Rewrite, cleanup, new allocation schemes: 
  6 * Copyright (C) 2004 Olof Johansson, IBM Corporation
  7 *
  8 * Dynamic DMA mapping support, platform-independent parts.
  9 *
 10 * This program is free software; you can redistribute it and/or modify
 11 * it under the terms of the GNU General Public License as published by
 12 * the Free Software Foundation; either version 2 of the License, or
 13 * (at your option) any later version.
 14 * 
 15 * This program is distributed in the hope that it will be useful,
 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 18 * GNU General Public License for more details.
 19 * 
 20 * You should have received a copy of the GNU General Public License
 21 * along with this program; if not, write to the Free Software
 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 23 */
 24
 25
 26#include <linux/config.h>
 27#include <linux/init.h>
 28#include <linux/types.h>
 29#include <linux/slab.h>
 30#include <linux/mm.h>
 31#include <linux/spinlock.h>
 32#include <linux/string.h>
 33#include <linux/pci.h>
 34#include <linux/dma-mapping.h>
 35#include <asm/io.h>
 36#include <asm/prom.h>
 37#include <asm/iommu.h>
 38#include <asm/pci-bridge.h>
 39#include <asm/machdep.h>
 40#include "pci.h"
 41
 42#ifdef CONFIG_PPC_ISERIES
 43#include <asm/iSeries/iSeries_pci.h>
 44#endif /* CONFIG_PPC_ISERIES */
 45
 46/*
 47 * We can use ->sysdata directly and avoid the extra work in
 48 * pci_device_to_OF_node since ->sysdata will have been initialised
 49 * in the iommu init code for all devices.
 50 */
 51#define PCI_GET_DN(dev) ((struct device_node *)((dev)->sysdata))
 52
 53static inline struct iommu_table *devnode_table(struct device *dev)
 54{
 55	struct pci_dev *pdev;
 56
 57	if (!dev) {
 58		pdev = ppc64_isabridge_dev;
 59		if (!pdev)
 60			return NULL;
 61	} else
 62		pdev = to_pci_dev(dev);
 63
 64#ifdef CONFIG_PPC_ISERIES
 65	return ISERIES_DEVNODE(pdev)->iommu_table;
 66#endif /* CONFIG_PPC_ISERIES */
 67
 68#ifdef CONFIG_PPC_MULTIPLATFORM
 69	return PCI_GET_DN(pdev)->iommu_table;
 70#endif /* CONFIG_PPC_MULTIPLATFORM */
 71}
 72
 73
 74/* Allocates a contiguous real buffer and creates mappings over it.
 75 * Returns the virtual address of the buffer and sets dma_handle
 76 * to the dma address (mapping) of the first page.
 77 */
 78static void *pci_iommu_alloc_coherent(struct device *hwdev, size_t size,
 79			   dma_addr_t *dma_handle, unsigned int __nocast flag)
 80{
 81	return iommu_alloc_coherent(devnode_table(hwdev), size, dma_handle,
 82			flag);
 83}
 84
 85static void pci_iommu_free_coherent(struct device *hwdev, size_t size,
 86			 void *vaddr, dma_addr_t dma_handle)
 87{
 88	iommu_free_coherent(devnode_table(hwdev), size, vaddr, dma_handle);
 89}
 90
 91/* Creates TCEs for a user provided buffer.  The user buffer must be 
 92 * contiguous real kernel storage (not vmalloc).  The address of the buffer
 93 * passed here is the kernel (virtual) address of the buffer.  The buffer
 94 * need not be page aligned, the dma_addr_t returned will point to the same
 95 * byte within the page as vaddr.
 96 */
 97static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr,
 98		size_t size, enum dma_data_direction direction)
 99{
100	return iommu_map_single(devnode_table(hwdev), vaddr, size, direction);
101}
102
103
104static void pci_iommu_unmap_single(struct device *hwdev, dma_addr_t dma_handle,
105		size_t size, enum dma_data_direction direction)
106{
107	iommu_unmap_single(devnode_table(hwdev), dma_handle, size, direction);
108}
109
110
111static int pci_iommu_map_sg(struct device *pdev, struct scatterlist *sglist,
112		int nelems, enum dma_data_direction direction)
113{
114	return iommu_map_sg(pdev, devnode_table(pdev), sglist,
115			nelems, direction);
116}
117
118static void pci_iommu_unmap_sg(struct device *pdev, struct scatterlist *sglist,
119		int nelems, enum dma_data_direction direction)
120{
121	iommu_unmap_sg(devnode_table(pdev), sglist, nelems, direction);
122}
123
124/* We support DMA to/from any memory page via the iommu */
125static int pci_iommu_dma_supported(struct device *dev, u64 mask)
126{
127	return 1;
128}
129
130void pci_iommu_init(void)
131{
132	pci_dma_ops.alloc_coherent = pci_iommu_alloc_coherent;
133	pci_dma_ops.free_coherent = pci_iommu_free_coherent;
134	pci_dma_ops.map_single = pci_iommu_map_single;
135	pci_dma_ops.unmap_single = pci_iommu_unmap_single;
136	pci_dma_ops.map_sg = pci_iommu_map_sg;
137	pci_dma_ops.unmap_sg = pci_iommu_unmap_sg;
138	pci_dma_ops.dma_supported = pci_iommu_dma_supported;
139}