|
@@ -739,7 +739,7 @@ static void ar_context_tasklet(unsigned long data)
|
|
|
d = &ab->descriptor;
|
|
|
|
|
|
if (d->res_count == 0) {
|
|
|
- size_t size, rest, offset;
|
|
|
+ size_t size, size2, rest, pktsize, size3, offset;
|
|
|
dma_addr_t start_bus;
|
|
|
void *start;
|
|
|
|
|
@@ -756,12 +756,41 @@ static void ar_context_tasklet(unsigned long data)
|
|
|
ab = ab->next;
|
|
|
d = &ab->descriptor;
|
|
|
size = buffer + PAGE_SIZE - ctx->pointer;
|
|
|
+ /* valid buffer data in the next page */
|
|
|
rest = le16_to_cpu(d->req_count) - le16_to_cpu(d->res_count);
|
|
|
+ /* what actually fits in this page */
|
|
|
+ size2 = min(rest, (size_t)PAGE_SIZE - size);
|
|
|
memmove(buffer, ctx->pointer, size);
|
|
|
- memcpy(buffer + size, ab->data, rest);
|
|
|
+ memcpy(buffer + size, ab->data, size2);
|
|
|
ctx->current_buffer = ab;
|
|
|
ctx->pointer = (void *) ab->data + rest;
|
|
|
- end = buffer + size + rest;
|
|
|
+
|
|
|
+ while (size > 0) {
|
|
|
+ void *next = handle_ar_packet(ctx, buffer);
|
|
|
+ pktsize = next - buffer;
|
|
|
+ if (pktsize >= size) {
|
|
|
+ /*
|
|
|
+ * We have handled all the data that was
|
|
|
+ * originally in this page, so we can now
|
|
|
+ * continue in the next page.
|
|
|
+ */
|
|
|
+ buffer = next;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ /* move the next packet to the start of the buffer */
|
|
|
+ memmove(buffer, next, size + size2 - pktsize);
|
|
|
+ size -= pktsize;
|
|
|
+ /* fill up this page again */
|
|
|
+ size3 = min(rest - size2,
|
|
|
+ (size_t)PAGE_SIZE - size - size2);
|
|
|
+ memcpy(buffer + size + size2,
|
|
|
+ (void *) ab->data + 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;
|
|
|
|
|
|
while (buffer < end)
|
|
|
buffer = handle_ar_packet(ctx, buffer);
|