diff options
author | Ralph Campbell <ralph.campbell@qlogic.com> | 2006-12-12 17:28:28 -0500 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2006-12-12 17:28:28 -0500 |
commit | f2cbb660ed37294e3eeb98c045de6890079ccb01 (patch) | |
tree | 860d7fcf838dd0937d59a420f2018ee6f2f9935e /drivers/infiniband/hw | |
parent | 9b513090a3c5e4964f9ac09016c1586988abb3d5 (diff) |
IB/ipath: Implement new verbs DMA mapping functions
This patch implements the interposing DMA mapping functions to allow
support for IOMMUs and remove the dependence on phys_to_virt() and
bus_to_virt().
Signed-off-by: Ralph Campbell <ralph.campbell@qlogic.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw')
-rw-r--r-- | drivers/infiniband/hw/ipath/Makefile | 1 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_dma.c | 189 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_keys.c | 8 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_mr.c | 7 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_verbs.c | 1 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_verbs.h | 2 |
6 files changed, 201 insertions, 7 deletions
diff --git a/drivers/infiniband/hw/ipath/Makefile b/drivers/infiniband/hw/ipath/Makefile index 7dc10551cf18..ec2e603ea241 100644 --- a/drivers/infiniband/hw/ipath/Makefile +++ b/drivers/infiniband/hw/ipath/Makefile | |||
@@ -6,6 +6,7 @@ obj-$(CONFIG_INFINIBAND_IPATH) += ib_ipath.o | |||
6 | ib_ipath-y := \ | 6 | ib_ipath-y := \ |
7 | ipath_cq.o \ | 7 | ipath_cq.o \ |
8 | ipath_diag.o \ | 8 | ipath_diag.o \ |
9 | ipath_dma.o \ | ||
9 | ipath_driver.o \ | 10 | ipath_driver.o \ |
10 | ipath_eeprom.o \ | 11 | ipath_eeprom.o \ |
11 | ipath_file_ops.o \ | 12 | ipath_file_ops.o \ |
diff --git a/drivers/infiniband/hw/ipath/ipath_dma.c b/drivers/infiniband/hw/ipath/ipath_dma.c new file mode 100644 index 000000000000..6e0f2b8918ce --- /dev/null +++ b/drivers/infiniband/hw/ipath/ipath_dma.c | |||
@@ -0,0 +1,189 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2006 QLogic, Corporation. All rights reserved. | ||
3 | * | ||
4 | * This software is available to you under a choice of one of two | ||
5 | * licenses. You may choose to be licensed under the terms of the GNU | ||
6 | * General Public License (GPL) Version 2, available from the file | ||
7 | * COPYING in the main directory of this source tree, or the | ||
8 | * OpenIB.org BSD license below: | ||
9 | * | ||
10 | * Redistribution and use in source and binary forms, with or | ||
11 | * without modification, are permitted provided that the following | ||
12 | * conditions are met: | ||
13 | * | ||
14 | * - Redistributions of source code must retain the above | ||
15 | * copyright notice, this list of conditions and the following | ||
16 | * disclaimer. | ||
17 | * | ||
18 | * - Redistributions in binary form must reproduce the above | ||
19 | * copyright notice, this list of conditions and the following | ||
20 | * disclaimer in the documentation and/or other materials | ||
21 | * provided with the distribution. | ||
22 | * | ||
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
24 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
25 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
26 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
27 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
28 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
29 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
30 | * SOFTWARE. | ||
31 | */ | ||
32 | |||
33 | #include <rdma/ib_verbs.h> | ||
34 | |||
35 | #include "ipath_verbs.h" | ||
36 | |||
37 | #define BAD_DMA_ADDRESS ((u64) 0) | ||
38 | |||
39 | /* | ||
40 | * The following functions implement driver specific replacements | ||
41 | * for the ib_dma_*() functions. | ||
42 | * | ||
43 | * These functions return kernel virtual addresses instead of | ||
44 | * device bus addresses since the driver uses the CPU to copy | ||
45 | * data instead of using hardware DMA. | ||
46 | */ | ||
47 | |||
48 | static int ipath_mapping_error(struct ib_device *dev, u64 dma_addr) | ||
49 | { | ||
50 | return dma_addr == BAD_DMA_ADDRESS; | ||
51 | } | ||
52 | |||
53 | static u64 ipath_dma_map_single(struct ib_device *dev, | ||
54 | void *cpu_addr, size_t size, | ||
55 | enum dma_data_direction direction) | ||
56 | { | ||
57 | BUG_ON(!valid_dma_direction(direction)); | ||
58 | return (u64) cpu_addr; | ||
59 | } | ||
60 | |||
61 | static void ipath_dma_unmap_single(struct ib_device *dev, | ||
62 | u64 addr, size_t size, | ||
63 | enum dma_data_direction direction) | ||
64 | { | ||
65 | BUG_ON(!valid_dma_direction(direction)); | ||
66 | } | ||
67 | |||
68 | static u64 ipath_dma_map_page(struct ib_device *dev, | ||
69 | struct page *page, | ||
70 | unsigned long offset, | ||
71 | size_t size, | ||
72 | enum dma_data_direction direction) | ||
73 | { | ||
74 | u64 addr; | ||
75 | |||
76 | BUG_ON(!valid_dma_direction(direction)); | ||
77 | |||
78 | if (offset + size > PAGE_SIZE) { | ||
79 | addr = BAD_DMA_ADDRESS; | ||
80 | goto done; | ||
81 | } | ||
82 | |||
83 | addr = (u64) page_address(page); | ||
84 | if (addr) | ||
85 | addr += offset; | ||
86 | /* TODO: handle highmem pages */ | ||
87 | |||
88 | done: | ||
89 | return addr; | ||
90 | } | ||
91 | |||
92 | static void ipath_dma_unmap_page(struct ib_device *dev, | ||
93 | u64 addr, size_t size, | ||
94 | enum dma_data_direction direction) | ||
95 | { | ||
96 | BUG_ON(!valid_dma_direction(direction)); | ||
97 | } | ||
98 | |||
99 | int ipath_map_sg(struct ib_device *dev, struct scatterlist *sg, int nents, | ||
100 | enum dma_data_direction direction) | ||
101 | { | ||
102 | u64 addr; | ||
103 | int i; | ||
104 | int ret = nents; | ||
105 | |||
106 | BUG_ON(!valid_dma_direction(direction)); | ||
107 | |||
108 | for (i = 0; i < nents; i++) { | ||
109 | addr = (u64) page_address(sg[i].page); | ||
110 | /* TODO: handle highmem pages */ | ||
111 | if (!addr) { | ||
112 | ret = 0; | ||
113 | break; | ||
114 | } | ||
115 | } | ||
116 | return ret; | ||
117 | } | ||
118 | |||
119 | static void ipath_unmap_sg(struct ib_device *dev, | ||
120 | struct scatterlist *sg, int nents, | ||
121 | enum dma_data_direction direction) | ||
122 | { | ||
123 | BUG_ON(!valid_dma_direction(direction)); | ||
124 | } | ||
125 | |||
126 | static u64 ipath_sg_dma_address(struct ib_device *dev, struct scatterlist *sg) | ||
127 | { | ||
128 | u64 addr = (u64) page_address(sg->page); | ||
129 | |||
130 | if (addr) | ||
131 | addr += sg->offset; | ||
132 | return addr; | ||
133 | } | ||
134 | |||
135 | static unsigned int ipath_sg_dma_len(struct ib_device *dev, | ||
136 | struct scatterlist *sg) | ||
137 | { | ||
138 | return sg->length; | ||
139 | } | ||
140 | |||
141 | static void ipath_sync_single_for_cpu(struct ib_device *dev, | ||
142 | u64 addr, | ||
143 | size_t size, | ||
144 | enum dma_data_direction dir) | ||
145 | { | ||
146 | } | ||
147 | |||
148 | static void ipath_sync_single_for_device(struct ib_device *dev, | ||
149 | u64 addr, | ||
150 | size_t size, | ||
151 | enum dma_data_direction dir) | ||
152 | { | ||
153 | } | ||
154 | |||
155 | static void *ipath_dma_alloc_coherent(struct ib_device *dev, size_t size, | ||
156 | u64 *dma_handle, gfp_t flag) | ||
157 | { | ||
158 | struct page *p; | ||
159 | void *addr = NULL; | ||
160 | |||
161 | p = alloc_pages(flag, get_order(size)); | ||
162 | if (p) | ||
163 | addr = page_address(p); | ||
164 | if (dma_handle) | ||
165 | *dma_handle = (u64) addr; | ||
166 | return addr; | ||
167 | } | ||
168 | |||
169 | static void ipath_dma_free_coherent(struct ib_device *dev, size_t size, | ||
170 | void *cpu_addr, dma_addr_t dma_handle) | ||
171 | { | ||
172 | free_pages((unsigned long) cpu_addr, get_order(size)); | ||
173 | } | ||
174 | |||
175 | struct ib_dma_mapping_ops ipath_dma_mapping_ops = { | ||
176 | ipath_mapping_error, | ||
177 | ipath_dma_map_single, | ||
178 | ipath_dma_unmap_single, | ||
179 | ipath_dma_map_page, | ||
180 | ipath_dma_unmap_page, | ||
181 | ipath_map_sg, | ||
182 | ipath_unmap_sg, | ||
183 | ipath_sg_dma_address, | ||
184 | ipath_sg_dma_len, | ||
185 | ipath_sync_single_for_cpu, | ||
186 | ipath_sync_single_for_device, | ||
187 | ipath_dma_alloc_coherent, | ||
188 | ipath_dma_free_coherent | ||
189 | }; | ||
diff --git a/drivers/infiniband/hw/ipath/ipath_keys.c b/drivers/infiniband/hw/ipath/ipath_keys.c index 9a6cbd05adcd..851763d7d2db 100644 --- a/drivers/infiniband/hw/ipath/ipath_keys.c +++ b/drivers/infiniband/hw/ipath/ipath_keys.c | |||
@@ -134,7 +134,7 @@ int ipath_lkey_ok(struct ipath_qp *qp, struct ipath_sge *isge, | |||
134 | */ | 134 | */ |
135 | if (sge->lkey == 0) { | 135 | if (sge->lkey == 0) { |
136 | isge->mr = NULL; | 136 | isge->mr = NULL; |
137 | isge->vaddr = bus_to_virt(sge->addr); | 137 | isge->vaddr = (void *) sge->addr; |
138 | isge->length = sge->length; | 138 | isge->length = sge->length; |
139 | isge->sge_length = sge->length; | 139 | isge->sge_length = sge->length; |
140 | ret = 1; | 140 | ret = 1; |
@@ -202,12 +202,12 @@ int ipath_rkey_ok(struct ipath_qp *qp, struct ipath_sge_state *ss, | |||
202 | int ret; | 202 | int ret; |
203 | 203 | ||
204 | /* | 204 | /* |
205 | * We use RKEY == zero for physical addresses | 205 | * We use RKEY == zero for kernel virtual addresses |
206 | * (see ipath_get_dma_mr). | 206 | * (see ipath_get_dma_mr and ipath_dma.c). |
207 | */ | 207 | */ |
208 | if (rkey == 0) { | 208 | if (rkey == 0) { |
209 | sge->mr = NULL; | 209 | sge->mr = NULL; |
210 | sge->vaddr = phys_to_virt(vaddr); | 210 | sge->vaddr = (void *) vaddr; |
211 | sge->length = len; | 211 | sge->length = len; |
212 | sge->sge_length = len; | 212 | sge->sge_length = len; |
213 | ss->sg_list = NULL; | 213 | ss->sg_list = NULL; |
diff --git a/drivers/infiniband/hw/ipath/ipath_mr.c b/drivers/infiniband/hw/ipath/ipath_mr.c index a0673c1eef71..8cc8598d6c69 100644 --- a/drivers/infiniband/hw/ipath/ipath_mr.c +++ b/drivers/infiniband/hw/ipath/ipath_mr.c | |||
@@ -54,6 +54,8 @@ static inline struct ipath_fmr *to_ifmr(struct ib_fmr *ibfmr) | |||
54 | * @acc: access flags | 54 | * @acc: access flags |
55 | * | 55 | * |
56 | * Returns the memory region on success, otherwise returns an errno. | 56 | * Returns the memory region on success, otherwise returns an errno. |
57 | * Note that all DMA addresses should be created via the | ||
58 | * struct ib_dma_mapping_ops functions (see ipath_dma.c). | ||
57 | */ | 59 | */ |
58 | struct ib_mr *ipath_get_dma_mr(struct ib_pd *pd, int acc) | 60 | struct ib_mr *ipath_get_dma_mr(struct ib_pd *pd, int acc) |
59 | { | 61 | { |
@@ -149,8 +151,7 @@ struct ib_mr *ipath_reg_phys_mr(struct ib_pd *pd, | |||
149 | m = 0; | 151 | m = 0; |
150 | n = 0; | 152 | n = 0; |
151 | for (i = 0; i < num_phys_buf; i++) { | 153 | for (i = 0; i < num_phys_buf; i++) { |
152 | mr->mr.map[m]->segs[n].vaddr = | 154 | mr->mr.map[m]->segs[n].vaddr = (void *) buffer_list[i].addr; |
153 | phys_to_virt(buffer_list[i].addr); | ||
154 | mr->mr.map[m]->segs[n].length = buffer_list[i].size; | 155 | mr->mr.map[m]->segs[n].length = buffer_list[i].size; |
155 | mr->mr.length += buffer_list[i].size; | 156 | mr->mr.length += buffer_list[i].size; |
156 | n++; | 157 | n++; |
@@ -347,7 +348,7 @@ int ipath_map_phys_fmr(struct ib_fmr *ibfmr, u64 * page_list, | |||
347 | n = 0; | 348 | n = 0; |
348 | ps = 1 << fmr->page_shift; | 349 | ps = 1 << fmr->page_shift; |
349 | for (i = 0; i < list_len; i++) { | 350 | for (i = 0; i < list_len; i++) { |
350 | fmr->mr.map[m]->segs[n].vaddr = phys_to_virt(page_list[i]); | 351 | fmr->mr.map[m]->segs[n].vaddr = (void *) page_list[i]; |
351 | fmr->mr.map[m]->segs[n].length = ps; | 352 | fmr->mr.map[m]->segs[n].length = ps; |
352 | if (++n == IPATH_SEGSZ) { | 353 | if (++n == IPATH_SEGSZ) { |
353 | m++; | 354 | m++; |
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c index acdee33ee1f8..2aaacdb7e52a 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs.c +++ b/drivers/infiniband/hw/ipath/ipath_verbs.c | |||
@@ -1599,6 +1599,7 @@ int ipath_register_ib_device(struct ipath_devdata *dd) | |||
1599 | dev->detach_mcast = ipath_multicast_detach; | 1599 | dev->detach_mcast = ipath_multicast_detach; |
1600 | dev->process_mad = ipath_process_mad; | 1600 | dev->process_mad = ipath_process_mad; |
1601 | dev->mmap = ipath_mmap; | 1601 | dev->mmap = ipath_mmap; |
1602 | dev->dma_ops = &ipath_dma_mapping_ops; | ||
1602 | 1603 | ||
1603 | snprintf(dev->node_desc, sizeof(dev->node_desc), | 1604 | snprintf(dev->node_desc, sizeof(dev->node_desc), |
1604 | IPATH_IDSTR " %s", init_utsname()->nodename); | 1605 | IPATH_IDSTR " %s", init_utsname()->nodename); |
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.h b/drivers/infiniband/hw/ipath/ipath_verbs.h index 8039f6e5f0c8..c0c8d5b24a7d 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs.h +++ b/drivers/infiniband/hw/ipath/ipath_verbs.h | |||
@@ -812,4 +812,6 @@ extern unsigned int ib_ipath_max_srq_wrs; | |||
812 | 812 | ||
813 | extern const u32 ib_ipath_rnr_table[]; | 813 | extern const u32 ib_ipath_rnr_table[]; |
814 | 814 | ||
815 | extern struct ib_dma_mapping_ops ipath_dma_mapping_ops; | ||
816 | |||
815 | #endif /* IPATH_VERBS_H */ | 817 | #endif /* IPATH_VERBS_H */ |