aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire/fw-ohci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firewire/fw-ohci.c')
-rw-r--r--drivers/firewire/fw-ohci.c73
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
1768static 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
1768static int handle_ir_dualbuffer_packet(struct context *context, 1790static 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));