Commit f30e6d3e419bfb5540fa82ba7eca01d578556e6b
1 parent
020abf03cd
Exists in
master
and in
7 other branches
firewire: octlet AT payloads can be stack-allocated
We do not need slab allocations anymore in order to satisfy streaming DMA mapping constraints, thanks to commit da28947e7e36 "firewire: ohci: avoid separate DMA mapping for small AT payloads". (Besides, the slab-allocated buffers that firewire-core, firewire-sbp2, and firedtv used to provide for 8-byte write and lock requests were still not fully portable since they crossed cacheline boundaries or shared a cacheline with unrelated CPU-accessed data. snd-firewire-lib got this aspect right by using an extra kmalloc/ kfree just for the 8-byte transaction buffer.) This change replaces kmalloc'ed lock transaction scratch buffers in firewire-core, firedtv, and snd-firewire-lib by local stack allocations. Perhaps the most notable result of the change is simpler locking because there is no need to serialize usages of preallocated per-device buffers anymore. Also, allocations and deallocations are simpler. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> Acked-by: Clemens Ladisch <clemens@ladisch.de>
Showing 9 changed files with 30 additions and 52 deletions Side-by-side Diff
drivers/firewire/core-card.c
... | ... | @@ -258,8 +258,7 @@ |
258 | 258 | |
259 | 259 | if (!card->broadcast_channel_allocated) { |
260 | 260 | fw_iso_resource_manage(card, generation, 1ULL << 31, |
261 | - &channel, &bandwidth, true, | |
262 | - card->bm_transaction_data); | |
261 | + &channel, &bandwidth, true); | |
263 | 262 | if (channel != 31) { |
264 | 263 | fw_notify("failed to allocate broadcast channel\n"); |
265 | 264 | return; |
... | ... | @@ -294,6 +293,7 @@ |
294 | 293 | bool root_device_is_cmc; |
295 | 294 | bool irm_is_1394_1995_only; |
296 | 295 | bool keep_this_irm; |
296 | + __be32 transaction_data[2]; | |
297 | 297 | |
298 | 298 | spin_lock_irq(&card->lock); |
299 | 299 | |
300 | 300 | |
301 | 301 | |
... | ... | @@ -355,21 +355,21 @@ |
355 | 355 | goto pick_me; |
356 | 356 | } |
357 | 357 | |
358 | - card->bm_transaction_data[0] = cpu_to_be32(0x3f); | |
359 | - card->bm_transaction_data[1] = cpu_to_be32(local_id); | |
358 | + transaction_data[0] = cpu_to_be32(0x3f); | |
359 | + transaction_data[1] = cpu_to_be32(local_id); | |
360 | 360 | |
361 | 361 | spin_unlock_irq(&card->lock); |
362 | 362 | |
363 | 363 | rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, |
364 | 364 | irm_id, generation, SCODE_100, |
365 | 365 | CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID, |
366 | - card->bm_transaction_data, 8); | |
366 | + transaction_data, 8); | |
367 | 367 | |
368 | 368 | if (rcode == RCODE_GENERATION) |
369 | 369 | /* Another bus reset, BM work has been rescheduled. */ |
370 | 370 | goto out; |
371 | 371 | |
372 | - bm_id = be32_to_cpu(card->bm_transaction_data[0]); | |
372 | + bm_id = be32_to_cpu(transaction_data[0]); | |
373 | 373 | |
374 | 374 | spin_lock_irq(&card->lock); |
375 | 375 | if (rcode == RCODE_COMPLETE && generation == card->generation) |
376 | 376 | |
... | ... | @@ -490,11 +490,11 @@ |
490 | 490 | /* |
491 | 491 | * Make sure that the cycle master sends cycle start packets. |
492 | 492 | */ |
493 | - card->bm_transaction_data[0] = cpu_to_be32(CSR_STATE_BIT_CMSTR); | |
493 | + transaction_data[0] = cpu_to_be32(CSR_STATE_BIT_CMSTR); | |
494 | 494 | rcode = fw_run_transaction(card, TCODE_WRITE_QUADLET_REQUEST, |
495 | 495 | root_id, generation, SCODE_100, |
496 | 496 | CSR_REGISTER_BASE + CSR_STATE_SET, |
497 | - card->bm_transaction_data, 4); | |
497 | + transaction_data, 4); | |
498 | 498 | if (rcode == RCODE_GENERATION) |
499 | 499 | goto out; |
500 | 500 | } |
drivers/firewire/core-cdev.c
... | ... | @@ -141,7 +141,6 @@ |
141 | 141 | int generation; |
142 | 142 | u64 channels; |
143 | 143 | s32 bandwidth; |
144 | - __be32 transaction_data[2]; | |
145 | 144 | struct iso_resource_event *e_alloc, *e_dealloc; |
146 | 145 | }; |
147 | 146 | |
... | ... | @@ -1229,8 +1228,7 @@ |
1229 | 1228 | r->channels, &channel, &bandwidth, |
1230 | 1229 | todo == ISO_RES_ALLOC || |
1231 | 1230 | todo == ISO_RES_REALLOC || |
1232 | - todo == ISO_RES_ALLOC_ONCE, | |
1233 | - r->transaction_data); | |
1231 | + todo == ISO_RES_ALLOC_ONCE); | |
1234 | 1232 | /* |
1235 | 1233 | * Is this generation outdated already? As long as this resource sticks |
1236 | 1234 | * in the idr, it will be scheduled again for a newer generation or at |
drivers/firewire/core-iso.c
... | ... | @@ -196,9 +196,10 @@ |
196 | 196 | */ |
197 | 197 | |
198 | 198 | static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, |
199 | - int bandwidth, bool allocate, __be32 data[2]) | |
199 | + int bandwidth, bool allocate) | |
200 | 200 | { |
201 | 201 | int try, new, old = allocate ? BANDWIDTH_AVAILABLE_INITIAL : 0; |
202 | + __be32 data[2]; | |
202 | 203 | |
203 | 204 | /* |
204 | 205 | * On a 1394a IRM with low contention, try < 1 is enough. |
205 | 206 | |
... | ... | @@ -233,9 +234,10 @@ |
233 | 234 | } |
234 | 235 | |
235 | 236 | static int manage_channel(struct fw_card *card, int irm_id, int generation, |
236 | - u32 channels_mask, u64 offset, bool allocate, __be32 data[2]) | |
237 | + u32 channels_mask, u64 offset, bool allocate) | |
237 | 238 | { |
238 | 239 | __be32 bit, all, old; |
240 | + __be32 data[2]; | |
239 | 241 | int channel, ret = -EIO, retry = 5; |
240 | 242 | |
241 | 243 | old = all = allocate ? cpu_to_be32(~0) : 0; |
... | ... | @@ -284,7 +286,7 @@ |
284 | 286 | } |
285 | 287 | |
286 | 288 | static void deallocate_channel(struct fw_card *card, int irm_id, |
287 | - int generation, int channel, __be32 buffer[2]) | |
289 | + int generation, int channel) | |
288 | 290 | { |
289 | 291 | u32 mask; |
290 | 292 | u64 offset; |
... | ... | @@ -293,7 +295,7 @@ |
293 | 295 | offset = channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI : |
294 | 296 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO; |
295 | 297 | |
296 | - manage_channel(card, irm_id, generation, mask, offset, false, buffer); | |
298 | + manage_channel(card, irm_id, generation, mask, offset, false); | |
297 | 299 | } |
298 | 300 | |
299 | 301 | /** |
... | ... | @@ -322,7 +324,7 @@ |
322 | 324 | */ |
323 | 325 | void fw_iso_resource_manage(struct fw_card *card, int generation, |
324 | 326 | u64 channels_mask, int *channel, int *bandwidth, |
325 | - bool allocate, __be32 buffer[2]) | |
327 | + bool allocate) | |
326 | 328 | { |
327 | 329 | u32 channels_hi = channels_mask; /* channels 31...0 */ |
328 | 330 | u32 channels_lo = channels_mask >> 32; /* channels 63...32 */ |
329 | 331 | |
... | ... | @@ -335,11 +337,11 @@ |
335 | 337 | if (channels_hi) |
336 | 338 | c = manage_channel(card, irm_id, generation, channels_hi, |
337 | 339 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, |
338 | - allocate, buffer); | |
340 | + allocate); | |
339 | 341 | if (channels_lo && c < 0) { |
340 | 342 | c = manage_channel(card, irm_id, generation, channels_lo, |
341 | 343 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO, |
342 | - allocate, buffer); | |
344 | + allocate); | |
343 | 345 | if (c >= 0) |
344 | 346 | c += 32; |
345 | 347 | } |
346 | 348 | |
... | ... | @@ -351,14 +353,13 @@ |
351 | 353 | if (*bandwidth == 0) |
352 | 354 | return; |
353 | 355 | |
354 | - ret = manage_bandwidth(card, irm_id, generation, *bandwidth, | |
355 | - allocate, buffer); | |
356 | + ret = manage_bandwidth(card, irm_id, generation, *bandwidth, allocate); | |
356 | 357 | if (ret < 0) |
357 | 358 | *bandwidth = 0; |
358 | 359 | |
359 | 360 | if (allocate && ret < 0) { |
360 | 361 | if (c >= 0) |
361 | - deallocate_channel(card, irm_id, generation, c, buffer); | |
362 | + deallocate_channel(card, irm_id, generation, c); | |
362 | 363 | *channel = ret; |
363 | 364 | } |
364 | 365 | } |
drivers/firewire/core-transaction.c
... | ... | @@ -326,8 +326,8 @@ |
326 | 326 | * It will contain tag, channel, and sy data instead of a node ID then. |
327 | 327 | * |
328 | 328 | * The payload buffer at @data is going to be DMA-mapped except in case of |
329 | - * quadlet-sized payload or of local (loopback) requests. Hence make sure that | |
330 | - * the buffer complies with the restrictions for DMA-mapped memory. The | |
329 | + * @length <= 8 or of local (loopback) requests. Hence make sure that the | |
330 | + * buffer complies with the restrictions of the streaming DMA mapping API. | |
331 | 331 | * @payload must not be freed before the @callback is called. |
332 | 332 | * |
333 | 333 | * In case of request types without payload, @data is NULL and @length is 0. |
... | ... | @@ -411,7 +411,8 @@ |
411 | 411 | * |
412 | 412 | * Returns the RCODE. See fw_send_request() for parameter documentation. |
413 | 413 | * Unlike fw_send_request(), @data points to the payload of the request or/and |
414 | - * to the payload of the response. | |
414 | + * to the payload of the response. DMA mapping restrictions apply to outbound | |
415 | + * request payloads of >= 8 bytes but not to inbound response payloads. | |
415 | 416 | */ |
416 | 417 | int fw_run_transaction(struct fw_card *card, int tcode, int destination_id, |
417 | 418 | int generation, int speed, unsigned long long offset, |
drivers/media/dvb/firewire/firedtv-avc.c
... | ... | @@ -1320,14 +1320,10 @@ |
1320 | 1320 | { |
1321 | 1321 | int ret; |
1322 | 1322 | |
1323 | - mutex_lock(&fdtv->avc_mutex); | |
1324 | - | |
1325 | 1323 | ret = fdtv_read(fdtv, addr, data); |
1326 | 1324 | if (ret < 0) |
1327 | 1325 | dev_err(fdtv->device, "CMP: read I/O error\n"); |
1328 | 1326 | |
1329 | - mutex_unlock(&fdtv->avc_mutex); | |
1330 | - | |
1331 | 1327 | return ret; |
1332 | 1328 | } |
1333 | 1329 | |
1334 | 1330 | |
... | ... | @@ -1335,18 +1331,9 @@ |
1335 | 1331 | { |
1336 | 1332 | int ret; |
1337 | 1333 | |
1338 | - mutex_lock(&fdtv->avc_mutex); | |
1339 | - | |
1340 | - /* data[] is stack-allocated and should not be DMA-mapped. */ | |
1341 | - memcpy(fdtv->avc_data, data, 8); | |
1342 | - | |
1343 | - ret = fdtv_lock(fdtv, addr, fdtv->avc_data); | |
1334 | + ret = fdtv_lock(fdtv, addr, data); | |
1344 | 1335 | if (ret < 0) |
1345 | 1336 | dev_err(fdtv->device, "CMP: lock I/O error\n"); |
1346 | - else | |
1347 | - memcpy(data, fdtv->avc_data, 8); | |
1348 | - | |
1349 | - mutex_unlock(&fdtv->avc_mutex); | |
1350 | 1337 | |
1351 | 1338 | return ret; |
1352 | 1339 | } |
include/linux/firewire.h
... | ... | @@ -125,7 +125,6 @@ |
125 | 125 | struct delayed_work bm_work; /* bus manager job */ |
126 | 126 | int bm_retries; |
127 | 127 | int bm_generation; |
128 | - __be32 bm_transaction_data[2]; | |
129 | 128 | int bm_node_id; |
130 | 129 | bool bm_abdicate; |
131 | 130 | |
... | ... | @@ -447,7 +446,7 @@ |
447 | 446 | void fw_iso_context_destroy(struct fw_iso_context *ctx); |
448 | 447 | void fw_iso_resource_manage(struct fw_card *card, int generation, |
449 | 448 | u64 channels_mask, int *channel, int *bandwidth, |
450 | - bool allocate, __be32 buffer[2]); | |
449 | + bool allocate); | |
451 | 450 | |
452 | 451 | #endif /* _LINUX_FIREWIRE_H */ |
sound/firewire/cmp.c
... | ... | @@ -49,10 +49,9 @@ |
49 | 49 | enum bus_reset_handling bus_reset_handling) |
50 | 50 | { |
51 | 51 | struct fw_device *device = fw_parent_device(c->resources.unit); |
52 | - __be32 *buffer = c->resources.buffer; | |
53 | 52 | int generation = c->resources.generation; |
54 | 53 | int rcode, errors = 0; |
55 | - __be32 old_arg; | |
54 | + __be32 old_arg, buffer[2]; | |
56 | 55 | int err; |
57 | 56 | |
58 | 57 | buffer[0] = c->last_pcr_value; |
sound/firewire/iso-resources.c
... | ... | @@ -11,7 +11,6 @@ |
11 | 11 | #include <linux/jiffies.h> |
12 | 12 | #include <linux/mutex.h> |
13 | 13 | #include <linux/sched.h> |
14 | -#include <linux/slab.h> | |
15 | 14 | #include <linux/spinlock.h> |
16 | 15 | #include "iso-resources.h" |
17 | 16 | |
... | ... | @@ -25,10 +24,6 @@ |
25 | 24 | */ |
26 | 25 | int fw_iso_resources_init(struct fw_iso_resources *r, struct fw_unit *unit) |
27 | 26 | { |
28 | - r->buffer = kmalloc(2 * 4, GFP_KERNEL); | |
29 | - if (!r->buffer) | |
30 | - return -ENOMEM; | |
31 | - | |
32 | 27 | r->channels_mask = ~0uLL; |
33 | 28 | r->unit = fw_unit_get(unit); |
34 | 29 | mutex_init(&r->mutex); |
... | ... | @@ -44,7 +39,6 @@ |
44 | 39 | void fw_iso_resources_destroy(struct fw_iso_resources *r) |
45 | 40 | { |
46 | 41 | WARN_ON(r->allocated); |
47 | - kfree(r->buffer); | |
48 | 42 | mutex_destroy(&r->mutex); |
49 | 43 | fw_unit_put(r->unit); |
50 | 44 | } |
... | ... | @@ -131,7 +125,7 @@ |
131 | 125 | |
132 | 126 | bandwidth = r->bandwidth + r->bandwidth_overhead; |
133 | 127 | fw_iso_resource_manage(card, r->generation, r->channels_mask, |
134 | - &channel, &bandwidth, true, r->buffer); | |
128 | + &channel, &bandwidth, true); | |
135 | 129 | if (channel == -EAGAIN) { |
136 | 130 | mutex_unlock(&r->mutex); |
137 | 131 | goto retry_after_bus_reset; |
... | ... | @@ -184,7 +178,7 @@ |
184 | 178 | bandwidth = r->bandwidth + r->bandwidth_overhead; |
185 | 179 | |
186 | 180 | fw_iso_resource_manage(card, r->generation, 1uLL << r->channel, |
187 | - &channel, &bandwidth, true, r->buffer); | |
181 | + &channel, &bandwidth, true); | |
188 | 182 | /* |
189 | 183 | * When another bus reset happens, pretend that the allocation |
190 | 184 | * succeeded; we will try again for the new generation later. |
... | ... | @@ -220,7 +214,7 @@ |
220 | 214 | if (r->allocated) { |
221 | 215 | bandwidth = r->bandwidth + r->bandwidth_overhead; |
222 | 216 | fw_iso_resource_manage(card, r->generation, 1uLL << r->channel, |
223 | - &channel, &bandwidth, false, r->buffer); | |
217 | + &channel, &bandwidth, false); | |
224 | 218 | if (channel < 0) |
225 | 219 | dev_err(&r->unit->device, |
226 | 220 | "isochronous resource deallocation failed\n"); |
sound/firewire/iso-resources.h