|
@@ -750,20 +750,19 @@ static void ar_context_tasklet(unsigned long data)
|
|
*/
|
|
*/
|
|
|
|
|
|
offset = offsetof(struct ar_buffer, data);
|
|
offset = offsetof(struct ar_buffer, data);
|
|
- start = buffer = ab;
|
|
|
|
|
|
+ start = ab;
|
|
start_bus = le32_to_cpu(ab->descriptor.data_address) - offset;
|
|
start_bus = le32_to_cpu(ab->descriptor.data_address) - offset;
|
|
|
|
+ buffer = ab->data;
|
|
|
|
|
|
ab = ab->next;
|
|
ab = ab->next;
|
|
d = &ab->descriptor;
|
|
d = &ab->descriptor;
|
|
- size = buffer + PAGE_SIZE - ctx->pointer;
|
|
|
|
|
|
+ size = start + PAGE_SIZE - ctx->pointer;
|
|
/* valid buffer data in the next page */
|
|
/* valid buffer data in the next page */
|
|
rest = le16_to_cpu(d->req_count) - le16_to_cpu(d->res_count);
|
|
rest = le16_to_cpu(d->req_count) - le16_to_cpu(d->res_count);
|
|
/* what actually fits in this page */
|
|
/* what actually fits in this page */
|
|
- size2 = min(rest, (size_t)PAGE_SIZE - size);
|
|
|
|
|
|
+ size2 = min(rest, (size_t)PAGE_SIZE - offset - size);
|
|
memmove(buffer, ctx->pointer, size);
|
|
memmove(buffer, ctx->pointer, size);
|
|
memcpy(buffer + size, ab->data, size2);
|
|
memcpy(buffer + size, ab->data, size2);
|
|
- ctx->current_buffer = ab;
|
|
|
|
- ctx->pointer = (void *) ab->data + rest;
|
|
|
|
|
|
|
|
while (size > 0) {
|
|
while (size > 0) {
|
|
void *next = handle_ar_packet(ctx, buffer);
|
|
void *next = handle_ar_packet(ctx, buffer);
|
|
@@ -782,22 +781,30 @@ static void ar_context_tasklet(unsigned long data)
|
|
size -= pktsize;
|
|
size -= pktsize;
|
|
/* fill up this page again */
|
|
/* fill up this page again */
|
|
size3 = min(rest - size2,
|
|
size3 = min(rest - size2,
|
|
- (size_t)PAGE_SIZE - size - size2);
|
|
|
|
|
|
+ (size_t)PAGE_SIZE - offset - size - size2);
|
|
memcpy(buffer + size + size2,
|
|
memcpy(buffer + size + size2,
|
|
(void *) ab->data + size2, size3);
|
|
(void *) ab->data + size2, size3);
|
|
size2 += size3;
|
|
size2 += size3;
|
|
}
|
|
}
|
|
|
|
|
|
- /* handle the packets that are fully in the next page */
|
|
|
|
- buffer = (void *) ab->data + (buffer - (start + size));
|
|
|
|
- end = (void *) ab->data + rest;
|
|
|
|
|
|
+ if (rest > 0) {
|
|
|
|
+ /* handle the packets that are fully in the next page */
|
|
|
|
+ buffer = (void *) ab->data +
|
|
|
|
+ (buffer - (start + offset + size));
|
|
|
|
+ end = (void *) ab->data + rest;
|
|
|
|
|
|
- while (buffer < end)
|
|
|
|
- buffer = handle_ar_packet(ctx, buffer);
|
|
|
|
|
|
+ while (buffer < end)
|
|
|
|
+ buffer = handle_ar_packet(ctx, buffer);
|
|
|
|
+
|
|
|
|
+ ctx->current_buffer = ab;
|
|
|
|
+ ctx->pointer = end;
|
|
|
|
|
|
- dma_free_coherent(ohci->card.device, PAGE_SIZE,
|
|
|
|
- start, start_bus);
|
|
|
|
- ar_context_add_page(ctx);
|
|
|
|
|
|
+ dma_free_coherent(ohci->card.device, PAGE_SIZE,
|
|
|
|
+ start, start_bus);
|
|
|
|
+ ar_context_add_page(ctx);
|
|
|
|
+ } else {
|
|
|
|
+ ctx->pointer = start + PAGE_SIZE;
|
|
|
|
+ }
|
|
} else {
|
|
} else {
|
|
buffer = ctx->pointer;
|
|
buffer = ctx->pointer;
|
|
ctx->pointer = end =
|
|
ctx->pointer = end =
|