aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire
diff options
context:
space:
mode:
authorDavid Moore <dcm@acm.org>2008-07-23 02:23:40 -0400
committerStefan Richter <stefanr@s5r6.in-berlin.de>2009-03-24 15:56:35 -0400
commit1aa292bb1c53500e3ab570b955d03afa97a9404d (patch)
tree738675d2cd801012b6626628223c2a20c6e5d352 /drivers/firewire
parent8e0ee43bc2c3e19db56a4adaa9a9b04ce885cd84 (diff)
firewire: Include iso timestamp in headers when header_size > 4
Previously, when an iso context had header_size > 4, the iso header (len/tag/channel/tcode/sy) was passed to userspace followed by quadlets stripped from the payload. This patch changes the behavior: header_size = 8 now passes the header quadlet followed by the timestamp quadlet. When header_size > 8, quadlets are stripped from the payload. The header_size = 4 case remains identical. Since this alters the semantics of the API, the firewire API version needs to be bumped concurrently with this change. This change also refactors the header copying code slightly to be much easier to read. Signed-off-by: David Moore <dcm@acm.org> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire')
-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));