aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firewire')
-rw-r--r--drivers/firewire/fw-ohci.c44
1 files changed, 24 insertions, 20 deletions
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
index 436a855a4c60..a44d16d0c505 100644
--- a/drivers/firewire/fw-ohci.c
+++ b/drivers/firewire/fw-ohci.c
@@ -125,6 +125,7 @@ struct context {
125struct iso_context { 125struct iso_context {
126 struct fw_iso_context base; 126 struct fw_iso_context base;
127 struct context context; 127 struct context context;
128 int excess_bytes;
128 void *header; 129 void *header;
129 size_t header_length; 130 size_t header_length;
130}; 131};
@@ -1408,9 +1409,13 @@ static int handle_ir_dualbuffer_packet(struct context *context,
1408 void *p, *end; 1409 void *p, *end;
1409 int i; 1410 int i;
1410 1411
1411 if (db->first_res_count > 0 && db->second_res_count > 0) 1412 if (db->first_res_count > 0 && db->second_res_count > 0) {
1412 /* This descriptor isn't done yet, stop iteration. */ 1413 if (ctx->excess_bytes <= le16_to_cpu(db->second_req_count)) {
1413 return 0; 1414 /* This descriptor isn't done yet, stop iteration. */
1415 return 0;
1416 }
1417 ctx->excess_bytes -= le16_to_cpu(db->second_req_count);
1418 }
1414 1419
1415 header_length = le16_to_cpu(db->first_req_count) - 1420 header_length = le16_to_cpu(db->first_req_count) -
1416 le16_to_cpu(db->first_res_count); 1421 le16_to_cpu(db->first_res_count);
@@ -1429,11 +1434,15 @@ static int handle_ir_dualbuffer_packet(struct context *context,
1429 *(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4)); 1434 *(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4));
1430 memcpy(ctx->header + i + 4, p + 8, ctx->base.header_size - 4); 1435 memcpy(ctx->header + i + 4, p + 8, ctx->base.header_size - 4);
1431 i += ctx->base.header_size; 1436 i += ctx->base.header_size;
1437 ctx->excess_bytes +=
1438 (le32_to_cpu(*(u32 *)(p + 4)) >> 16) & 0xffff;
1432 p += ctx->base.header_size + 4; 1439 p += ctx->base.header_size + 4;
1433 } 1440 }
1434
1435 ctx->header_length = i; 1441 ctx->header_length = i;
1436 1442
1443 ctx->excess_bytes -= le16_to_cpu(db->second_req_count) -
1444 le16_to_cpu(db->second_res_count);
1445
1437 if (le16_to_cpu(db->control) & DESCRIPTOR_IRQ_ALWAYS) { 1446 if (le16_to_cpu(db->control) & DESCRIPTOR_IRQ_ALWAYS) {
1438 ir_header = (__le32 *) (db + 1); 1447 ir_header = (__le32 *) (db + 1);
1439 ctx->base.callback(&ctx->base, 1448 ctx->base.callback(&ctx->base,
@@ -1775,19 +1784,6 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base,
1775 * packet, retransmit or terminate.. 1784 * packet, retransmit or terminate..
1776 */ 1785 */
1777 1786
1778 if (packet->skip) {
1779 d = context_get_descriptors(&ctx->context, 2, &d_bus);
1780 if (d == NULL)
1781 return -ENOMEM;
1782
1783 db = (struct db_descriptor *) d;
1784 db->control = cpu_to_le16(DESCRIPTOR_STATUS |
1785 DESCRIPTOR_BRANCH_ALWAYS |
1786 DESCRIPTOR_WAIT);
1787 db->first_size = cpu_to_le16(ctx->base.header_size + 4);
1788 context_append(&ctx->context, d, 2, 0);
1789 }
1790
1791 p = packet; 1787 p = packet;
1792 z = 2; 1788 z = 2;
1793 1789
@@ -1815,11 +1811,18 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base,
1815 db->control = cpu_to_le16(DESCRIPTOR_STATUS | 1811 db->control = cpu_to_le16(DESCRIPTOR_STATUS |
1816 DESCRIPTOR_BRANCH_ALWAYS); 1812 DESCRIPTOR_BRANCH_ALWAYS);
1817 db->first_size = cpu_to_le16(ctx->base.header_size + 4); 1813 db->first_size = cpu_to_le16(ctx->base.header_size + 4);
1818 db->first_req_count = cpu_to_le16(header_size); 1814 if (p->skip && rest == p->payload_length) {
1815 db->control |= cpu_to_le16(DESCRIPTOR_WAIT);
1816 db->first_req_count = db->first_size;
1817 } else {
1818 db->first_req_count = cpu_to_le16(header_size);
1819 }
1819 db->first_res_count = db->first_req_count; 1820 db->first_res_count = db->first_req_count;
1820 db->first_buffer = cpu_to_le32(d_bus + sizeof(*db)); 1821 db->first_buffer = cpu_to_le32(d_bus + sizeof(*db));
1821 1822
1822 if (offset + rest < PAGE_SIZE) 1823 if (p->skip && rest == p->payload_length)
1824 length = 4;
1825 else if (offset + rest < PAGE_SIZE)
1823 length = rest; 1826 length = rest;
1824 else 1827 else
1825 length = PAGE_SIZE - offset; 1828 length = PAGE_SIZE - offset;
@@ -1835,7 +1838,8 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base,
1835 context_append(&ctx->context, d, z, header_z); 1838 context_append(&ctx->context, d, z, header_z);
1836 offset = (offset + length) & ~PAGE_MASK; 1839 offset = (offset + length) & ~PAGE_MASK;
1837 rest -= length; 1840 rest -= length;
1838 page++; 1841 if (offset == 0)
1842 page++;
1839 } 1843 }
1840 1844
1841 return 0; 1845 return 0;