diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2013-06-26 08:49:44 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2013-09-17 10:32:37 -0400 |
commit | 4aa806b771d16b810771d86ce23c4c3160888db3 (patch) | |
tree | 5450d1495c1ffbb6d852df44002b95de275deb3f | |
parent | 272b98c6455f00884f0350f775c5342358ebb73f (diff) |
DMA-API: provide a helper to set both DMA and coherent DMA masks
Provide a helper to set both the DMA and coherent DMA masks to the
same value - this avoids duplicated code in a number of drivers,
sometimes with buggy error handling, and also allows us identify
which drivers do things differently.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r-- | Documentation/DMA-API-HOWTO.txt | 37 | ||||
-rw-r--r-- | Documentation/DMA-API.txt | 8 | ||||
-rw-r--r-- | include/linux/dma-mapping.h | 14 |
3 files changed, 44 insertions, 15 deletions
diff --git a/Documentation/DMA-API-HOWTO.txt b/Documentation/DMA-API-HOWTO.txt index 14129f149a75..5e983031cc11 100644 --- a/Documentation/DMA-API-HOWTO.txt +++ b/Documentation/DMA-API-HOWTO.txt | |||
@@ -101,14 +101,23 @@ style to do this even if your device holds the default setting, | |||
101 | because this shows that you did think about these issues wrt. your | 101 | because this shows that you did think about these issues wrt. your |
102 | device. | 102 | device. |
103 | 103 | ||
104 | The query is performed via a call to dma_set_mask(): | 104 | The query is performed via a call to dma_set_mask_and_coherent(): |
105 | 105 | ||
106 | int dma_set_mask(struct device *dev, u64 mask); | 106 | int dma_set_mask_and_coherent(struct device *dev, u64 mask); |
107 | 107 | ||
108 | The query for consistent allocations is performed via a call to | 108 | which will query the mask for both streaming and coherent APIs together. |
109 | dma_set_coherent_mask(): | 109 | If you have some special requirements, then the following two separate |
110 | queries can be used instead: | ||
110 | 111 | ||
111 | int dma_set_coherent_mask(struct device *dev, u64 mask); | 112 | The query for streaming mappings is performed via a call to |
113 | dma_set_mask(): | ||
114 | |||
115 | int dma_set_mask(struct device *dev, u64 mask); | ||
116 | |||
117 | The query for consistent allocations is performed via a call | ||
118 | to dma_set_coherent_mask(): | ||
119 | |||
120 | int dma_set_coherent_mask(struct device *dev, u64 mask); | ||
112 | 121 | ||
113 | Here, dev is a pointer to the device struct of your device, and mask | 122 | Here, dev is a pointer to the device struct of your device, and mask |
114 | is a bit mask describing which bits of an address your device | 123 | is a bit mask describing which bits of an address your device |
@@ -137,7 +146,7 @@ exactly why. | |||
137 | 146 | ||
138 | The standard 32-bit addressing device would do something like this: | 147 | The standard 32-bit addressing device would do something like this: |
139 | 148 | ||
140 | if (dma_set_mask(dev, DMA_BIT_MASK(32))) { | 149 | if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) { |
141 | printk(KERN_WARNING | 150 | printk(KERN_WARNING |
142 | "mydev: No suitable DMA available.\n"); | 151 | "mydev: No suitable DMA available.\n"); |
143 | goto ignore_this_device; | 152 | goto ignore_this_device; |
@@ -171,22 +180,20 @@ the case would look like this: | |||
171 | 180 | ||
172 | int using_dac, consistent_using_dac; | 181 | int using_dac, consistent_using_dac; |
173 | 182 | ||
174 | if (!dma_set_mask(dev, DMA_BIT_MASK(64))) { | 183 | if (!dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) { |
175 | using_dac = 1; | 184 | using_dac = 1; |
176 | consistent_using_dac = 1; | 185 | consistent_using_dac = 1; |
177 | dma_set_coherent_mask(dev, DMA_BIT_MASK(64)); | 186 | } else if (!dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) { |
178 | } else if (!dma_set_mask(dev, DMA_BIT_MASK(32))) { | ||
179 | using_dac = 0; | 187 | using_dac = 0; |
180 | consistent_using_dac = 0; | 188 | consistent_using_dac = 0; |
181 | dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); | ||
182 | } else { | 189 | } else { |
183 | printk(KERN_WARNING | 190 | printk(KERN_WARNING |
184 | "mydev: No suitable DMA available.\n"); | 191 | "mydev: No suitable DMA available.\n"); |
185 | goto ignore_this_device; | 192 | goto ignore_this_device; |
186 | } | 193 | } |
187 | 194 | ||
188 | dma_set_coherent_mask() will always be able to set the same or a | 195 | The coherent coherent mask will always be able to set the same or a |
189 | smaller mask as dma_set_mask(). However for the rare case that a | 196 | smaller mask as the streaming mask. However for the rare case that a |
190 | device driver only uses consistent allocations, one would have to | 197 | device driver only uses consistent allocations, one would have to |
191 | check the return value from dma_set_coherent_mask(). | 198 | check the return value from dma_set_coherent_mask(). |
192 | 199 | ||
@@ -199,9 +206,9 @@ address you might do something like: | |||
199 | goto ignore_this_device; | 206 | goto ignore_this_device; |
200 | } | 207 | } |
201 | 208 | ||
202 | When dma_set_mask() is successful, and returns zero, the kernel saves | 209 | When dma_set_mask() or dma_set_mask_and_coherent() is successful, and |
203 | away this mask you have provided. The kernel will use this | 210 | returns zero, the kernel saves away this mask you have provided. The |
204 | information later when you make DMA mappings. | 211 | kernel will use this information later when you make DMA mappings. |
205 | 212 | ||
206 | There is a case which we are aware of at this time, which is worth | 213 | There is a case which we are aware of at this time, which is worth |
207 | mentioning in this documentation. If your device supports multiple | 214 | mentioning in this documentation. If your device supports multiple |
diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt index 78a6c569d204..e865279cec58 100644 --- a/Documentation/DMA-API.txt +++ b/Documentation/DMA-API.txt | |||
@@ -142,6 +142,14 @@ internal API for use by the platform than an external API for use by | |||
142 | driver writers. | 142 | driver writers. |
143 | 143 | ||
144 | int | 144 | int |
145 | dma_set_mask_and_coherent(struct device *dev, u64 mask) | ||
146 | |||
147 | Checks to see if the mask is possible and updates the device | ||
148 | streaming and coherent DMA mask parameters if it is. | ||
149 | |||
150 | Returns: 0 if successful and a negative error if not. | ||
151 | |||
152 | int | ||
145 | dma_set_mask(struct device *dev, u64 mask) | 153 | dma_set_mask(struct device *dev, u64 mask) |
146 | 154 | ||
147 | Checks to see if the mask is possible and updates the device | 155 | Checks to see if the mask is possible and updates the device |
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index 3a8d0a2af607..ec951f98e3d9 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h | |||
@@ -97,6 +97,20 @@ static inline int dma_set_coherent_mask(struct device *dev, u64 mask) | |||
97 | } | 97 | } |
98 | #endif | 98 | #endif |
99 | 99 | ||
100 | /* | ||
101 | * Set both the DMA mask and the coherent DMA mask to the same thing. | ||
102 | * Note that we don't check the return value from dma_set_coherent_mask() | ||
103 | * as the DMA API guarantees that the coherent DMA mask can be set to | ||
104 | * the same or smaller than the streaming DMA mask. | ||
105 | */ | ||
106 | static inline int dma_set_mask_and_coherent(struct device *dev, u64 mask) | ||
107 | { | ||
108 | int rc = dma_set_mask(dev, mask); | ||
109 | if (rc == 0) | ||
110 | dma_set_coherent_mask(dev, mask); | ||
111 | return rc; | ||
112 | } | ||
113 | |||
100 | extern u64 dma_get_required_mask(struct device *dev); | 114 | extern u64 dma_get_required_mask(struct device *dev); |
101 | 115 | ||
102 | static inline unsigned int dma_get_max_seg_size(struct device *dev) | 116 | static inline unsigned int dma_get_max_seg_size(struct device *dev) |