aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2007-02-16 17:34:46 -0500
committerStefan Richter <stefanr@s5r6.in-berlin.de>2007-03-09 16:03:01 -0500
commitd2746dc192e8b9446ea1cb843e94c30f177b7e54 (patch)
treefffe9d5bd448e6542407c88f56c1e02a03da248f
parent1e1d196bf5d9258f9583a05c41c1c351ffcdeac2 (diff)
firewire: Use a buffer fill descriptor for receive when header size is 0.
When the DMA is setup to not strip any headers, we need to use the buffer fill descriptor instead of the dual buffer, since the dual buffer descriptor must strip a non-zero number of header quadlets. Signed-off-by: Kristian Høgsberg <krh@redhat.com> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
-rw-r--r--drivers/firewire/fw-iso.c2
-rw-r--r--drivers/firewire/fw-ohci.c107
-rw-r--r--drivers/firewire/fw-transaction.h3
3 files changed, 95 insertions, 17 deletions
diff --git a/drivers/firewire/fw-iso.c b/drivers/firewire/fw-iso.c
index 1605e1157237..736b1bf1513e 100644
--- a/drivers/firewire/fw-iso.c
+++ b/drivers/firewire/fw-iso.c
@@ -111,7 +111,7 @@ fw_iso_context_create(struct fw_card *card, int type, size_t header_size,
111{ 111{
112 struct fw_iso_context *ctx; 112 struct fw_iso_context *ctx;
113 113
114 ctx = card->driver->allocate_iso_context(card, type); 114 ctx = card->driver->allocate_iso_context(card, type, header_size);
115 if (IS_ERR(ctx)) 115 if (IS_ERR(ctx))
116 return ctx; 116 return ctx;
117 117
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
index 76ac70a38545..9b9ea0f3c416 100644
--- a/drivers/firewire/fw-ohci.c
+++ b/drivers/firewire/fw-ohci.c
@@ -1267,16 +1267,34 @@ ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation)
1267 spin_unlock_irqrestore(&ohci->lock, flags); 1267 spin_unlock_irqrestore(&ohci->lock, flags);
1268 return retval; 1268 return retval;
1269} 1269}
1270
1271static int handle_ir_bufferfill_packet(struct context *context,
1272 struct descriptor *d,
1273 struct descriptor *last)
1274{
1275 struct iso_context *ctx =
1276 container_of(context, struct iso_context, context);
1270 1277
1271static int handle_ir_packet(struct context *context, 1278 if (d->res_count > 0)
1272 struct descriptor *d, 1279 return 0;
1273 struct descriptor *last) 1280
1281 if (le16_to_cpu(last->control) & descriptor_irq_always)
1282 ctx->base.callback(&ctx->base,
1283 le16_to_cpu(last->res_count),
1284 0, NULL, ctx->base.callback_data);
1285
1286 return 1;
1287}
1288
1289static int handle_ir_dualbuffer_packet(struct context *context,
1290 struct descriptor *d,
1291 struct descriptor *last)
1274{ 1292{
1275 struct iso_context *ctx = 1293 struct iso_context *ctx =
1276 container_of(context, struct iso_context, context); 1294 container_of(context, struct iso_context, context);
1277 struct db_descriptor *db = (struct db_descriptor *) d; 1295 struct db_descriptor *db = (struct db_descriptor *) d;
1278 size_t header_length; 1296 size_t header_length;
1279 1297
1280 if (db->first_res_count > 0 && db->second_res_count > 0) 1298 if (db->first_res_count > 0 && db->second_res_count > 0)
1281 /* This descriptor isn't done yet, stop iteration. */ 1299 /* This descriptor isn't done yet, stop iteration. */
1282 return 0; 1300 return 0;
@@ -1317,7 +1335,7 @@ static int handle_it_packet(struct context *context,
1317} 1335}
1318 1336
1319static struct fw_iso_context * 1337static struct fw_iso_context *
1320ohci_allocate_iso_context(struct fw_card *card, int type) 1338ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size)
1321{ 1339{
1322 struct fw_ohci *ohci = fw_ohci(card); 1340 struct fw_ohci *ohci = fw_ohci(card);
1323 struct iso_context *ctx, *list; 1341 struct iso_context *ctx, *list;
@@ -1333,7 +1351,10 @@ ohci_allocate_iso_context(struct fw_card *card, int type)
1333 } else { 1351 } else {
1334 mask = &ohci->ir_context_mask; 1352 mask = &ohci->ir_context_mask;
1335 list = ohci->ir_context_list; 1353 list = ohci->ir_context_list;
1336 callback = handle_ir_packet; 1354 if (header_size > 0)
1355 callback = handle_ir_dualbuffer_packet;
1356 else
1357 callback = handle_ir_bufferfill_packet;
1337 } 1358 }
1338 1359
1339 spin_lock_irqsave(&ohci->lock, flags); 1360 spin_lock_irqsave(&ohci->lock, flags);
@@ -1378,7 +1399,7 @@ static int ohci_start_iso(struct fw_iso_context *base, s32 cycle)
1378{ 1399{
1379 struct iso_context *ctx = container_of(base, struct iso_context, base); 1400 struct iso_context *ctx = container_of(base, struct iso_context, base);
1380 struct fw_ohci *ohci = ctx->context.ohci; 1401 struct fw_ohci *ohci = ctx->context.ohci;
1381 u32 cycle_match = 0; 1402 u32 cycle_match = 0, mode;
1382 int index; 1403 int index;
1383 1404
1384 if (ctx->base.type == FW_ISO_CONTEXT_TRANSMIT) { 1405 if (ctx->base.type == FW_ISO_CONTEXT_TRANSMIT) {
@@ -1393,11 +1414,15 @@ static int ohci_start_iso(struct fw_iso_context *base, s32 cycle)
1393 } else { 1414 } else {
1394 index = ctx - ohci->ir_context_list; 1415 index = ctx - ohci->ir_context_list;
1395 1416
1417 if (ctx->base.header_size > 0)
1418 mode = IR_CONTEXT_DUAL_BUFFER_MODE;
1419 else
1420 mode = IR_CONTEXT_BUFFER_FILL;
1396 reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 1 << index); 1421 reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 1 << index);
1397 reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << index); 1422 reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << index);
1398 reg_write(ohci, context_match(ctx->context.regs), 1423 reg_write(ohci, context_match(ctx->context.regs),
1399 0xf0000000 | ctx->base.channel); 1424 0xf0000000 | ctx->base.channel);
1400 context_run(&ctx->context, IR_CONTEXT_DUAL_BUFFER_MODE); 1425 context_run(&ctx->context, mode);
1401 } 1426 }
1402 1427
1403 return 0; 1428 return 0;
@@ -1544,10 +1569,10 @@ ohci_queue_iso_transmit(struct fw_iso_context *base,
1544} 1569}
1545 1570
1546static int 1571static int
1547ohci_queue_iso_receive(struct fw_iso_context *base, 1572ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base,
1548 struct fw_iso_packet *packet, 1573 struct fw_iso_packet *packet,
1549 struct fw_iso_buffer *buffer, 1574 struct fw_iso_buffer *buffer,
1550 unsigned long payload) 1575 unsigned long payload)
1551{ 1576{
1552 struct iso_context *ctx = container_of(base, struct iso_context, base); 1577 struct iso_context *ctx = container_of(base, struct iso_context, base);
1553 struct db_descriptor *db = NULL; 1578 struct db_descriptor *db = NULL;
@@ -1604,10 +1629,58 @@ ohci_queue_iso_receive(struct fw_iso_context *base,
1604 1629
1605 if (p->interrupt) 1630 if (p->interrupt)
1606 db->control |= cpu_to_le16(descriptor_irq_always); 1631 db->control |= cpu_to_le16(descriptor_irq_always);
1632
1633 return 0;
1634}
1607 1635
1608 return 0; 1636static int
1609 } 1637ohci_queue_iso_receive_bufferfill(struct fw_iso_context *base,
1638 struct fw_iso_packet *packet,
1639 struct fw_iso_buffer *buffer,
1640 unsigned long payload)
1641{
1642 struct iso_context *ctx = container_of(base, struct iso_context, base);
1643 struct descriptor *d = NULL;
1644 dma_addr_t d_bus, page_bus;
1645 u32 length, rest;
1646 int page, offset;
1610 1647
1648 page = payload >> PAGE_SHIFT;
1649 offset = payload & ~PAGE_MASK;
1650 rest = packet->payload_length;
1651
1652 while (rest > 0) {
1653 d = context_get_descriptors(&ctx->context, 1, &d_bus);
1654 if (d == NULL)
1655 return -ENOMEM;
1656
1657 d->control = cpu_to_le16(descriptor_input_more |
1658 descriptor_status |
1659 descriptor_branch_always);
1660
1661 if (offset + rest < PAGE_SIZE)
1662 length = rest;
1663 else
1664 length = PAGE_SIZE - offset;
1665
1666 page_bus = page_private(buffer->pages[page]);
1667 d->data_address = cpu_to_le32(page_bus + offset);
1668 d->req_count = cpu_to_le16(length);
1669 d->res_count = cpu_to_le16(length);
1670
1671 context_append(&ctx->context, d, 1, 0);
1672
1673 offset = (offset + length) & ~PAGE_MASK;
1674 rest -= length;
1675 page++;
1676 }
1677
1678 if (packet->interrupt)
1679 d->control |= cpu_to_le16(descriptor_irq_always);
1680
1681 return 0;
1682}
1683
1611static int 1684static int
1612ohci_queue_iso(struct fw_iso_context *base, 1685ohci_queue_iso(struct fw_iso_context *base,
1613 struct fw_iso_packet *packet, 1686 struct fw_iso_packet *packet,
@@ -1616,8 +1689,12 @@ ohci_queue_iso(struct fw_iso_context *base,
1616{ 1689{
1617 if (base->type == FW_ISO_CONTEXT_TRANSMIT) 1690 if (base->type == FW_ISO_CONTEXT_TRANSMIT)
1618 return ohci_queue_iso_transmit(base, packet, buffer, payload); 1691 return ohci_queue_iso_transmit(base, packet, buffer, payload);
1692 else if (base->header_size == 0)
1693 return ohci_queue_iso_receive_bufferfill(base, packet,
1694 buffer, payload);
1619 else 1695 else
1620 return ohci_queue_iso_receive(base, packet, buffer, payload); 1696 return ohci_queue_iso_receive_dualbuffer(base, packet,
1697 buffer, payload);
1621} 1698}
1622 1699
1623static const struct fw_card_driver ohci_driver = { 1700static const struct fw_card_driver ohci_driver = {
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h
index 7942e914b8f1..1bbcbb341f2f 100644
--- a/drivers/firewire/fw-transaction.h
+++ b/drivers/firewire/fw-transaction.h
@@ -425,7 +425,8 @@ struct fw_card_driver {
425 int node_id, int generation); 425 int node_id, int generation);
426 426
427 struct fw_iso_context * 427 struct fw_iso_context *
428 (*allocate_iso_context)(struct fw_card *card, int type); 428 (*allocate_iso_context)(struct fw_card *card,
429 int type, size_t header_size);
429 void (*free_iso_context)(struct fw_iso_context *ctx); 430 void (*free_iso_context)(struct fw_iso_context *ctx);
430 431
431 int (*start_iso)(struct fw_iso_context *ctx, s32 cycle); 432 int (*start_iso)(struct fw_iso_context *ctx, s32 cycle);