Skip to content

Commit f30e6d3

Browse files
author
Stefan Richter
committed
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 da28947 "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>
1 parent 020abf0 commit f30e6d3

File tree

9 files changed

+30
-52
lines changed

9 files changed

+30
-52
lines changed

drivers/firewire/core-card.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -258,8 +258,7 @@ static void allocate_broadcast_channel(struct fw_card *card, int generation)
258258

259259
if (!card->broadcast_channel_allocated) {
260260
fw_iso_resource_manage(card, generation, 1ULL << 31,
261-
&channel, &bandwidth, true,
262-
card->bm_transaction_data);
261+
&channel, &bandwidth, true);
263262
if (channel != 31) {
264263
fw_notify("failed to allocate broadcast channel\n");
265264
return;
@@ -294,6 +293,7 @@ static void bm_work(struct work_struct *work)
294293
bool root_device_is_cmc;
295294
bool irm_is_1394_1995_only;
296295
bool keep_this_irm;
296+
__be32 transaction_data[2];
297297

298298
spin_lock_irq(&card->lock);
299299

@@ -355,21 +355,21 @@ static void bm_work(struct work_struct *work)
355355
goto pick_me;
356356
}
357357

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);
360360

361361
spin_unlock_irq(&card->lock);
362362

363363
rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,
364364
irm_id, generation, SCODE_100,
365365
CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID,
366-
card->bm_transaction_data, 8);
366+
transaction_data, 8);
367367

368368
if (rcode == RCODE_GENERATION)
369369
/* Another bus reset, BM work has been rescheduled. */
370370
goto out;
371371

372-
bm_id = be32_to_cpu(card->bm_transaction_data[0]);
372+
bm_id = be32_to_cpu(transaction_data[0]);
373373

374374
spin_lock_irq(&card->lock);
375375
if (rcode == RCODE_COMPLETE && generation == card->generation)
@@ -490,11 +490,11 @@ static void bm_work(struct work_struct *work)
490490
/*
491491
* Make sure that the cycle master sends cycle start packets.
492492
*/
493-
card->bm_transaction_data[0] = cpu_to_be32(CSR_STATE_BIT_CMSTR);
493+
transaction_data[0] = cpu_to_be32(CSR_STATE_BIT_CMSTR);
494494
rcode = fw_run_transaction(card, TCODE_WRITE_QUADLET_REQUEST,
495495
root_id, generation, SCODE_100,
496496
CSR_REGISTER_BASE + CSR_STATE_SET,
497-
card->bm_transaction_data, 4);
497+
transaction_data, 4);
498498
if (rcode == RCODE_GENERATION)
499499
goto out;
500500
}

drivers/firewire/core-cdev.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@ struct iso_resource {
141141
int generation;
142142
u64 channels;
143143
s32 bandwidth;
144-
__be32 transaction_data[2];
145144
struct iso_resource_event *e_alloc, *e_dealloc;
146145
};
147146

@@ -1229,8 +1228,7 @@ static void iso_resource_work(struct work_struct *work)
12291228
r->channels, &channel, &bandwidth,
12301229
todo == ISO_RES_ALLOC ||
12311230
todo == ISO_RES_REALLOC ||
1232-
todo == ISO_RES_ALLOC_ONCE,
1233-
r->transaction_data);
1231+
todo == ISO_RES_ALLOC_ONCE);
12341232
/*
12351233
* Is this generation outdated already? As long as this resource sticks
12361234
* in the idr, it will be scheduled again for a newer generation or at

drivers/firewire/core-iso.c

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -196,9 +196,10 @@ EXPORT_SYMBOL(fw_iso_context_stop);
196196
*/
197197

