diff options
-rw-r--r-- | drivers/net/xen-netback/netback.c | 11 | ||||
-rw-r--r-- | drivers/xen/grant-table.c | 53 | ||||
-rw-r--r-- | drivers/xen/xenbus/xenbus_client.c | 6 | ||||
-rw-r--r-- | include/xen/grant_table.h | 12 |
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) | |||
1460 | static void xen_netbk_tx_action(struct xen_netbk *netbk) | 1458 | static 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 | ||
1477 | static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx) | 1472 | static 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 | } |
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 | ||
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, | |||
189 | int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, | 189 | int 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 | */ | ||
201 | void gnttab_batch_map(struct gnttab_map_grant_ref *batch, unsigned count); | ||
202 | void gnttab_batch_copy(struct gnttab_copy *batch, unsigned count); | ||
203 | |||
192 | #endif /* __ASM_GNTTAB_H__ */ | 204 | #endif /* __ASM_GNTTAB_H__ */ |