aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/xen-netback/netback.c11
-rw-r--r--drivers/xen/grant-table.c53
-rw-r--r--drivers/xen/xenbus/xenbus_client.c6
-rw-r--r--include/xen/grant_table.h12
4 files changed, 70 insertions, 12 deletions
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 682633bfe00f..05593d882023 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -635,9 +635,7 @@ static void xen_netbk_rx_action(struct xen_netbk *netbk)
635 return; 635 return;
636 636
637 BUG_ON(npo.copy_prod > ARRAY_SIZE(netbk->grant_copy_op)); 637 BUG_ON(npo.copy_prod > ARRAY_SIZE(netbk->grant_copy_op));
638 ret = HYPERVISOR_grant_table_op(GNTTABOP_copy, &netbk->grant_copy_op, 638 gnttab_batch_copy(netbk->grant_copy_op, npo.copy_prod);
639 npo.copy_prod);
640 BUG_ON(ret != 0);
641 639
642 while ((skb = __skb_dequeue(&rxq)) != NULL) { 640 while ((skb = __skb_dequeue(&rxq)) != NULL) {
643 sco = (struct skb_cb_overlay *)skb->cb; 641 sco = (struct skb_cb_overlay *)skb->cb;
@@ -1460,18 +1458,15 @@ static void xen_netbk_tx_submit(struct xen_netbk *netbk)
1460static void xen_netbk_tx_action(struct xen_netbk *netbk) 1458static void xen_netbk_tx_action(struct xen_netbk *netbk)
1461{ 1459{
1462 unsigned nr_gops; 1460 unsigned nr_gops;
1463 int ret;
1464 1461
1465 nr_gops = xen_netbk_tx_build_gops(netbk); 1462 nr_gops = xen_netbk_tx_build_gops(netbk);
1466 1463
1467 if (nr_gops == 0) 1464 if (nr_gops == 0)
1468 return; 1465 return;
1469 ret = HYPERVISOR_grant_table_op(GNTTABOP_copy,
1470 netbk->tx_copy_ops, nr_gops);
1471 BUG_ON(ret);
1472 1466
1473 xen_netbk_tx_submit(netbk); 1467 gnttab_batch_copy(netbk->tx_copy_ops, nr_gops);
1474 1468
1469 xen_netbk_tx_submit(netbk);
1475} 1470}
1476 1471
1477static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx) 1472static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx)
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index eea81cf8a2a5..3a567b15600b 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>
@@ -823,6 +824,52 @@ unsigned int gnttab_max_grant_frames(void)
823} 824}
824EXPORT_SYMBOL_GPL(gnttab_max_grant_frames); 825EXPORT_SYMBOL_GPL(gnttab_max_grant_frames);
825 826
827/* Handling of paged out grant targets (GNTST_eagain) */
828#define MAX_DELAY 256
829static inline void
830gnttab_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
847void 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}
858EXPORT_SYMBOL_GPL(gnttab_batch_map);
859
860void 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}
871EXPORT_SYMBOL_GPL(gnttab_batch_copy);
872
826int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, 873int 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
diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c
index b3e146edb51d..bcf3ba4a6ec1 100644
--- a/drivers/xen/xenbus/xenbus_client.c
+++ b/drivers/xen/xenbus/xenbus_client.c
@@ -490,8 +490,7 @@ static int xenbus_map_ring_valloc_pv(struct xenbus_device *dev,
490 490
491 op.host_addr = arbitrary_virt_to_machine(pte).maddr; 491 op.host_addr = arbitrary_virt_to_machine(pte).maddr;
492 492
493 if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) 493 gnttab_batch_map(&op, 1);
494 BUG();
495 494
496 if (op.status != GNTST_okay) { 495 if (op.status != GNTST_okay) {
497 free_vm_area(area); 496 free_vm_area(area);
@@ -572,8 +571,7 @@ int xenbus_map_ring(struct xenbus_device *dev, int gnt_ref,
572 gnttab_set_map_op(&op, (unsigned long)vaddr, GNTMAP_host_map, gnt_ref, 571 gnttab_set_map_op(&op, (unsigned long)vaddr, GNTMAP_host_map, gnt_ref,
573 dev->otherend_id); 572 dev->otherend_id);
574 573
575 if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) 574 gnttab_batch_map(&op, 1);
576 BUG();
577 575
578 if (op.status != GNTST_okay) { 576 if (op.status != GNTST_okay) {
579 xenbus_dev_fatal(dev, op.status, 577 xenbus_dev_fatal(dev, op.status,
diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h
index 11e27c3af3cb..ba0d77529a29 100644
--- a/include/xen/grant_table.h
+++ b/include/xen/grant_table.h
@@ -189,4 +189,16 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
189int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, 189int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
190 struct page **pages, unsigned int count, bool clear_pte); 190 struct page **pages, unsigned int count, bool clear_pte);
191 191
192/* Perform a batch of grant map/copy operations. Retry every batch slot
193 * for which the hypervisor returns GNTST_eagain. This is typically due
194 * to paged out target frames.
195 *
196 * Will retry for 1, 2, ... 255 ms, i.e. 256 times during 32 seconds.
197 *
198 * Return value in each iand every status field of the batch guaranteed
199 * to not be GNTST_eagain.
200 */
201void gnttab_batch_map(struct gnttab_map_grant_ref *batch, unsigned count);
202void gnttab_batch_copy(struct gnttab_copy *batch, unsigned count);
203
192#endif /* __ASM_GNTTAB_H__ */ 204#endif /* __ASM_GNTTAB_H__ */