198198
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)
200200
{
201201
int try, new, old = allocate ? BANDWIDTH_AVAILABLE_INITIAL : 0;
202+
__be32 data[2];
202203

203204
/*
204205
* On a 1394a IRM with low contention, try < 1 is enough.
@@ -233,9 +234,10 @@ static int manage_bandwidth(struct fw_card *card, int irm_id, int generation,
233234
}
234235

235236
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)
237238
{
238239
__be32 bit, all, old;
240+
__be32 data[2];
239241
int channel, ret = -EIO, retry = 5;
240242

241243
old = all = allocate ? cpu_to_be32(~0) : 0;
@@ -284,7 +286,7 @@ static int manage_channel(struct fw_card *card, int irm_id, int generation,
284286
}
285287

286288
static void deallocate_channel(struct fw_card *card, int irm_id,
287-
int generation, int channel, __be32 buffer[2])
289+
int generation, int channel)
288290
{
289291
u32 mask;
290292
u64 offset;
@@ -293,7 +295,7 @@ static void deallocate_channel(struct fw_card *card, int irm_id,
293295
offset = channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI :
294296
CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO;
295297

296-
manage_channel(card, irm_id, generation, mask, offset, false, buffer);
298+
manage_channel(card, irm_id, generation, mask, offset, false);
297299
}
298300

299301
/**
@@ -322,7 +324,7 @@ static void deallocate_channel(struct fw_card *card, int irm_id,
322324
*/
323325
void fw_iso_resource_manage(struct fw_card *card, int generation,
324326
u64 channels_mask, int *channel, int *bandwidth,
325-
bool allocate, __be32 buffer[2])
327+
bool allocate)
326328
{
327329
u32 channels_hi = channels_mask; /* channels 31...0 */
328330
u32 channels_lo = channels_mask >> 32; /* channels 63...32 */
@@ -335,11 +337,11 @@ void fw_iso_resource_manage(struct fw_card *card, int generation,
335337
if (channels_hi)
336338
c = manage_channel(card, irm_id, generation, channels_hi,
337339
CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI,
338-
allocate, buffer);
340+
allocate);
339341
if (channels_lo && c < 0) {
340342
c = manage_channel(card, irm_id, generation, channels_lo,
341343
CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO,
342-
allocate, buffer);
344+
allocate);
343345
if (c >= 0)
344346
c += 32;
345347
}
@@ -351,14 +353,13 @@ void fw_iso_resource_manage(struct fw_card *card, int generation,
351353
if (*bandwidth == 0)
352354
return;
353355

354-
ret = manage_bandwidth(card, irm_id, generation, *bandwidth,
355-
allocate, buffer);
356+
ret = manage_bandwidth(card, irm_id, generation, *bandwidth, allocate);
356357
if (ret < 0)
357358
*bandwidth = 0;
358359

359360
if (allocate && ret < 0) {
360361
if (c >= 0)
361-
deallocate_channel(card, irm_id, generation, c, buffer);
362+
deallocate_channel(card, irm_id, generation, c);
362363
*channel = ret;
363364
}
364365
}

drivers/firewire/core-transaction.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,8 @@ static int allocate_tlabel(struct fw_card *card)
326326
* It will contain tag, channel, and sy data instead of a node ID then.
327327
*
328328
* 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.
331331
* @payload must not be freed before the @callback is called.
332332
*
333333
* In case of request types without payload, @data is NULL and @length is 0.
@@ -411,7 +411,8 @@ static void transaction_callback(struct fw_card *card, int rcode,
411411
*
412412
* Returns the RCODE. See fw_send_request() for parameter documentation.
413413
* 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.
415416
*/
416417
int fw_run_transaction(struct fw_card *card, int tcode, int destination_id,
417418
int generation, int speed, unsigned long long offset,

drivers/media/dvb/firewire/firedtv-avc.c

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,33 +1320,20 @@ static int cmp_read(struct firedtv *fdtv, u64 addr, __be32 *data)
13201320
{
13211321
int ret;
13221322

1323-
mutex_lock(&fdtv->avc_mutex);
1324-
13251323
ret = fdtv_read(fdtv, addr, data);
13261324
if (ret < 0)
13271325
dev_err(fdtv->device, "CMP: read I/O error\n");
13281326

1329-
mutex_unlock(&fdtv->avc_mutex);
1330-
13311327
return ret;
13321328
}
13331329

13341330
static int cmp_lock(struct firedtv *fdtv, u64 addr, __be32 data[])
13351331
{
13361332
int ret;
13371333

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);
13441335
if (ret < 0)
13451336
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);
13501337

13511338
return ret;
13521339
}

