diff options
author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2009-06-20 07:23:59 -0400 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2009-06-25 13:42:36 -0400 |
commit | 6fdc03709433ccc2005f0f593ae9d9dd04f7b485 (patch) | |
tree | e42e7304084b1b6420d456fbd2a5622e93327a74 /drivers/firewire | |
parent | 0c53decdd0a9f9c459ccabe0b5f79660bde5375b (diff) |
firewire: core: do not DMA-map stack addresses
The DMA mapping API cannot map on-stack addresses, as explained in
Documentation/DMA-mapping.txt. Convert the two cases of on-stack packet
payload buffers in firewire-core (payload of lock requests in the bus
manager work and in iso resource management) to slab-allocated memory.
There are a number on-stack buffers for quadlet write or quadlet read
requests in firewire-core and firewire-sbp2. These are harmless; they
are copied to/ from card driver internal DMA buffers since quadlet
payloads are inlined with packet headers.
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire')
-rw-r--r-- | drivers/firewire/core-card.c | 14 | ||||
-rw-r--r-- | drivers/firewire/core-cdev.c | 4 | ||||
-rw-r--r-- | drivers/firewire/core-iso.c | 24 | ||||
-rw-r--r-- | drivers/firewire/core.h | 3 |
4 files changed, 25 insertions, 20 deletions
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 543fccac81bb..f74edae5cb4c 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c | |||
@@ -196,8 +196,8 @@ static void allocate_broadcast_channel(struct fw_card *card, int generation) | |||
196 | { | 196 | { |
197 | int channel, bandwidth = 0; | 197 | int channel, bandwidth = 0; |
198 | 198 | ||
199 | fw_iso_resource_manage(card, generation, 1ULL << 31, | 199 | fw_iso_resource_manage(card, generation, 1ULL << 31, &channel, |
200 | &channel, &bandwidth, true); | 200 | &bandwidth, true, card->bm_transaction_data); |
201 | if (channel == 31) { | 201 | if (channel == 31) { |
202 | card->broadcast_channel_allocated = true; | 202 | card->broadcast_channel_allocated = true; |
203 | device_for_each_child(card->device, (void *)(long)generation, | 203 | device_for_each_child(card->device, (void *)(long)generation, |
@@ -230,7 +230,6 @@ static void fw_card_bm_work(struct work_struct *work) | |||
230 | bool do_reset = false; | 230 | bool do_reset = false; |
231 | bool root_device_is_running; | 231 | bool root_device_is_running; |
232 | bool root_device_is_cmc; | 232 | bool root_device_is_cmc; |
233 | __be32 lock_data[2]; | ||
234 | 233 | ||
235 | spin_lock_irqsave(&card->lock, flags); | 234 | spin_lock_irqsave(&card->lock, flags); |
236 | 235 | ||
@@ -273,22 +272,23 @@ static void fw_card_bm_work(struct work_struct *work) | |||
273 | goto pick_me; | 272 | goto pick_me; |
274 | } | 273 | } |
275 | 274 | ||
276 | lock_data[0] = cpu_to_be32(0x3f); | 275 | card->bm_transaction_data[0] = cpu_to_be32(0x3f); |
277 | lock_data[1] = cpu_to_be32(local_id); | 276 | card->bm_transaction_data[1] = cpu_to_be32(local_id); |
278 | 277 | ||
279 | spin_unlock_irqrestore(&card->lock, flags); | 278 | spin_unlock_irqrestore(&card->lock, flags); |
280 | 279 | ||
281 | rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, | 280 | rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, |
282 | irm_id, generation, SCODE_100, | 281 | irm_id, generation, SCODE_100, |
283 | CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID, | 282 | CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID, |
284 | lock_data, sizeof(lock_data)); | 283 | card->bm_transaction_data, |
284 | sizeof(card->bm_transaction_data)); | ||
285 | 285 | ||
286 | if (rcode == RCODE_GENERATION) | 286 | if (rcode == RCODE_GENERATION) |
287 | /* Another bus reset, BM work has been rescheduled. */ | 287 | /* Another bus reset, BM work has been rescheduled. */ |
288 | goto out; | 288 | goto out; |
289 | 289 | ||
290 | if (rcode == RCODE_COMPLETE && | 290 | if (rcode == RCODE_COMPLETE && |
291 | lock_data[0] != cpu_to_be32(0x3f)) { | 291 | card->bm_transaction_data[0] != cpu_to_be32(0x3f)) { |
292 | 292 | ||
293 | /* Somebody else is BM. Only act as IRM. */ | 293 | /* Somebody else is BM. Only act as IRM. */ |
294 | if (local_id == irm_id) | 294 | if (local_id == irm_id) |
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index d1d30c615b0f..ced186d7e9a9 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c | |||
@@ -125,6 +125,7 @@ struct iso_resource { | |||
125 | int generation; | 125 | int generation; |
126 | u64 channels; | 126 | u64 channels; |
127 | s32 bandwidth; | 127 | s32 bandwidth; |
128 | __be32 transaction_data[2]; | ||
128 | struct iso_resource_event *e_alloc, *e_dealloc; | 129 | struct iso_resource_event *e_alloc, *e_dealloc; |
129 | }; | 130 | }; |
130 | 131 | ||
@@ -1049,7 +1050,8 @@ static void iso_resource_work(struct work_struct *work) | |||
1049 | r->channels, &channel, &bandwidth, | 1050 | r->channels, &channel, &bandwidth, |
1050 | todo == ISO_RES_ALLOC || | 1051 | todo == ISO_RES_ALLOC || |
1051 | todo == ISO_RES_REALLOC || | 1052 | todo == ISO_RES_REALLOC || |
1052 | todo == ISO_RES_ALLOC_ONCE); | 1053 | todo == ISO_RES_ALLOC_ONCE, |
1054 | r->transaction_data); | ||
1053 | /* | 1055 | /* |
1054 | * Is this generation outdated already? As long as this resource sticks | 1056 | * Is this generation outdated already? As long as this resource sticks |
1055 | * in the idr, it will be scheduled again for a newer generation or at | 1057 | * in the idr, it will be scheduled again for a newer generation or at |
diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c index 166f19c6d38d..110e731f5574 100644 --- a/drivers/firewire/core-iso.c +++ b/drivers/firewire/core-iso.c | |||
@@ -177,9 +177,8 @@ EXPORT_SYMBOL(fw_iso_context_stop); | |||
177 | */ | 177 | */ |
178 | 178 | ||
179 | static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, | 179 | static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, |
180 | int bandwidth, bool allocate) | 180 | int bandwidth, bool allocate, __be32 data[2]) |
181 | { | 181 | { |
182 | __be32 data[2]; | ||
183 | int try, new, old = allocate ? BANDWIDTH_AVAILABLE_INITIAL : 0; | 182 | int try, new, old = allocate ? BANDWIDTH_AVAILABLE_INITIAL : 0; |
184 | 183 | ||
185 | /* | 184 | /* |
@@ -215,9 +214,9 @@ static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, | |||
215 | } | 214 | } |
216 | 215 | ||
217 | static int manage_channel(struct fw_card *card, int irm_id, int generation, | 216 | static int manage_channel(struct fw_card *card, int irm_id, int generation, |
218 | u32 channels_mask, u64 offset, bool allocate) | 217 | u32 channels_mask, u64 offset, bool allocate, __be32 data[2]) |
219 | { | 218 | { |
220 | __be32 data[2], c, all, old; | 219 | __be32 c, all, old; |
221 | int i, retry = 5; | 220 | int i, retry = 5; |
222 | 221 | ||
223 | old = all = allocate ? cpu_to_be32(~0) : 0; | 222 | old = all = allocate ? cpu_to_be32(~0) : 0; |
@@ -260,7 +259,7 @@ static int manage_channel(struct fw_card *card, int irm_id, int generation, | |||
260 | } | 259 | } |
261 | 260 | ||
262 | static void deallocate_channel(struct fw_card *card, int irm_id, | 261 | static void deallocate_channel(struct fw_card *card, int irm_id, |
263 | int generation, int channel) | 262 | int generation, int channel, __be32 buffer[2]) |
264 | { | 263 | { |
265 | u32 mask; | 264 | u32 mask; |
266 | u64 offset; | 265 | u64 offset; |
@@ -269,7 +268,7 @@ static void deallocate_channel(struct fw_card *card, int irm_id, | |||
269 | offset = channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI : | 268 | offset = channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI : |
270 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO; | 269 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO; |
271 | 270 | ||
272 | manage_channel(card, irm_id, generation, mask, offset, false); | 271 | manage_channel(card, irm_id, generation, mask, offset, false, buffer); |
273 | } | 272 | } |
274 | 273 | ||
275 | /** | 274 | /** |
@@ -298,7 +297,7 @@ static void deallocate_channel(struct fw_card *card, int irm_id, | |||
298 | */ | 297 | */ |
299 | void fw_iso_resource_manage(struct fw_card *card, int generation, | 298 | void fw_iso_resource_manage(struct fw_card *card, int generation, |
300 | u64 channels_mask, int *channel, int *bandwidth, | 299 | u64 channels_mask, int *channel, int *bandwidth, |
301 | bool allocate) | 300 | bool allocate, __be32 buffer[2]) |
302 | { | 301 | { |
303 | u32 channels_hi = channels_mask; /* channels 31...0 */ | 302 | u32 channels_hi = channels_mask; /* channels 31...0 */ |
304 | u32 channels_lo = channels_mask >> 32; /* channels 63...32 */ | 303 | u32 channels_lo = channels_mask >> 32; /* channels 63...32 */ |
@@ -310,10 +309,12 @@ void fw_iso_resource_manage(struct fw_card *card, int generation, | |||
310 | 309 | ||
311 | if (channels_hi) | 310 | if (channels_hi) |
312 | c = manage_channel(card, irm_id, generation, channels_hi, | 311 | c = manage_channel(card, irm_id, generation, channels_hi, |
313 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, allocate); | 312 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, |
313 | allocate, buffer); | ||
314 | if (channels_lo && c < 0) { | 314 | if (channels_lo && c < 0) { |
315 | c = manage_channel(card, irm_id, generation, channels_lo, | 315 | c = manage_channel(card, irm_id, generation, channels_lo, |
316 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO, allocate); | 316 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO, |
317 | allocate, buffer); | ||
317 | if (c >= 0) | 318 | if (c >= 0) |
318 | c += 32; | 319 | c += 32; |
319 | } | 320 | } |
@@ -325,12 +326,13 @@ void fw_iso_resource_manage(struct fw_card *card, int generation, | |||
325 | if (*bandwidth == 0) | 326 | if (*bandwidth == 0) |
326 | return; | 327 | return; |
327 | 328 | ||
328 | ret = manage_bandwidth(card, irm_id, generation, *bandwidth, allocate); | 329 | ret = manage_bandwidth(card, irm_id, generation, *bandwidth, |
330 | allocate, buffer); | ||
329 | if (ret < 0) | 331 | if (ret < 0) |
330 | *bandwidth = 0; | 332 | *bandwidth = 0; |
331 | 333 | ||
332 | if (allocate && ret < 0 && c >= 0) { | 334 | if (allocate && ret < 0 && c >= 0) { |
333 | deallocate_channel(card, irm_id, generation, c); | 335 | deallocate_channel(card, irm_id, generation, c, buffer); |
334 | *channel = ret; | 336 | *channel = ret; |
335 | } | 337 | } |
336 | } | 338 | } |
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index c3cfc647e5e3..6052816be353 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h | |||
@@ -120,7 +120,8 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event); | |||
120 | 120 | ||
121 | int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma); | 121 | int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma); |
122 | void fw_iso_resource_manage(struct fw_card *card, int generation, | 122 | void fw_iso_resource_manage(struct fw_card *card, int generation, |
123 | u64 channels_mask, int *channel, int *bandwidth, bool allocate); | 123 | u64 channels_mask, int *channel, int *bandwidth, |
124 | bool allocate, __be32 buffer[2]); | ||
124 | 125 | ||
125 | 126 | ||
126 | /* -topology */ | 127 | /* -topology */ |