diff options
| -rw-r--r-- | drivers/net/xen-netback/common.h | 19 | ||||
| -rw-r--r-- | drivers/net/xen-netback/interface.c | 68 | ||||
| -rw-r--r-- | drivers/net/xen-netback/netback.c | 99 |
3 files changed, 140 insertions, 46 deletions
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 28c98229e95f..ef3026f46a37 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h | |||
| @@ -176,9 +176,9 @@ struct xenvif_queue { /* Per-queue data for xenvif */ | |||
| 176 | struct xen_netif_rx_back_ring rx; | 176 | struct xen_netif_rx_back_ring rx; |
| 177 | struct sk_buff_head rx_queue; | 177 | struct sk_buff_head rx_queue; |
| 178 | RING_IDX rx_last_skb_slots; | 178 | RING_IDX rx_last_skb_slots; |
| 179 | bool rx_queue_purge; | 179 | unsigned long status; |
| 180 | 180 | ||
| 181 | struct timer_list wake_queue; | 181 | struct timer_list rx_stalled; |
| 182 | 182 | ||
| 183 | struct gnttab_copy grant_copy_op[MAX_GRANT_COPY_OPS]; | 183 | struct gnttab_copy grant_copy_op[MAX_GRANT_COPY_OPS]; |
| 184 | 184 | ||
| @@ -198,6 +198,20 @@ struct xenvif_queue { /* Per-queue data for xenvif */ | |||
| 198 | struct xenvif_stats stats; | 198 | struct xenvif_stats stats; |
| 199 | }; | 199 | }; |
| 200 | 200 | ||
| 201 | enum state_bit_shift { | ||
| 202 | /* This bit marks that the vif is connected */ | ||
| 203 | VIF_STATUS_CONNECTED, | ||
| 204 | /* This bit signals the RX thread that queuing was stopped (in | ||
| 205 | * start_xmit), and either the timer fired or an RX interrupt came | ||
| 206 | */ | ||
| 207 | QUEUE_STATUS_RX_PURGE_EVENT, | ||
| 208 | /* This bit tells the interrupt handler that this queue was the reason | ||
| 209 | * for the carrier off, so it should kick the thread. Only queues which | ||
| 210 | * brought it down can turn on the carrier. | ||
| 211 | */ | ||
| 212 | QUEUE_STATUS_RX_STALLED | ||
| 213 | }; | ||
| 214 | |||
| 201 | struct xenvif { | 215 | struct xenvif { |
| 202 | /* Unique identifier for this interface. */ | 216 | /* Unique identifier for this interface. */ |
| 203 | domid_t domid; | 217 | domid_t domid; |
| @@ -220,6 +234,7 @@ struct xenvif { | |||
| 220 | * frontend is rogue. | 234 | * frontend is rogue. |
| 221 | */ | 235 | */ |
| 222 | bool disabled; | 236 | bool disabled; |
| 237 | unsigned long status; | ||
| 223 | 238 | ||
| 224 | /* Queues */ | 239 | /* Queues */ |
| 225 | struct xenvif_queue *queues; | 240 | struct xenvif_queue *queues; |
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index bd59d9dbf27b..48a55cda979b 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c | |||
| @@ -55,7 +55,8 @@ static inline void xenvif_stop_queue(struct xenvif_queue *queue) | |||
| 55 | 55 | ||
| 56 | int xenvif_schedulable(struct xenvif *vif) | 56 | int xenvif_schedulable(struct xenvif *vif) |
| 57 | { | 57 | { |
| 58 | return netif_running(vif->dev) && netif_carrier_ok(vif->dev); | 58 | return netif_running(vif->dev) && |
| 59 | test_bit(VIF_STATUS_CONNECTED, &vif->status); | ||
| 59 | } | 60 | } |
| 60 | 61 | ||
| 61 | static irqreturn_t xenvif_tx_interrupt(int irq, void *dev_id) | 62 | static irqreturn_t xenvif_tx_interrupt(int irq, void *dev_id) |
| @@ -77,8 +78,12 @@ int xenvif_poll(struct napi_struct *napi, int budget) | |||
| 77 | /* This vif is rogue, we pretend we've there is nothing to do | 78 | /* This vif is rogue, we pretend we've there is nothing to do |
| 78 | * for this vif to deschedule it from NAPI. But this interface | 79 | * for this vif to deschedule it from NAPI. But this interface |
| 79 | * will be turned off in thread context later. | 80 | * will be turned off in thread context later. |
| 81 | * Also, if a guest doesn't post enough slots to receive data on one of | ||
| 82 | * its queues, the carrier goes down and NAPI is descheduled here so | ||
| 83 | * the guest can't send more packets until it's ready to receive. | ||
| 80 | */ | 84 | */ |
| 81 | if (unlikely(queue->vif->disabled)) { | 85 | if (unlikely(queue->vif->disabled || |
| 86 | !netif_carrier_ok(queue->vif->dev))) { | ||
| 82 | napi_complete(napi); | 87 | napi_complete(napi); |
| 83 | return 0; | 88 | return 0; |
| 84 | } | 89 | } |
| @@ -96,7 +101,16 @@ int xenvif_poll(struct napi_struct *napi, int budget) | |||
| 96 | static irqreturn_t xenvif_rx_interrupt(int irq, void *dev_id) | 101 | static irqreturn_t xenvif_rx_interrupt(int irq, void *dev_id) |
| 97 | { | 102 | { |
| 98 | struct xenvif_queue *queue = dev_id; | 103 | struct xenvif_queue *queue = dev_id; |
| 104 | struct netdev_queue *net_queue = | ||
| 105 | netdev_get_tx_queue(queue->vif->dev, queue->id); | ||
| 99 | 106 | ||
| 107 | /* QUEUE_STATUS_RX_PURGE_EVENT is only set if either QDisc was off OR | ||
| 108 | * the carrier went down and this queue was previously blocked | ||
| 109 | */ | ||
| 110 | if (unlikely(netif_tx_queue_stopped(net_queue) || | ||
| 111 | (!netif_carrier_ok(queue->vif->dev) && | ||
| 112 | test_bit(QUEUE_STATUS_RX_STALLED, &queue->status)))) | ||
| 113 | set_bit(QUEUE_STATUS_RX_PURGE_EVENT, &queue->status); | ||
| 100 | xenvif_kick_thread(queue); | 114 | xenvif_kick_thread(queue); |
| 101 | 115 | ||
| 102 | return IRQ_HANDLED; | 116 | return IRQ_HANDLED; |
| @@ -124,16 +138,14 @@ void xenvif_wake_queue(struct xenvif_queue *queue) | |||
| 124 | netif_tx_wake_queue(netdev_get_tx_queue(dev, id)); | 138 | netif_tx_wake_queue(netdev_get_tx_queue(dev, id)); |
| 125 | } | 139 | } |
| 126 | 140 | ||
| 127 | /* Callback to wake the queue and drain it on timeout */ | 141 | /* Callback to wake the queue's thread and turn the carrier off on timeout */ |
| 128 | static void xenvif_wake_queue_callback(unsigned long data) | 142 | static void xenvif_rx_stalled(unsigned long data) |
| 129 | { | 143 | { |
| 130 | struct xenvif_queue *queue = (struct xenvif_queue *)data; | 144 | struct xenvif_queue *queue = (struct xenvif_queue *)data; |
| 131 | 145 | ||
| 132 | if (xenvif_queue_stopped(queue)) { | 146 | if (xenvif_queue_stopped(queue)) { |
| 133 | netdev_err(queue->vif->dev, "draining TX queue\n"); | 147 | set_bit(QUEUE_STATUS_RX_PURGE_EVENT, &queue->status); |
| 134 | queue->rx_queue_purge = true; | ||
| 135 | xenvif_kick_thread(queue); | 148 | xenvif_kick_thread(queue); |
| 136 | xenvif_wake_queue(queue); | ||
| 137 | } | 149 | } |
| 138 | } | 150 | } |
| 139 | 151 | ||
| @@ -182,11 +194,11 @@ static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 182 | * drain. | 194 | * drain. |
| 183 | */ | 195 | */ |
| 184 | if (!xenvif_rx_ring_slots_available(queue, min_slots_needed)) { | 196 | if (!xenvif_rx_ring_slots_available(queue, min_slots_needed)) { |
| 185 | queue->wake_queue.function = xenvif_wake_queue_callback; | 197 | queue->rx_stalled.function = xenvif_rx_stalled; |
| 186 | queue->wake_queue.data = (unsigned long)queue; | 198 | queue->rx_stalled.data = (unsigned long)queue; |
| 187 | xenvif_stop_queue(queue); | 199 | xenvif_stop_queue(queue); |
| 188 | mod_timer(&queue->wake_queue, | 200 | mod_timer(&queue->rx_stalled, |
| 189 | jiffies + rx_drain_timeout_jiffies); | 201 | jiffies + rx_drain_timeout_jiffies); |
| 190 | } | 202 | } |
| 191 | 203 | ||
| 192 | skb_queue_tail(&queue->rx_queue, skb); | 204 | skb_queue_tail(&queue->rx_queue, skb); |
| @@ -267,7 +279,7 @@ static void xenvif_down(struct xenvif *vif) | |||
| 267 | static int xenvif_open(struct net_device *dev) | 279 | static int xenvif_open(struct net_device *dev) |
| 268 | { | 280 | { |
| 269 | struct xenvif *vif = netdev_priv(dev); | 281 | struct xenvif *vif = netdev_priv(dev); |
| 270 | if (netif_carrier_ok(dev)) | 282 | if (test_bit(VIF_STATUS_CONNECTED, &vif->status)) |
| 271 | xenvif_up(vif); | 283 | xenvif_up(vif); |
| 272 | netif_tx_start_all_queues(dev); | 284 | netif_tx_start_all_queues(dev); |
| 273 | return 0; | 285 | return 0; |
| @@ -276,7 +288,7 @@ static int xenvif_open(struct net_device *dev) | |||
| 276 | static int xenvif_close(struct net_device *dev) | 288 | static int xenvif_close(struct net_device *dev) |
| 277 | { | 289 | { |
| 278 | struct xenvif *vif = netdev_priv(dev); | 290 | struct xenvif *vif = netdev_priv(dev); |
| 279 | if (netif_carrier_ok(dev)) | 291 | if (test_bit(VIF_STATUS_CONNECTED, &vif->status)) |
| 280 | xenvif_down(vif); | 292 | xenvif_down(vif); |
| 281 | netif_tx_stop_all_queues(dev); | 293 | netif_tx_stop_all_queues(dev); |
| 282 | return 0; | 294 | return 0; |
| @@ -514,7 +526,7 @@ int xenvif_init_queue(struct xenvif_queue *queue) | |||
| 514 | queue->grant_tx_handle[i] = NETBACK_INVALID_HANDLE; | 526 | queue->grant_tx_handle[i] = NETBACK_INVALID_HANDLE; |
| 515 | } | 527 | } |
| 516 | 528 | ||
| 517 | init_timer(&queue->wake_queue); | 529 | init_timer(&queue->rx_stalled); |
| 518 | 530 | ||
| 519 | netif_napi_add(queue->vif->dev, &queue->napi, xenvif_poll, | 531 | netif_napi_add(queue->vif->dev, &queue->napi, xenvif_poll, |
| 520 | XENVIF_NAPI_WEIGHT); | 532 | XENVIF_NAPI_WEIGHT); |
| @@ -528,6 +540,7 @@ void xenvif_carrier_on(struct xenvif *vif) | |||
| 528 | if (!vif->can_sg && vif->dev->mtu > ETH_DATA_LEN) | 540 | if (!vif->can_sg && vif->dev->mtu > ETH_DATA_LEN) |
| 529 | dev_set_mtu(vif->dev, ETH_DATA_LEN); | 541 | dev_set_mtu(vif->dev, ETH_DATA_LEN); |
| 530 | netdev_update_features(vif->dev); | 542 | netdev_update_features(vif->dev); |
