diff options
Diffstat (limited to 'drivers/xen')
-rw-r--r-- | drivers/xen/grant-table.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 89dcca448bb6..17972fbacddc 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/io.h> | 42 | #include <linux/io.h> |
43 | #include <linux/delay.h> | 43 | #include <linux/delay.h> |
44 | #include <linux/hardirq.h> | 44 | #include <linux/hardirq.h> |
45 | #include <linux/workqueue.h> | ||
45 | 46 | ||
46 | #include <xen/xen.h> | 47 | #include <xen/xen.h> |
47 | #include <xen/interface/xen.h> | 48 | #include <xen/interface/xen.h> |
@@ -819,6 +820,49 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, | |||
819 | } | 820 | } |
820 | EXPORT_SYMBOL_GPL(gnttab_unmap_refs); | 821 | EXPORT_SYMBOL_GPL(gnttab_unmap_refs); |
821 | 822 | ||
823 | #define GNTTAB_UNMAP_REFS_DELAY 5 | ||
824 | |||
825 | static void __gnttab_unmap_refs_async(struct gntab_unmap_queue_data* item); | ||
826 | |||
827 | static void gnttab_unmap_work(struct work_struct *work) | ||
828 | { | ||
829 | struct gntab_unmap_queue_data | ||
830 | *unmap_data = container_of(work, | ||
831 | struct gntab_unmap_queue_data, | ||
832 | gnttab_work.work); | ||
833 | if (unmap_data->age != UINT_MAX) | ||
834 | unmap_data->age++; | ||
835 | __gnttab_unmap_refs_async(unmap_data); | ||
836 | } | ||
837 | |||
838 | static void __gnttab_unmap_refs_async(struct gntab_unmap_queue_data* item) | ||
839 | { | ||
840 | int ret; | ||
841 | int pc; | ||
842 | |||
843 | for (pc = 0; pc < item->count; pc++) { | ||
844 | if (page_count(item->pages[pc]) > 1) { | ||
845 | unsigned long delay = GNTTAB_UNMAP_REFS_DELAY * (item->age + 1); | ||
846 | schedule_delayed_work(&item->gnttab_work, | ||
847 | msecs_to_jiffies(delay)); | ||
848 | return; | ||
849 | } | ||
850 | } | ||
851 | |||
852 | ret = gnttab_unmap_refs(item->unmap_ops, item->kunmap_ops, | ||
853 | item->pages, item->count); | ||
854 | item->done(ret, item); | ||
855 | } | ||
856 | |||
857 | void gnttab_unmap_refs_async(struct gntab_unmap_queue_data* item) | ||
858 | { | ||
859 | INIT_DELAYED_WORK(&item->gnttab_work, gnttab_unmap_work); | ||
860 | item->age = 0; | ||
861 | |||
862 | __gnttab_unmap_refs_async(item); | ||
863 | } | ||
864 | EXPORT_SYMBOL_GPL(gnttab_unmap_refs_async); | ||
865 | |||
822 | static int gnttab_map_frames_v1(xen_pfn_t *frames, unsigned int nr_gframes) | 866 | static int gnttab_map_frames_v1(xen_pfn_t *frames, unsigned int nr_gframes) |
823 | { | 867 | { |
824 | int rc; | 868 | int rc; |