diff options
Diffstat (limited to 'drivers/firewire/fw-ohci.c')
-rw-r--r-- | drivers/firewire/fw-ohci.c | 73 |
1 files changed, 35 insertions, 38 deletions
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 6d19828a93a5..bbfd6cdac668 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c | |||
@@ -1765,6 +1765,28 @@ ohci_get_bus_time(struct fw_card *card) | |||
1765 | return bus_time; | 1765 | return bus_time; |
1766 | } | 1766 | } |
1767 | 1767 | ||
1768 | static void copy_iso_headers(struct iso_context *ctx, void *p) | ||
1769 | { | ||
1770 | int i = ctx->header_length; | ||
1771 | |||
1772 | if (i + ctx->base.header_size > PAGE_SIZE) | ||
1773 | return; | ||
1774 | |||
1775 | /* | ||
1776 | * The iso header is byteswapped to little endian by | ||
1777 | * the controller, but the remaining header quadlets | ||
1778 | * are big endian. We want to present all the headers | ||
1779 | * as big endian, so we have to swap the first quadlet. | ||
1780 | */ | ||
1781 | if (ctx->base.header_size > 0) | ||
1782 | *(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4)); | ||
1783 | if (ctx->base.header_size > 4) | ||
1784 | *(u32 *) (ctx->header + i + 4) = __swab32(*(u32 *) p); | ||
1785 | if (ctx->base.header_size > 8) | ||
1786 | memcpy(ctx->header + i + 8, p + 8, ctx->base.header_size - 8); | ||
1787 | ctx->header_length += ctx->base.header_size; | ||
1788 | } | ||
1789 | |||
1768 | static int handle_ir_dualbuffer_packet(struct context *context, | 1790 | static int handle_ir_dualbuffer_packet(struct context *context, |
1769 | struct descriptor *d, | 1791 | struct descriptor *d, |
1770 | struct descriptor *last) | 1792 | struct descriptor *last) |
@@ -1775,7 +1797,6 @@ static int handle_ir_dualbuffer_packet(struct context *context, | |||
1775 | __le32 *ir_header; | 1797 | __le32 *ir_header; |
1776 | size_t header_length; | 1798 | size_t header_length; |
1777 | void *p, *end; | 1799 | void *p, *end; |
1778 | int i; | ||
1779 | 1800 | ||
1780 | if (db->first_res_count != 0 && db->second_res_count != 0) { | 1801 | if (db->first_res_count != 0 && db->second_res_count != 0) { |
1781 | if (ctx->excess_bytes <= le16_to_cpu(db->second_req_count)) { | 1802 | if (ctx->excess_bytes <= le16_to_cpu(db->second_req_count)) { |
@@ -1788,25 +1809,14 @@ static int handle_ir_dualbuffer_packet(struct context *context, | |||
1788 | header_length = le16_to_cpu(db->first_req_count) - | 1809 | header_length = le16_to_cpu(db->first_req_count) - |
1789 | le16_to_cpu(db->first_res_count); | 1810 | le16_to_cpu(db->first_res_count); |
1790 | 1811 | ||
1791 | i = ctx->header_length; | ||
1792 | p = db + 1; | 1812 | p = db + 1; |
1793 | end = p + header_length; | 1813 | end = p + header_length; |
1794 | while (p < end && i + ctx->base.header_size <= PAGE_SIZE) { | 1814 | while (p < end) { |
1795 | /* | 1815 | copy_iso_headers(ctx, p); |
1796 | * The iso header is byteswapped to little endian by | ||
1797 | * the controller, but the remaining header quadlets | ||
1798 | * are big endian. We want to present all the headers | ||
1799 | * as big endian, so we have to swap the first | ||
1800 | * quadlet. | ||
1801 | */ | ||
1802 | *(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4)); | ||
1803 | memcpy(ctx->header + i + 4, p + 8, ctx->base.header_size - 4); | ||
1804 | i += ctx->base.header_size; | ||
1805 | ctx->excess_bytes += | 1816 | ctx->excess_bytes += |
1806 | (le32_to_cpu(*(__le32 *)(p + 4)) >> 16) & 0xffff; | 1817 | (le32_to_cpu(*(__le32 *)(p + 4)) >> 16) & 0xffff; |
1807 | p += ctx->base.header_size + 4; | 1818 | p += max(ctx->base.header_size, (size_t)8); |
1808 | } | 1819 | } |
1809 | ctx->header_length = i; | ||
1810 | 1820 | ||
1811 | ctx->excess_bytes -= le16_to_cpu(db->second_req_count) - | 1821 | ctx->excess_bytes -= le16_to_cpu(db->second_req_count) - |
1812 | le16_to_cpu(db->second_res_count); | 1822 | le16_to_cpu(db->second_res_count); |
@@ -1832,7 +1842,6 @@ static int handle_ir_packet_per_buffer(struct context *context, | |||
1832 | struct descriptor *pd; | 1842 | struct descriptor *pd; |
1833 | __le32 *ir_header; | 1843 | __le32 *ir_header; |
1834 | void *p; | 1844 | void *p; |
1835 | int i; | ||
1836 | 1845 | ||
1837 | for (pd = d; pd <= last; pd++) { | 1846 | for (pd = d; pd <= last; pd++) { |
1838 | if (pd->transfer_status) | 1847 | if (pd->transfer_status) |
@@ -1842,21 +1851,8 @@ static int handle_ir_packet_per_buffer(struct context *context, | |||
1842 | /* Descriptor(s) not done yet, stop iteration */ | 1851 | /* Descriptor(s) not done yet, stop iteration */ |
1843 | return 0; | 1852 | return 0; |
1844 | 1853 | ||
1845 | i = ctx->header_length; | 1854 | p = last + 1; |
1846 | p = last + 1; | 1855 | copy_iso_headers(ctx, p); |
1847 | |||
1848 | if (ctx->base.header_size > 0 && | ||
1849 | i + ctx->base.header_size <= PAGE_SIZE) { | ||
1850 | /* | ||
1851 | * The iso header is byteswapped to little endian by | ||
1852 | * the controller, but the remaining header quadlets | ||
1853 | * are big endian. We want to present all the headers | ||
1854 | * as big endian, so we have to swap the first quadlet. | ||
1855 | */ | ||
1856 | *(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4)); | ||
1857 | memcpy(ctx->header + i + 4, p + 8, ctx->base.header_size - 4); | ||
1858 | ctx->header_length += ctx->base.header_size; | ||
1859 | } | ||
1860 | 1856 | ||
1861 | if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS) { | 1857 | if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS) { |
1862 | ir_header = (__le32 *) p; | 1858 | ir_header = (__le32 *) p; |
@@ -2151,11 +2147,11 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, | |||
2151 | z = 2; | 2147 | z = 2; |
2152 | 2148 | ||
2153 | /* | 2149 | /* |
2154 | * The OHCI controller puts the status word in the header | 2150 | * The OHCI controller puts the isochronous header and trailer in the |
2155 | * buffer too, so we need 4 extra bytes per packet. | 2151 | * buffer, so we need at least 8 bytes. |
2156 | */ | 2152 | */ |
2157 | packet_count = p->header_length / ctx->base.header_size; | 2153 | packet_count = p->header_length / ctx->base.header_size; |
2158 | header_size = packet_count * (ctx->base.header_size + 4); | 2154 | header_size = packet_count * max(ctx->base.header_size, (size_t)8); |
2159 | 2155 | ||
2160 | /* Get header size in number of descriptors. */ | 2156 | /* Get header size in number of descriptors. */ |
2161 | header_z = DIV_ROUND_UP(header_size, sizeof(*d)); | 2157 | header_z = DIV_ROUND_UP(header_size, sizeof(*d)); |
@@ -2173,7 +2169,8 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, | |||
2173 | db = (struct db_descriptor *) d; | 2169 | db = (struct db_descriptor *) d; |
2174 | db->control = cpu_to_le16(DESCRIPTOR_STATUS | | 2170 | db->control = cpu_to_le16(DESCRIPTOR_STATUS | |
2175 | DESCRIPTOR_BRANCH_ALWAYS); | 2171 | DESCRIPTOR_BRANCH_ALWAYS); |
2176 | db->first_size = cpu_to_le16(ctx->base.header_size + 4); | 2172 | db->first_size = |
2173 | cpu_to_le16(max(ctx->base.header_size, (size_t)8)); | ||
2177 | if (p->skip && rest == p->payload_length) { | 2174 | if (p->skip && rest == p->payload_length) { |
2178 | db->control |= cpu_to_le16(DESCRIPTOR_WAIT); | 2175 | db->control |= cpu_to_le16(DESCRIPTOR_WAIT); |
2179 | db->first_req_count = db->first_size; | 2176 | db->first_req_count = db->first_size; |
@@ -2223,11 +2220,11 @@ ohci_queue_iso_receive_packet_per_buffer(struct fw_iso_context *base, | |||
2223 | int page, offset, packet_count, header_size, payload_per_buffer; | 2220 | int page, offset, packet_count, header_size, payload_per_buffer; |
2224 | 2221 | ||
2225 | /* | 2222 | /* |
2226 | * The OHCI controller puts the status word in the | 2223 | * The OHCI controller puts the isochronous header and trailer in the |
2227 | * buffer too, so we need 4 extra bytes per packet. | 2224 | * buffer, so we need at least 8 bytes. |
2228 | */ | 2225 | */ |
2229 | packet_count = p->header_length / ctx->base.header_size; | 2226 | packet_count = p->header_length / ctx->base.header_size; |
2230 | header_size = ctx->base.header_size + 4; | 2227 | header_size = max(ctx->base.header_size, (size_t)8); |
2231 | 2228 | ||
2232 | /* Get header size in number of descriptors. */ | 2229 | /* Get header size in number of descriptors. */ |
2233 | header_z = DIV_ROUND_UP(header_size, sizeof(*d)); | 2230 | header_z = DIV_ROUND_UP(header_size, sizeof(*d)); |