diff options
Diffstat (limited to 'drivers/xen/grant-table.c')
-rw-r--r-- | drivers/xen/grant-table.c | 67 |
1 files changed, 60 insertions, 7 deletions
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 006726688baf..b2b0a375b348 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/vmalloc.h> | 38 | #include <linux/vmalloc.h> |
39 | #include <linux/uaccess.h> | 39 | #include <linux/uaccess.h> |
40 | #include <linux/io.h> | 40 | #include <linux/io.h> |
41 | #include <linux/delay.h> | ||
41 | #include <linux/hardirq.h> | 42 | #include <linux/hardirq.h> |
42 | 43 | ||
43 | #include <xen/xen.h> | 44 | #include <xen/xen.h> |
@@ -47,6 +48,7 @@ | |||
47 | #include <xen/interface/memory.h> | 48 | #include <xen/interface/memory.h> |
48 | #include <xen/hvc-console.h> | 49 | #include <xen/hvc-console.h> |
49 | #include <asm/xen/hypercall.h> | 50 | #include <asm/xen/hypercall.h> |
51 | #include <asm/xen/interface.h> | ||
50 | 52 | ||
51 | #include <asm/pgtable.h> | 53 | #include <asm/pgtable.h> |
52 | #include <asm/sync_bitops.h> | 54 | #include <asm/sync_bitops.h> |
@@ -285,10 +287,9 @@ int gnttab_grant_foreign_access(domid_t domid, unsigned long frame, | |||
285 | } | 287 | } |
286 | EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access); | 288 | EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access); |
287 | 289 | ||
288 | void gnttab_update_subpage_entry_v2(grant_ref_t ref, domid_t domid, | 290 | static void gnttab_update_subpage_entry_v2(grant_ref_t ref, domid_t domid, |
289 | unsigned long frame, int flags, | 291 | unsigned long frame, int flags, |
290 | unsigned page_off, | 292 | unsigned page_off, unsigned length) |
291 | unsigned length) | ||
292 | { | 293 | { |
293 | gnttab_shared.v2[ref].sub_page.frame = frame; | 294 | gnttab_shared.v2[ref].sub_page.frame = frame; |
294 | gnttab_shared.v2[ref].sub_page.page_off = page_off; | 295 | gnttab_shared.v2[ref].sub_page.page_off = page_off; |
@@ -345,9 +346,9 @@ bool gnttab_subpage_grants_available(void) | |||
345 | } | 346 | } |
346 | EXPORT_SYMBOL_GPL(gnttab_subpage_grants_available); | 347 | EXPORT_SYMBOL_GPL(gnttab_subpage_grants_available); |
347 | 348 | ||
348 | void gnttab_update_trans_entry_v2(grant_ref_t ref, domid_t domid, | 349 | static void gnttab_update_trans_entry_v2(grant_ref_t ref, domid_t domid, |
349 | int flags, domid_t trans_domid, | 350 | int flags, domid_t trans_domid, |
350 | grant_ref_t trans_gref) | 351 | grant_ref_t trans_gref) |
351 | { | 352 | { |
352 | gnttab_shared.v2[ref].transitive.trans_domid = trans_domid; | 353 | gnttab_shared.v2[ref].transitive.trans_domid = trans_domid; |
353 | gnttab_shared.v2[ref].transitive.gref = trans_gref; | 354 | gnttab_shared.v2[ref].transitive.gref = trans_gref; |
@@ -823,6 +824,52 @@ unsigned int gnttab_max_grant_frames(void) | |||
823 | } | 824 | } |
824 | EXPORT_SYMBOL_GPL(gnttab_max_grant_frames); | 825 | EXPORT_SYMBOL_GPL(gnttab_max_grant_frames); |
825 | 826 | ||
827 | /* Handling of paged out grant targets (GNTST_eagain) */ | ||
828 | #define MAX_DELAY 256 | ||
829 | static inline void | ||
830 | gnttab_retry_eagain_gop(unsigned int cmd, void *gop, int16_t *status, | ||
831 | const char *func) | ||
832 | { | ||
833 | unsigned delay = 1; | ||
834 | |||
835 | do { | ||
836 | BUG_ON(HYPERVISOR_grant_table_op(cmd, gop, 1)); | ||
837 | if (*status == GNTST_eagain) | ||
838 | msleep(delay++); | ||
839 | } while ((*status == GNTST_eagain) && (delay < MAX_DELAY)); | ||
840 | |||
841 | if (delay >= MAX_DELAY) { | ||
842 | printk(KERN_ERR "%s: %s eagain grant\n", func, current->comm); | ||
843 | *status = GNTST_bad_page; | ||
844 | } | ||
845 | } | ||
846 | |||
847 | void gnttab_batch_map(struct gnttab_map_grant_ref *batch, unsigned count) | ||
848 | { | ||
849 | struct gnttab_map_grant_ref *op; | ||
850 | |||
851 | if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, batch, count)) | ||
852 | BUG(); | ||
853 | for (op = batch; op < batch + count; op++) | ||
854 | if (op->status == GNTST_eagain) | ||
855 | gnttab_retry_eagain_gop(GNTTABOP_map_grant_ref, op, | ||
856 | &op->status, __func__); | ||
857 | } | ||
858 | EXPORT_SYMBOL_GPL(gnttab_batch_map); | ||
859 | |||
860 | void gnttab_batch_copy(struct gnttab_copy *batch, unsigned count) | ||
861 | { | ||
862 | struct gnttab_copy *op; | ||
863 | |||
864 | if (HYPERVISOR_grant_table_op(GNTTABOP_copy, batch, count)) | ||
865 | BUG(); | ||
866 | for (op = batch; op < batch + count; op++) | ||
867 | if (op->status == GNTST_eagain) | ||
868 | gnttab_retry_eagain_gop(GNTTABOP_copy, op, | ||
869 | &op->status, __func__); | ||
870 | } | ||
871 | EXPORT_SYMBOL_GPL(gnttab_batch_copy); | ||
872 | |||
826 | int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, | 873 | int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, |
827 | struct gnttab_map_grant_ref *kmap_ops, | 874 | struct gnttab_map_grant_ref *kmap_ops, |
828 | struct page **pages, unsigned int count) | 875 | struct page **pages, unsigned int count) |
@@ -836,6 +883,12 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, | |||
836 | if (ret) | 883 | if (ret) |
837 | return ret; | 884 | return ret; |
838 | 885 | ||
886 | /* Retry eagain maps */ | ||
887 | for (i = 0; i < count; i++) | ||
888 | if (map_ops[i].status == GNTST_eagain) | ||
889 | gnttab_retry_eagain_gop(GNTTABOP_map_grant_ref, map_ops + i, | ||
890 | &map_ops[i].status, __func__); | ||
891 | |||
839 | if (xen_feature(XENFEAT_auto_translated_physmap)) | 892 | if (xen_feature(XENFEAT_auto_translated_physmap)) |
840 | return ret; | 893 | return ret; |
841 | 894 | ||