|
@@ -38,6 +38,7 @@
|
|
|
#include <linux/vmalloc.h>
|
|
|
#include <linux/uaccess.h>
|
|
|
#include <linux/io.h>
|
|
|
+#include <linux/delay.h>
|
|
|
#include <linux/hardirq.h>
|
|
|
|
|
|
#include <xen/xen.h>
|
|
@@ -823,6 +824,52 @@ unsigned int gnttab_max_grant_frames(void)
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(gnttab_max_grant_frames);
|
|
|
|
|
|
+/* Handling of paged out grant targets (GNTST_eagain) */
|
|
|
+#define MAX_DELAY 256
|
|
|
+static inline void
|
|
|
+gnttab_retry_eagain_gop(unsigned int cmd, void *gop, int16_t *status,
|
|
|
+ const char *func)
|
|
|
+{
|
|
|
+ unsigned delay = 1;
|
|
|
+
|
|
|
+ do {
|
|
|
+ BUG_ON(HYPERVISOR_grant_table_op(cmd, gop, 1));
|
|
|
+ if (*status == GNTST_eagain)
|
|
|
+ msleep(delay++);
|
|
|
+ } while ((*status == GNTST_eagain) && (delay < MAX_DELAY));
|
|
|
+
|
|
|
+ if (delay >= MAX_DELAY) {
|
|
|
+ printk(KERN_ERR "%s: %s eagain grant\n", func, current->comm);
|
|
|
+ *status = GNTST_bad_page;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void gnttab_batch_map(struct gnttab_map_grant_ref *batch, unsigned count)
|
|
|
+{
|
|
|
+ struct gnttab_map_grant_ref *op;
|
|
|
+
|
|
|
+ if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, batch, count))
|
|
|
+ BUG();
|
|
|
+ for (op = batch; op < batch + count; op++)
|
|
|
+ if (op->status == GNTST_eagain)
|
|
|
+ gnttab_retry_eagain_gop(GNTTABOP_map_grant_ref, op,
|
|
|
+ &op->status, __func__);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(gnttab_batch_map);
|
|
|
+
|
|
|
+void gnttab_batch_copy(struct gnttab_copy *batch, unsigned count)
|
|
|
+{
|
|
|
+ struct gnttab_copy *op;
|
|
|
+
|
|
|
+ if (HYPERVISOR_grant_table_op(GNTTABOP_copy, batch, count))
|
|
|
+ BUG();
|
|
|
+ for (op = batch; op < batch + count; op++)
|
|
|
+ if (op->status == GNTST_eagain)
|
|
|
+ gnttab_retry_eagain_gop(GNTTABOP_copy, op,
|
|
|
+ &op->status, __func__);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(gnttab_batch_copy);
|
|
|
+
|
|
|
int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
|
|
|
struct gnttab_map_grant_ref *kmap_ops,
|
|
|
struct page **pages, unsigned int count)
|
|
@@ -836,6 +883,12 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
|
+ /* Retry eagain maps */
|
|
|
+ for (i = 0; i < count; i++)
|
|
|
+ if (map_ops[i].status == GNTST_eagain)
|
|
|
+ gnttab_retry_eagain_gop(GNTTABOP_map_grant_ref, map_ops + i,
|
|
|
+ &map_ops[i].status, __func__);
|
|
|
+
|
|
|
if (xen_feature(XENFEAT_auto_translated_physmap))
|
|
|
return ret;
|
|
|
|