include/linux/firewire.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,6 @@ struct fw_card {
125125
struct delayed_work bm_work; /* bus manager job */
126126
int bm_retries;
127127
int bm_generation;
128-
__be32 bm_transaction_data[2];
129128
int bm_node_id;
130129
bool bm_abdicate;
131130

@@ -447,6 +446,6 @@ int fw_iso_context_stop(struct fw_iso_context *ctx);
447446
void fw_iso_context_destroy(struct fw_iso_context *ctx);
448447
void fw_iso_resource_manage(struct fw_card *card, int generation,
449448
u64 channels_mask, int *channel, int *bandwidth,
450-
bool allocate, __be32 buffer[2]);
449+
bool allocate);
451450

452451
#endif /* _LINUX_FIREWIRE_H */

sound/firewire/cmp.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,9 @@ static int pcr_modify(struct cmp_connection *c,
4949
enum bus_reset_handling bus_reset_handling)
5050
{
5151
struct fw_device *device = fw_parent_device(c->resources.unit);
52-
__be32 *buffer = c->resources.buffer;
5352
int generation = c->resources.generation;
5453
int rcode, errors = 0;
55-
__be32 old_arg;
54+
__be32 old_arg, buffer[2];
5655
int err;
5756

5857
buffer[0] = c->last_pcr_value;

sound/firewire/iso-resources.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
#include <linux/jiffies.h>
1212
#include <linux/mutex.h>
1313
#include <linux/sched.h>
14-
#include <linux/slab.h>
1514
#include <linux/spinlock.h>
1615
#include "iso-resources.h"
1716

@@ -25,10 +24,6 @@
2524
*/
2625
int fw_iso_resources_init(struct fw_iso_resources *r, struct fw_unit *unit)
2726
{
28-
r->buffer = kmalloc(2 * 4, GFP_KERNEL);
29-
if (!r->buffer)
30-
return -ENOMEM;
31-
3227
r->channels_mask = ~0uLL;
3328
r->unit = fw_unit_get(unit);
3429
mutex_init(&r->mutex);
@@ -44,7 +39,6 @@ int fw_iso_resources_init(struct fw_iso_resources *r, struct fw_unit *unit)
4439
void fw_iso_resources_destroy(struct fw_iso_resources *r)
4540
{
4641
WARN_ON(r->allocated);
47-
kfree(r->buffer);
4842
mutex_destroy(&r->mutex);
4943
fw_unit_put(r->unit);
5044
}
@@ -131,7 +125,7 @@ int fw_iso_resources_allocate(struct fw_iso_resources *r,
131125

132126
bandwidth = r->bandwidth + r->bandwidth_overhead;
133127
fw_iso_resource_manage(card, r->generation, r->channels_mask,
134-
&channel, &bandwidth, true, r->buffer);
128+
&channel, &bandwidth, true);
135129
if (channel == -EAGAIN) {
136130
mutex_unlock(&r->mutex);
137131
goto retry_after_bus_reset;
@@ -184,7 +178,7 @@ int fw_iso_resources_update(struct fw_iso_resources *r)
184178
bandwidth = r->bandwidth + r->bandwidth_overhead;
185179

186180
fw_iso_resource_manage(card, r->generation, 1uLL << r->channel,
187-
&channel, &bandwidth, true, r->buffer);
181+
&channel, &bandwidth, true);
188182
/*
189183
* When another bus reset happens, pretend that the allocation
190184
* succeeded; we will try again for the new generation later.
@@ -220,7 +214,7 @@ void fw_iso_resources_free(struct fw_iso_resources *r)
220214
if (r->allocated) {
221215
bandwidth = r->bandwidth + r->bandwidth_overhead;
222216
fw_iso_resource_manage(card, r->generation, 1uLL << r->channel,
223-
&channel, &bandwidth, false, r->buffer);
217+
&channel, &bandwidth, false);
224218
if (channel < 0)
225219
dev_err(&r->unit->device,
226220
"isochronous resource deallocation failed\n");

sound/firewire/iso-resources.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ struct fw_iso_resources {
2424
unsigned int bandwidth_overhead;
2525
int generation; /* in which allocation is valid */
2626
bool allocated;
27-
__be32 *buffer;
2827
};
2928

3029
int fw_iso_resources_init(struct fw_iso_resources *r,

0 commit comments

Comments
 (0)