aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire/fw-ohci.c
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2007-02-16 17:34:44 -0500
committerStefan Richter <stefanr@s5r6.in-berlin.de>2007-03-09 16:03:00 -0500
commit9b32d5f3074e9b1afaa39a360a59fd77a2214783 (patch)
tree441cde033cc8a55b7bc9715684c42554fa259cc4 /drivers/firewire/fw-ohci.c
parent500be7251a4af1a87aa48285a23a741f74a97a89 (diff)
firewire: Acummulate received iso headers and send them back to user space.
Signed-off-by: Kristian Høgsberg <krh@redhat.com> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire/fw-ohci.c')
-rw-r--r--drivers/firewire/fw-ohci.c49
1 files changed, 34 insertions, 15 deletions
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
index d601ec7ff4d5..b5a154583e0d 100644
--- a/drivers/firewire/fw-ohci.c
+++ b/drivers/firewire/fw-ohci.c
@@ -143,6 +143,8 @@ struct at_context {
143struct iso_context { 143struct iso_context {
144 struct fw_iso_context base; 144 struct fw_iso_context base;
145 struct context context; 145 struct context context;
146 void *header;
147 size_t header_length;
146}; 148};
147 149
148#define CONFIG_ROM_SIZE 1024 150#define CONFIG_ROM_SIZE 1024
@@ -501,7 +503,7 @@ context_init(struct context *ctx, struct fw_ohci *ohci,
501 return 0; 503 return 0;
502} 504}
503 505
504 static void 506static void
505context_release(struct context *ctx) 507context_release(struct context *ctx)
506{ 508{
507 struct fw_card *card = &ctx->ohci->card; 509 struct fw_card *card = &ctx->ohci->card;
@@ -1273,16 +1275,23 @@ static int handle_ir_packet(struct context *context,
1273 struct iso_context *ctx = 1275 struct iso_context *ctx =
1274 container_of(context, struct iso_context, context); 1276 container_of(context, struct iso_context, context);
1275 struct db_descriptor *db = (struct db_descriptor *) d; 1277 struct db_descriptor *db = (struct db_descriptor *) d;
1278 size_t header_length;
1276 1279
1277 if (db->first_res_count > 0 && db->second_res_count > 0) 1280 if (db->first_res_count > 0 && db->second_res_count > 0)
1278 /* This descriptor isn't done yet, stop iteration. */ 1281 /* This descriptor isn't done yet, stop iteration. */
1279 return 0; 1282 return 0;
1280 1283
1281 if (le16_to_cpu(db->control) & descriptor_irq_always) 1284 header_length = db->first_req_count - db->first_res_count;
1282 /* FIXME: we should pass payload address here. */ 1285 if (ctx->header_length + header_length <= PAGE_SIZE)
1283 ctx->base.callback(&ctx->base, 1286 memcpy(ctx->header + ctx->header_length, db + 1, header_length);
1284 0, 0, 1287 ctx->header_length += header_length;
1288
1289 if (le16_to_cpu(db->control) & descriptor_irq_always) {
1290 ctx->base.callback(&ctx->base, 0,
1291 ctx->header_length, ctx->header,
1285 ctx->base.callback_data); 1292 ctx->base.callback_data);
1293 ctx->header_length = 0;
1294 }
1286 1295
1287 return 1; 1296 return 1;
1288} 1297}
@@ -1301,9 +1310,8 @@ static int handle_it_packet(struct context *context,
1301 return 0; 1310 return 0;
1302 1311
1303 if (le16_to_cpu(last->control) & descriptor_irq_always) 1312 if (le16_to_cpu(last->control) & descriptor_irq_always)
1304 ctx->base.callback(&ctx->base, 1313 ctx->base.callback(&ctx->base, le16_to_cpu(last->res_count),
1305 0, le16_to_cpu(last->res_count), 1314 0, NULL, ctx->base.callback_data);
1306 ctx->base.callback_data);
1307 1315
1308 return 1; 1316 return 1;
1309} 1317}
@@ -1316,7 +1324,7 @@ ohci_allocate_iso_context(struct fw_card *card, int type)
1316 descriptor_callback_t callback; 1324 descriptor_callback_t callback;
1317 u32 *mask, regs; 1325 u32 *mask, regs;
1318 unsigned long flags; 1326 unsigned long flags;
1319 int index, retval; 1327 int index, retval = -ENOMEM;
1320 1328
1321 if (type == FW_ISO_CONTEXT_TRANSMIT) { 1329 if (type == FW_ISO_CONTEXT_TRANSMIT) {
1322 mask = &ohci->it_context_mask; 1330 mask = &ohci->it_context_mask;
@@ -1344,16 +1352,26 @@ ohci_allocate_iso_context(struct fw_card *card, int type)
1344 1352
1345 ctx = &list[index]; 1353 ctx = &list[index];
1346 memset(ctx, 0, sizeof *ctx); 1354 memset(ctx, 0, sizeof *ctx);
1355 ctx->header_length = 0;
1356 ctx->header = (void *) __get_free_page(GFP_KERNEL);
1357 if (ctx->header == NULL)
1358 goto out;
1359
1347 retval = context_init(&ctx->context, ohci, ISO_BUFFER_SIZE, 1360 retval = context_init(&ctx->context, ohci, ISO_BUFFER_SIZE,
1348 regs, callback); 1361 regs, callback);
1349 if (retval < 0) { 1362 if (retval < 0)
1350 spin_lock_irqsave(&ohci->lock, flags); 1363 goto out_with_header;
1351 *mask |= 1 << index;
1352 spin_unlock_irqrestore(&ohci->lock, flags);
1353 return ERR_PTR(retval);
1354 }
1355 1364
1356 return &ctx->base; 1365 return &ctx->base;
1366
1367 out_with_header:
1368 free_page((unsigned long)ctx->header);
1369 out:
1370 spin_lock_irqsave(&ohci->lock, flags);
1371 *mask |= 1 << index;
1372 spin_unlock_irqrestore(&ohci->lock, flags);
1373
1374 return ERR_PTR(retval);
1357} 1375}
1358 1376
1359static int ohci_start_iso(struct fw_iso_context *base, s32 cycle) 1377static int ohci_start_iso(struct fw_iso_context *base, s32 cycle)
@@ -1413,6 +1431,7 @@ static void ohci_free_iso_context(struct fw_iso_context *base)
1413 1431
1414 ohci_stop_iso(base); 1432 ohci_stop_iso(base);
1415 context_release(&ctx->context); 1433 context_release(&ctx->context);
1434 free_page((unsigned long)ctx->header);
1416 1435
1417 spin_lock_irqsave(&ohci->lock, flags); 1436 spin_lock_irqsave(&ohci->lock, flags);
1418 1437