Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 275941 Details for
Bug 344851
[firewire] juju stack lacks full support for ohci 1.0 controllers
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
v3 of FireWire OHCI 1.0 Iso Receive support
linux-2.6-firewire-ohci-1.0-iso-receive.patch (text/plain), 7.73 KB, created by
Jarod Wilson
on 2007-12-03 18:11:18 UTC
(
hide
)
Description:
v3 of FireWire OHCI 1.0 Iso Receive support
Filename:
MIME Type:
Creator:
Jarod Wilson
Created:
2007-12-03 18:11:18 UTC
Size:
7.73 KB
patch
obsolete
>diff -Naurp linux-2.6.23.noarch/drivers/firewire/fw-ohci.c linux-2.6.23.noarch.fw/drivers/firewire/fw-ohci.c >--- linux-2.6.23.noarch/drivers/firewire/fw-ohci.c 2007-10-09 16:31:38.000000000 -0400 >+++ linux-2.6.23.noarch.fw/drivers/firewire/fw-ohci.c 2007-12-03 09:40:47.000000000 -0500 >@@ -435,6 +435,21 @@ static void ar_context_run(struct ar_con > flush_writes(ctx->ohci); > } > >+static struct descriptor * >+find_branch_descriptor(struct descriptor *d, int z) >+{ >+ int b, key; >+ >+ b = (le16_to_cpu(d->control) & DESCRIPTOR_BRANCH_ALWAYS) >> 2; >+ key = (le16_to_cpu(d->control) & DESCRIPTOR_KEY_IMMEDIATE) >> 8; >+ >+ /* figure out which descriptor the branch address goes in */ >+ if (z == 2 && (b == 3 || key == 2)) >+ return d; >+ else >+ return d + z - 1; >+} >+ > static void context_tasklet(unsigned long data) > { > struct context *ctx = (struct context *) data; >@@ -453,7 +468,7 @@ static void context_tasklet(unsigned lon > address = le32_to_cpu(last->branch_address); > z = address & 0xf; > d = ctx->buffer + (address - ctx->buffer_bus) / sizeof(*d); >- last = (z == 2) ? d : d + z - 1; >+ last = find_branch_descriptor(d, z); > > if (!ctx->callback(ctx, d, last)) > break; >@@ -564,7 +579,7 @@ static void context_append(struct contex > > ctx->head_descriptor = d + z + extra; > ctx->prev_descriptor->branch_address = cpu_to_le32(d_bus | z); >- ctx->prev_descriptor = z == 2 ? d : d + z - 1; >+ ctx->prev_descriptor = find_branch_descriptor(d, z); > > dma_sync_single_for_device(ctx->ohci->card.device, ctx->buffer_bus, > ctx->buffer_size, DMA_TO_DEVICE); >@@ -653,7 +668,7 @@ at_context_queue_packet(struct context * > driver_data = (struct driver_data *) &d[3]; > driver_data->packet = packet; > packet->driver_data = driver_data; >- >+ > if (packet->payload_length > 0) { > payload_bus = > dma_map_single(ohci->card.device, packet->payload, >@@ -898,7 +913,7 @@ at_context_transmit(struct context *ctx, > > if (retval < 0) > packet->callback(packet, &ctx->ohci->card, packet->ack); >- >+ > } > > static void bus_reset_tasklet(unsigned long data) >@@ -1403,6 +1418,57 @@ static int handle_ir_dualbuffer_packet(s > return 1; > } > >+static int handle_ir_packet_per_buffer(struct context *context, >+ struct descriptor *d, >+ struct descriptor *last) >+{ >+ struct iso_context *ctx = >+ container_of(context, struct iso_context, context); >+ struct descriptor *pd = d + 1; >+ __le32 *ir_header; >+ size_t header_length; >+ void *p, *end; >+ int i, z; >+ >+ if (pd->res_count == pd->req_count) >+ /* Descriptor(s) not done yet, stop iteration */ >+ return 0; >+ >+ header_length = le16_to_cpu(d->req_count); >+ >+ i = ctx->header_length; >+ z = le32_to_cpu(pd->branch_address) & 0xf; >+ p = d + z; >+ end = p + header_length; >+ >+ while (p < end && i + ctx->base.header_size <= PAGE_SIZE) { >+ /* >+ * The iso header is byteswapped to little endian by >+ * the controller, but the remaining header quadlets >+ * are big endian. We want to present all the headers >+ * as big endian, so we have to swap the first quadlet. >+ */ >+ *(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4)); >+ memcpy(ctx->header + i + 4, p + 8, ctx->base.header_size - 4); >+ i += ctx->base.header_size; >+ p += ctx->base.header_size + 4; >+ } >+ >+ ctx->header_length = i; >+ >+ if (le16_to_cpu(pd->control) & DESCRIPTOR_IRQ_ALWAYS) { >+ ir_header = (__le32 *) (d + z); >+ ctx->base.callback(&ctx->base, >+ le32_to_cpu(ir_header[0]) & 0xffff, >+ ctx->header_length, ctx->header, >+ ctx->base.callback_data); >+ ctx->header_length = 0; >+ } >+ >+ >+ return 1; >+} >+ > static int handle_it_packet(struct context *context, > struct descriptor *d, > struct descriptor *last) >@@ -1438,14 +1504,12 @@ ohci_allocate_iso_context(struct fw_card > } else { > mask = &ohci->ir_context_mask; > list = ohci->ir_context_list; >- callback = handle_ir_dualbuffer_packet; >+ if (ohci->version >= OHCI_VERSION_1_1) >+ callback = handle_ir_dualbuffer_packet; >+ else >+ callback = handle_ir_packet_per_buffer; > } > >- /* FIXME: We need a fallback for pre 1.1 OHCI. */ >- if (callback == handle_ir_dualbuffer_packet && >- ohci->version < OHCI_VERSION_1_1) >- return ERR_PTR(-EINVAL); >- > spin_lock_irqsave(&ohci->lock, flags); > index = ffs(*mask) - 1; > if (index >= 0) >@@ -1504,7 +1568,9 @@ static int ohci_start_iso(struct fw_iso_ > context_run(&ctx->context, match); > } else { > index = ctx - ohci->ir_context_list; >- control = IR_CONTEXT_DUAL_BUFFER_MODE | IR_CONTEXT_ISOCH_HEADER; >+ control = IR_CONTEXT_ISOCH_HEADER; >+ if (ohci->version >= OHCI_VERSION_1_1) >+ control |= IR_CONTEXT_DUAL_BUFFER_MODE; > match = (tags << 28) | (sync << 8) | ctx->base.channel; > if (cycle >= 0) { > match |= (cycle & 0x07fff) << 12; >@@ -1710,7 +1776,6 @@ ohci_queue_iso_receive_dualbuffer(struct > offset = payload & ~PAGE_MASK; > rest = p->payload_length; > >- /* FIXME: OHCI 1.0 doesn't support dual buffer receive */ > /* FIXME: make packet-per-buffer/dual-buffer a context option */ > while (rest > 0) { > d = context_get_descriptors(&ctx->context, >@@ -1749,6 +1814,81 @@ ohci_queue_iso_receive_dualbuffer(struct > } > > static int >+ohci_queue_iso_receive_packet_per_buffer(struct fw_iso_context *base, >+ struct fw_iso_packet *packet, >+ struct fw_iso_buffer *buffer, >+ unsigned long payload) >+{ >+ struct iso_context *ctx = container_of(base, struct iso_context, base); >+ struct descriptor *d = NULL, *pd = NULL; >+ struct fw_iso_packet *p; >+ dma_addr_t d_bus, page_bus; >+ u32 z, header_z, rest; >+ int i, page, offset, packet_count, header_size; >+ >+ if (packet->skip) { >+ d = context_get_descriptors(&ctx->context, 1, &d_bus); >+ if (d == NULL) >+ return -ENOMEM; >+ >+ d->control = cpu_to_le16(DESCRIPTOR_STATUS | >+ DESCRIPTOR_INPUT_LAST | >+ DESCRIPTOR_BRANCH_ALWAYS | >+ DESCRIPTOR_WAIT); >+ context_append(&ctx->context, d, 1, 0); >+ } >+ >+ /* Set up one descriptor for header, one for payload */ >+ /* FIXME: handle cases where we need multiple desc. for payload */ >+ z = 2; >+ p = packet; >+ >+ /* >+ * The OHCI controller puts the status word in the >+ * buffer too, so we need 4 extra bytes per packet. >+ */ >+ packet_count = p->header_length / ctx->base.header_size; >+ header_size = packet_count * (ctx->base.header_size + 4); >+ >+ /* Get header size in number of descriptors. */ >+ header_z = DIV_ROUND_UP(header_size, sizeof(*d)); >+ page = payload >> PAGE_SHIFT; >+ offset = payload & ~PAGE_MASK; >+ rest = p->payload_length; >+ >+ for (i = 0; i < packet_count; i++) { >+ /* d points to the header descriptor */ >+ d = context_get_descriptors(&ctx->context, >+ z + header_z, &d_bus); >+ if (d == NULL) >+ return -ENOMEM; >+ >+ d->control = cpu_to_le16(DESCRIPTOR_INPUT_MORE); >+ d->req_count = cpu_to_le16(header_size); >+ d->res_count = d->req_count; >+ d->data_address = cpu_to_le32(d_bus + (z * sizeof(*d))); >+ >+ /* pd points to the payload descriptor */ >+ pd = d + 1; >+ pd->control = cpu_to_le16(DESCRIPTOR_STATUS | >+ DESCRIPTOR_INPUT_LAST | >+ DESCRIPTOR_BRANCH_ALWAYS); >+ if (p->interrupt) >+ pd->control |= cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS); >+ >+ pd->req_count = cpu_to_le16(rest); >+ pd->res_count = pd->req_count; >+ >+ page_bus = page_private(buffer->pages[page]); >+ pd->data_address = cpu_to_le32(page_bus + offset); >+ >+ context_append(&ctx->context, d, z, header_z); >+ } >+ >+ return 0; >+} >+ >+static int > ohci_queue_iso(struct fw_iso_context *base, > struct fw_iso_packet *packet, > struct fw_iso_buffer *buffer, >@@ -1762,8 +1902,9 @@ ohci_queue_iso(struct fw_iso_context *ba > return ohci_queue_iso_receive_dualbuffer(base, packet, > buffer, payload); > else >- /* FIXME: Implement fallback for OHCI 1.0 controllers. */ >- return -EINVAL; >+ return ohci_queue_iso_receive_packet_per_buffer(base, packet, >+ buffer, >+ payload); > } > > static const struct fw_card_driver ohci_driver = {
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 344851
:
233701
|
257711
|
274231
|
274241
| 275941 |
275971