diff options
-rw-r--r-- | drivers/net/xen-netback/common.h | 5 | ||||
-rw-r--r-- | drivers/net/xen-netback/interface.c | 5 | ||||
-rw-r--r-- | drivers/net/xen-netback/netback.c | 76 | ||||
-rw-r--r-- | drivers/net/xen-netback/xenbus.c | 1 |
4 files changed, 86 insertions, 1 deletions
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index c2642402b7a1..083ecc93fe5e 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h | |||
@@ -179,6 +179,8 @@ struct xenvif_queue { /* Per-queue data for xenvif */ | |||
179 | 179 | ||
180 | unsigned int rx_queue_max; | 180 | unsigned int rx_queue_max; |
181 | unsigned int rx_queue_len; | 181 | unsigned int rx_queue_len; |
182 | unsigned long last_rx_time; | ||
183 | bool stalled; | ||
182 | 184 | ||
183 | struct gnttab_copy grant_copy_op[MAX_GRANT_COPY_OPS]; | 185 | struct gnttab_copy grant_copy_op[MAX_GRANT_COPY_OPS]; |
184 | 186 | ||
@@ -232,6 +234,9 @@ struct xenvif { | |||
232 | /* Queues */ | 234 | /* Queues */ |
233 | struct xenvif_queue *queues; | 235 | struct xenvif_queue *queues; |
234 | unsigned int num_queues; /* active queues, resource allocated */ | 236 | unsigned int num_queues; /* active queues, resource allocated */ |
237 | unsigned int stalled_queues; | ||
238 | |||
239 | spinlock_t lock; | ||
235 | 240 | ||
236 | #ifdef CONFIG_DEBUG_FS | 241 | #ifdef CONFIG_DEBUG_FS |
237 | struct dentry *xenvif_dbg_root; | 242 | struct dentry *xenvif_dbg_root; |
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index a134d52f55b4..895fe84011e7 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c | |||
@@ -419,6 +419,8 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid, | |||
419 | vif->queues = NULL; | 419 | vif->queues = NULL; |
420 | vif->num_queues = 0; | 420 | vif->num_queues = 0; |
421 | 421 | ||
422 | spin_lock_init(&vif->lock); | ||
423 | |||
422 | dev->netdev_ops = &xenvif_netdev_ops; | 424 | dev->netdev_ops = &xenvif_netdev_ops; |
423 | dev->hw_features = NETIF_F_SG | | 425 | dev->hw_features = NETIF_F_SG | |
424 | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | | 426 | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | |
@@ -505,7 +507,6 @@ void xenvif_carrier_on(struct xenvif *vif) | |||
505 | dev_set_mtu(vif->dev, ETH_DATA_LEN); | 507 | dev_set_mtu(vif->dev, ETH_DATA_LEN); |
506 | netdev_update_features(vif->dev); | 508 | netdev_update_features(vif->dev); |
507 | set_bit(VIF_STATUS_CONNECTED, &vif->status); | 509 | set_bit(VIF_STATUS_CONNECTED, &vif->status); |
508 | netif_carrier_on(vif->dev); | ||
509 | if (netif_running(vif->dev)) | 510 | if (netif_running(vif->dev)) |
510 | xenvif_up(vif); | 511 | xenvif_up(vif); |
511 | rtnl_unlock(); | 512 | rtnl_unlock(); |
@@ -565,6 +566,8 @@ int xenvif_connect(struct xenvif_queue *queue, unsigned long tx_ring_ref, | |||
565 | disable_irq(queue->rx_irq); | 566 | disable_irq(queue->rx_irq); |
566 | } | 567 | } |
567 | 568 | ||
569 | queue->stalled = true; | ||
570 | |||
568 | task = kthread_create(xenvif_kthread_guest_rx, | 571 | task = kthread_create(xenvif_kthread_guest_rx, |
569 | (void *)queue, "%s-guest-rx", queue->name); | 572 | (void *)queue, "%s-guest-rx", queue->name); |
570 | if (IS_ERR(task)) { | 573 | if (IS_ERR(task)) { |
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 57aa3b507d32..6563f0713fc0 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c | |||
@@ -62,6 +62,13 @@ unsigned int rx_drain_timeout_msecs = 10000; | |||
62 | module_param(rx_drain_timeout_msecs, uint, 0444); | 62 | module_param(rx_drain_timeout_msecs, uint, 0444); |
63 | unsigned int rx_drain_timeout_jiffies; | 63 | unsigned int rx_drain_timeout_jiffies; |
64 | 64 | ||
65 | /* The length of time before the frontend is considered unresponsive | ||
66 | * because it isn't providing Rx slots. | ||
67 | */ | ||
68 | static unsigned int rx_stall_timeout_msecs = 60000; | ||
69 | module_param(rx_stall_timeout_msecs, uint, 0444); | ||
70 | static unsigned int rx_stall_timeout_jiffies; | ||
71 | |||
65 | unsigned int xenvif_max_queues; | 72 | unsigned int xenvif_max_queues; |
66 | module_param_named(max_queues, xenvif_max_queues, uint, 0644); | 73 | module_param_named(max_queues, xenvif_max_queues, uint, 0644); |
67 | MODULE_PARM_DESC(max_queues, | 74 | MODULE_PARM_DESC(max_queues, |
@@ -649,6 +656,8 @@ static void xenvif_rx_action(struct xenvif_queue *queue) | |||
649 | RING_IDX ring_slots_used; | 656 | RING_IDX ring_slots_used; |
650 | int i; | 657 | int i; |
651 | 658 | ||
659 | queue->last_rx_time = jiffies; | ||
660 | |||
652 | /* We need a cheap worse case estimate for the number of | 661 | /* We need a cheap worse case estimate for the number of |
653 | * slots we'll use. | 662 | * slots we'll use. |
654 | */ | 663 | */ |
@@ -1972,10 +1981,67 @@ err: | |||
1972 | return err; | 1981 | return err; |
1973 | } | 1982 | } |
1974 | 1983 | ||
1984 | static void xenvif_queue_carrier_off(struct xenvif_queue *queue) | ||
1985 | { | ||
1986 | struct xenvif *vif = queue->vif; | ||
1987 | |||
1988 | queue->stalled = true; | ||
1989 | |||
1990 | /* At least one queue has stalled? Disable the carrier. */ | ||
1991 | spin_lock(&vif->lock); | ||
1992 | if (vif->stalled_queues++ == 0) { | ||
1993 | netdev_info(vif->dev, "Guest Rx stalled"); | ||
1994 | netif_carrier_off(vif->dev); | ||
1995 | } | ||
1996 | spin_unlock(&vif->lock); | ||
1997 | } | ||
1998 | |||
1999 | static void xenvif_queue_carrier_on(struct xenvif_queue *queue) | ||
2000 | { | ||
2001 | struct xenvif *vif = queue->vif; | ||
2002 | |||
2003 | queue->last_rx_time = jiffies; /* Reset Rx stall detection. */ | ||
2004 | queue->stalled = false; | ||
2005 | |||
2006 | /* All queues are ready? Enable the carrier. */ | ||
2007 | spin_lock(&vif->lock); | ||
2008 | if (--vif->stalled_queues == 0) { | ||
2009 | netdev_info(vif->dev, "Guest Rx ready"); | ||
2010 | netif_carrier_on(vif->dev); | ||
2011 | } | ||
2012 | spin_unlock(&vif->lock); | ||
2013 | } | ||
2014 | |||
2015 | static bool xenvif_rx_queue_stalled(struct xenvif_queue *queue) | ||
2016 | { | ||
2017 | RING_IDX prod, cons; | ||
2018 | |||
2019 | prod = queue->rx.sring->req_prod; | ||
2020 | cons = queue->rx.req_cons; | ||
2021 | |||
2022 | return !queue->stalled | ||
2023 | && prod - cons < XEN_NETBK_RX_SLOTS_MAX | ||
2024 | && time_after(jiffies, | ||
2025 | queue->last_rx_time + rx_stall_timeout_jiffies); | ||
2026 | } | ||
2027 | |||
2028 | static bool xenvif_rx_queue_ready(struct xenvif_queue *queue) | ||
2029 | { | ||
2030 | RING_IDX prod, cons; | ||
2031 | |||
2032 | prod = queue->rx.sring->req_prod; | ||
2033 | cons = queue->rx.req_cons; | ||
2034 | |||
2035 | return queue->stalled | ||
2036 | && prod - cons >= XEN_NETBK_RX_SLOTS_MAX; | ||
2037 | } | ||
2038 | |||
1975 | static bool xenvif_have_rx_work(struct xenvif_queue *queue) | 2039 | static bool xenvif_have_rx_work(struct xenvif_queue *queue) |
1976 | { | 2040 | { |
1977 | return (!skb_queue_empty(&queue->rx_queue) | 2041 | return (!skb_queue_empty(&queue->rx_queue) |
1978 | && xenvif_rx_ring_slots_available(queue, XEN_NETBK_RX_SLOTS_MAX)) | 2042 | && xenvif_rx_ring_slots_available(queue, XEN_NETBK_RX_SLOTS_MAX)) |
2043 | || xenvif_rx_queue_stalled(queue) | ||
2044 | || xenvif_rx_queue_ready(queue) | ||
1979 | || kthread_should_stop() | 2045 | || kthread_should_stop() |
1980 | || queue->vif->disabled; | 2046 | || queue->vif->disabled; |
1981 | } | 2047 | } |
@@ -2050,6 +2116,15 @@ int xenvif_kthread_guest_rx(void *data) | |||
2050 | if (!skb_queue_empty(&queue->rx_queue)) | 2116 | if (!skb_queue_empty(&queue->rx_queue)) |
2051 | xenvif_rx_action(queue); | 2117 | xenvif_rx_action(queue); |
2052 | 2118 | ||
2119 | /* If the guest hasn't provided any Rx slots for a | ||
2120 | * while it's probably not responsive, drop the | ||
2121 | * carrier so packets are dropped earlier. | ||
2122 | */ | ||
2123 | if (xenvif_rx_queue_stalled(queue)) | ||
2124 | xenvif_queue_carrier_off(queue); | ||
2125 | else if (xenvif_rx_queue_ready(queue)) | ||
2126 | xenvif_queue_carrier_on(queue); | ||
2127 | |||
2053 | /* Queued packets may have foreign pages from other | 2128 | /* Queued packets may have foreign pages from other |
2054 | * domains. These cannot be queued indefinitely as | 2129 | * domains. These cannot be queued indefinitely as |
2055 | * this would starve guests of grant refs and transmit | 2130 | * this would starve guests of grant refs and transmit |
@@ -2120,6 +2195,7 @@ static int __init netback_init(void) | |||
2120 | goto failed_init; | 2195 | goto failed_init; |
2121 | 2196 | ||
2122 | rx_drain_timeout_jiffies = msecs_to_jiffies(rx_drain_timeout_msecs); | 2197 | rx_drain_timeout_jiffies = msecs_to_jiffies(rx_drain_timeout_msecs); |
2198 | rx_stall_timeout_jiffies = msecs_to_jiffies(rx_stall_timeout_msecs); | ||
2123 | 2199 | ||
2124 | #ifdef CONFIG_DEBUG_FS | 2200 | #ifdef CONFIG_DEBUG_FS |
2125 | xen_netback_dbg_root = debugfs_create_dir("xen-netback", NULL); | 2201 | xen_netback_dbg_root = debugfs_create_dir("xen-netback", NULL); |
diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index 96a754d8e517..4e56a27f9689 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c | |||
@@ -711,6 +711,7 @@ static void connect(struct backend_info *be) | |||
711 | be->vif->queues = vzalloc(requested_num_queues * | 711 | be->vif->queues = vzalloc(requested_num_queues * |
712 | sizeof(struct xenvif_queue)); | 712 | sizeof(struct xenvif_queue)); |
713 | be->vif->num_queues = requested_num_queues; | 713 | be->vif->num_queues = requested_num_queues; |
714 | be->vif->stalled_queues = requested_num_queues; | ||
714 | 715 | ||
715 | for (queue_index = 0; queue_index < requested_num_queues; ++queue_index) { | 716 | for (queue_index = 0; queue_index < requested_num_queues; ++queue_index) { |
716 | queue = &be->vif->queues[queue_index]; | 717 | queue = &be->vif->queues[queue_index]; |