Merge tag 'ioremap-5.5' of git://git.infradead.org/users/hch/ioremap
[linux-2.6-microblaze.git] / kernel / events / ring_buffer.c
index ffb59a4..7ffd5c7 100644 (file)
@@ -562,6 +562,42 @@ void *perf_get_aux(struct perf_output_handle *handle)
 }
 EXPORT_SYMBOL_GPL(perf_get_aux);
 
+/*
+ * Copy out AUX data from an AUX handle.
+ */
+long perf_output_copy_aux(struct perf_output_handle *aux_handle,
+                         struct perf_output_handle *handle,
+                         unsigned long from, unsigned long to)
+{
+       unsigned long tocopy, remainder, len = 0;
+       struct ring_buffer *rb = aux_handle->rb;
+       void *addr;
+
+       from &= (rb->aux_nr_pages << PAGE_SHIFT) - 1;
+       to &= (rb->aux_nr_pages << PAGE_SHIFT) - 1;
+
+       do {
+               tocopy = PAGE_SIZE - offset_in_page(from);
+               if (to > from)
+                       tocopy = min(tocopy, to - from);
+               if (!tocopy)
+                       break;
+
+               addr = rb->aux_pages[from >> PAGE_SHIFT];
+               addr += offset_in_page(from);
+
+               remainder = perf_output_copy(handle, addr, tocopy);
+               if (remainder)
+                       return -EFAULT;
+
+               len += tocopy;
+               from += tocopy;
+               from &= (rb->aux_nr_pages << PAGE_SHIFT) - 1;
+       } while (to != from);
+
+       return len;
+}
+
 #define PERF_AUX_GFP   (GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN | __GFP_NORETRY)
 
 static struct page *rb_alloc_aux_page(int node, int order)
@@ -754,6 +790,14 @@ static void *perf_mmap_alloc_page(int cpu)
        return page_address(page);
 }
 
+static void perf_mmap_free_page(void *addr)
+{
+       struct page *page = virt_to_page(addr);
+
+       page->mapping = NULL;
+       __free_page(page);
+}
+
 struct ring_buffer *rb_alloc(int nr_pages, long watermark, int cpu, int flags)
 {
        struct ring_buffer *rb;
@@ -788,9 +832,9 @@ struct ring_buffer *rb_alloc(int nr_pages, long watermark, int cpu, int flags)
 
 fail_data_pages:
        for (i--; i >= 0; i--)
-               free_page((unsigned long)rb->data_pages[i]);
+               perf_mmap_free_page(rb->data_pages[i]);
 
-       free_page((unsigned long)rb->user_page);
+       perf_mmap_free_page(rb->user_page);
 
 fail_user_page:
        kfree(rb);
@@ -799,21 +843,13 @@ fail:
        return NULL;
 }
 
-static void perf_mmap_free_page(unsigned long addr)
-{
-       struct page *page = virt_to_page((void *)addr);
-
-       page->mapping = NULL;
-       __free_page(page);
-}
-
 void rb_free(struct ring_buffer *rb)
 {
        int i;
 
-       perf_mmap_free_page((unsigned long)rb->user_page);
+       perf_mmap_free_page(rb->user_page);
        for (i = 0; i < rb->nr_pages; i++)
-               perf_mmap_free_page((unsigned long)rb->data_pages[i]);
+               perf_mmap_free_page(rb->data_pages[i]);
        kfree(rb);
 }