diff options
author | David Vrabel <david.vrabel@citrix.com> | 2014-12-18 06:13:06 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-12-18 12:49:49 -0500 |
commit | 26c0e102585d5a4d311f5d6eb7f524d288e7f6b7 (patch) | |
tree | 6ae75952d9356a1e82d175c67501506ad535cace /drivers/net | |
parent | 0e324cf640fbd517615071c336fd4148fb5ce578 (diff) |
xen-netback: support frontends without feature-rx-notify again
Commit bc96f648df1bbc2729abbb84513cf4f64273a1f1 (xen-netback: make
feature-rx-notify mandatory) incorrectly assumed that there were no
frontends in use that did not support this feature. But the frontend
driver in MiniOS does not and since this is used by (qemu) stubdoms,
these stopped working.
Netback sort of works as-is in this mode except:
- If there are no Rx requests and the internal Rx queue fills, only
the drain timeout will wake the thread. The default drain timeout
of 10 s would give unacceptable pauses.
- If an Rx stall was detected and the internal Rx queue is drained,
then the Rx thread would never wake.
Handle these two cases (when feature-rx-notify is disabled) by:
- Reducing the drain timeout to 30 ms.
- Disabling Rx stall detection.
Reported-by: John <jw@nuclearfallout.net>
Tested-by: John <jw@nuclearfallout.net>
Signed-off-by: David Vrabel <david.vrabel@citrix.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/xen-netback/common.h | 4 | ||||
-rw-r--r-- | drivers/net/xen-netback/interface.c | 4 | ||||
-rw-r--r-- | drivers/net/xen-netback/netback.c | 27 | ||||
-rw-r--r-- | drivers/net/xen-netback/xenbus.c | 12 |
4 files changed, 29 insertions, 18 deletions
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 083ecc93fe5e..5f1fda44882b 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h | |||
@@ -230,6 +230,8 @@ struct xenvif { | |||
230 | */ | 230 | */ |
231 | bool disabled; | 231 | bool disabled; |
232 | unsigned long status; | 232 | unsigned long status; |
233 | unsigned long drain_timeout; | ||
234 | unsigned long stall_timeout; | ||
233 | 235 | ||
234 | /* Queues */ | 236 | /* Queues */ |
235 | struct xenvif_queue *queues; | 237 | struct xenvif_queue *queues; |
@@ -328,7 +330,7 @@ irqreturn_t xenvif_interrupt(int irq, void *dev_id); | |||
328 | extern bool separate_tx_rx_irq; | 330 | extern bool separate_tx_rx_irq; |
329 | 331 | ||
330 | extern unsigned int rx_drain_timeout_msecs; | 332 | extern unsigned int rx_drain_timeout_msecs; |
331 | extern unsigned int rx_drain_timeout_jiffies; | 333 | extern unsigned int rx_stall_timeout_msecs; |
332 | extern unsigned int xenvif_max_queues; | 334 | extern unsigned int xenvif_max_queues; |
333 | 335 | ||
334 | #ifdef CONFIG_DEBUG_FS | 336 | #ifdef CONFIG_DEBUG_FS |
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index a6a32d337bbb..9259a732e8a4 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c | |||
@@ -166,7 +166,7 @@ static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
166 | goto drop; | 166 | goto drop; |
167 | 167 | ||
168 | cb = XENVIF_RX_CB(skb); | 168 | cb = XENVIF_RX_CB(skb); |
169 | cb->expires = jiffies + rx_drain_timeout_jiffies; | 169 | cb->expires = jiffies + vif->drain_timeout; |
170 | 170 | ||
171 | xenvif_rx_queue_tail(queue, skb); | 171 | xenvif_rx_queue_tail(queue, skb); |
172 | xenvif_kick_thread(queue); | 172 | xenvif_kick_thread(queue); |
@@ -414,6 +414,8 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid, | |||
414 | vif->ip_csum = 1; | 414 | vif->ip_csum = 1; |
415 | vif->dev = dev; | 415 | vif->dev = dev; |
416 | vif->disabled = false; | 416 | vif->disabled = false; |
417 | vif->drain_timeout = msecs_to_jiffies(rx_drain_timeout_msecs); | ||
418 | vif->stall_timeout = msecs_to_jiffies(rx_stall_timeout_msecs); | ||
417 | 419 | ||
418 | /* Start out with no queues. */ | 420 | /* Start out with no queues. */ |
419 | vif->queues = NULL; | 421 | vif->queues = NULL; |
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 4a509f715fe8..908e65e9b821 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c | |||
@@ -60,14 +60,12 @@ module_param(separate_tx_rx_irq, bool, 0644); | |||
60 | */ | 60 | */ |
61 | unsigned int rx_drain_timeout_msecs = 10000; | 61 | 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; | ||
64 | 63 | ||
65 | /* The length of time before the frontend is considered unresponsive | 64 | /* The length of time before the frontend is considered unresponsive |
66 | * because it isn't providing Rx slots. | 65 | * because it isn't providing Rx slots. |
67 | */ | 66 | */ |
68 | static unsigned int rx_stall_timeout_msecs = 60000; | 67 | unsigned int rx_stall_timeout_msecs = 60000; |
69 | module_param(rx_stall_timeout_msecs, uint, 0444); | 68 | module_param(rx_stall_timeout_msecs, uint, 0444); |
70 | static unsigned int rx_stall_timeout_jiffies; | ||
71 | 69 | ||
72 | unsigned int xenvif_max_queues; | 70 | unsigned int xenvif_max_queues; |
73 | module_param_named(max_queues, xenvif_max_queues, uint, 0644); | 71 | module_param_named(max_queues, xenvif_max_queues, uint, 0644); |
@@ -2020,7 +2018,7 @@ static bool xenvif_rx_queue_stalled(struct xenvif_queue *queue) | |||
2020 | return !queue->stalled | 2018 | return !queue->stalled |
2021 | && prod - cons < XEN_NETBK_RX_SLOTS_MAX | 2019 | && prod - cons < XEN_NETBK_RX_SLOTS_MAX |
2022 | && time_after(jiffies, | 2020 | && time_after(jiffies, |
2023 | queue->last_rx_time + rx_stall_timeout_jiffies); | 2021 | queue->last_rx_time + queue->vif->stall_timeout); |
2024 | } | 2022 | } |
2025 | 2023 | ||
2026 | static bool xenvif_rx_queue_ready(struct xenvif_queue *queue) | 2024 | static bool xenvif_rx_queue_ready(struct xenvif_queue *queue) |
@@ -2038,8 +2036,9 @@ static bool xenvif_have_rx_work(struct xenvif_queue *queue) | |||
2038 | { | 2036 | { |
2039 | return (!skb_queue_empty(&queue->rx_queue) | 2037 | return (!skb_queue_empty(&queue->rx_queue) |
2040 | && xenvif_rx_ring_slots_available(queue, XEN_NETBK_RX_SLOTS_MAX)) | 2038 | && xenvif_rx_ring_slots_available(queue, XEN_NETBK_RX_SLOTS_MAX)) |
2041 | || xenvif_rx_queue_stalled(queue) | 2039 | || (queue->vif->stall_timeout && |
2042 | || xenvif_rx_queue_ready(queue) | 2040 | (xenvif_rx_queue_stalled(queue) |
2041 | || xenvif_rx_queue_ready(queue))) | ||
2043 | || kthread_should_stop() | 2042 | || kthread_should_stop() |
2044 | || queue->vif->disabled; | 2043 | || queue->vif->disabled; |
2045 | } | 2044 | } |
@@ -2092,6 +2091,9 @@ int xenvif_kthread_guest_rx(void *data) | |||
2092 | struct xenvif_queue *queue = data; | 2091 | struct xenvif_queue *queue = data; |
2093 | struct xenvif *vif = queue->vif; | 2092 | struct xenvif *vif = queue->vif; |
2094 | 2093 | ||
2094 | if (!vif->stall_timeout) | ||
2095 | xenvif_queue_carrier_on(queue); | ||
2096 | |||
2095 | for (;;) { | 2097 | for (;;) { |
2096 | xenvif_wait_for_rx_work(queue); | 2098 | xenvif_wait_for_rx_work(queue); |
2097 | 2099 | ||
@@ -2118,10 +2120,12 @@ int xenvif_kthread_guest_rx(void *data) | |||
2118 | * while it's probably not responsive, drop the | 2120 | * while it's probably not responsive, drop the |
2119 | * carrier so packets are dropped earlier. | 2121 | * carrier so packets are dropped earlier. |
2120 | */ | 2122 | */ |
2121 | if (xenvif_rx_queue_stalled(queue)) | 2123 | if (vif->stall_timeout) { |
2122 | xenvif_queue_carrier_off(queue); | 2124 | if (xenvif_rx_queue_stalled(queue)) |
2123 | else if (xenvif_rx_queue_ready(queue)) | 2125 | xenvif_queue_carrier_off(queue); |
2124 | xenvif_queue_carrier_on(queue); | 2126 | else if (xenvif_rx_queue_ready(queue)) |
2127 | xenvif_queue_carrier_on(queue); | ||
2128 | } | ||
2125 | 2129 | ||
2126 | /* Queued packets may have foreign pages from other | 2130 | /* Queued packets may have foreign pages from other |
2127 | * domains. These cannot be queued indefinitely as | 2131 | * domains. These cannot be queued indefinitely as |
@@ -2192,9 +2196,6 @@ static int __init netback_init(void) | |||
2192 | if (rc) | 2196 | if (rc) |
2193 | goto failed_init; | 2197 | goto failed_init; |
2194 | 2198 | ||
2195 | rx_drain_timeout_jiffies = msecs_to_jiffies(rx_drain_timeout_msecs); | ||
2196 | rx_stall_timeout_jiffies = msecs_to_jiffies(rx_stall_timeout_msecs); | ||
2197 | |||
2198 | #ifdef CONFIG_DEBUG_FS | 2199 | #ifdef CONFIG_DEBUG_FS |
2199 | xen_netback_dbg_root = debugfs_create_dir("xen-netback", NULL); | 2200 | xen_netback_dbg_root = debugfs_create_dir("xen-netback", NULL); |
2200 | if (IS_ERR_OR_NULL(xen_netback_dbg_root)) | 2201 | if (IS_ERR_OR_NULL(xen_netback_dbg_root)) |
diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index d44cd19169bd..efbaf2ae1999 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c | |||
@@ -887,9 +887,15 @@ static int read_xenbus_vif_flags(struct backend_info *be) | |||
887 | return -EOPNOTSUPP; | 887 | return -EOPNOTSUPP; |
888 | 888 | ||
889 | if (xenbus_scanf(XBT_NIL, dev->otherend, | 889 | if (xenbus_scanf(XBT_NIL, dev->otherend, |
890 | "feature-rx-notify", "%d", &val) < 0 || val == 0) { | 890 | "feature-rx-notify", "%d", &val) < 0) |
891 | xenbus_dev_fatal(dev, -EINVAL, "feature-rx-notify is mandatory"); | 891 | val = 0; |
892 | return -EINVAL; | 892 | if (!val) { |
893 | /* - Reduce drain timeout to poll more frequently for | ||
894 | * Rx requests. | ||
895 | * - Disable Rx stall detection. | ||
896 | */ | ||
897 | be->vif->drain_timeout = msecs_to_jiffies(30); | ||
898 | be->vif->stall_timeout = 0; | ||
893 | } | 899 | } |
894 | 900 | ||
895 | if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-sg", | 901 | if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-sg", |