aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/xen-netback/common.h5
-rw-r--r--drivers/net/xen-netback/interface.c11
-rw-r--r--drivers/net/xen-netback/netback.c16
3 files changed, 30 insertions, 2 deletions
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h
index 89b2d429c440..89d1d0556b6e 100644
--- a/drivers/net/xen-netback/common.h
+++ b/drivers/net/xen-netback/common.h
@@ -104,6 +104,11 @@ struct xenvif {
104 domid_t domid; 104 domid_t domid;
105 unsigned int handle; 105 unsigned int handle;
106 106
107 /* Is this interface disabled? True when backend discovers
108 * frontend is rogue.
109 */
110 bool disabled;
111
107 /* Use NAPI for guest TX */ 112 /* Use NAPI for guest TX */
108 struct napi_struct napi; 113 struct napi_struct napi;
109 /* When feature-split-event-channels = 0, tx_irq = rx_irq. */ 114 /* When feature-split-event-channels = 0, tx_irq = rx_irq. */
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
index cdc298e3b747..ef05c5c49d41 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -63,6 +63,15 @@ static int xenvif_poll(struct napi_struct *napi, int budget)
63 struct xenvif *vif = container_of(napi, struct xenvif, napi); 63 struct xenvif *vif = container_of(napi, struct xenvif, napi);
64 int work_done; 64 int work_done;
65 65
66 /* This vif is rogue, we pretend we've there is nothing to do
67 * for this vif to deschedule it from NAPI. But this interface
68 * will be turned off in thread context later.
69 */
70 if (unlikely(vif->disabled)) {
71 napi_complete(napi);
72 return 0;
73 }
74
66 work_done = xenvif_tx_action(vif, budget); 75 work_done = xenvif_tx_action(vif, budget);
67 76
68 if (work_done < budget) { 77 if (work_done < budget) {
@@ -363,6 +372,8 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
363 vif->ip_csum = 1; 372 vif->ip_csum = 1;
364 vif->dev = dev; 373 vif->dev = dev;
365 374
375 vif->disabled = false;
376
366 vif->credit_bytes = vif->remaining_credit = ~0UL; 377 vif->credit_bytes = vif->remaining_credit = ~0UL;
367 vif->credit_usec = 0UL; 378 vif->credit_usec = 0UL;
368 init_timer(&vif->credit_timeout); 379 init_timer(&vif->credit_timeout);
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index ae34f5fc7fbc..3f021e054ba1 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -711,7 +711,8 @@ static void xenvif_tx_err(struct xenvif *vif,
711static void xenvif_fatal_tx_err(struct xenvif *vif) 711static void xenvif_fatal_tx_err(struct xenvif *vif)
712{ 712{
713 netdev_err(vif->dev, "fatal error; disabling device\n"); 713 netdev_err(vif->dev, "fatal error; disabling device\n");
714 xenvif_carrier_off(vif); 714 vif->disabled = true;
715 xenvif_kick_thread(vif);
715} 716}
716 717
717static int xenvif_count_requests(struct xenvif *vif, 718static int xenvif_count_requests(struct xenvif *vif,
@@ -1212,7 +1213,7 @@ static unsigned xenvif_tx_build_gops(struct xenvif *vif, int budget)
1212 vif->tx.sring->req_prod, vif->tx.req_cons, 1213 vif->tx.sring->req_prod, vif->tx.req_cons,
1213 XEN_NETIF_TX_RING_SIZE); 1214 XEN_NETIF_TX_RING_SIZE);
1214 xenvif_fatal_tx_err(vif); 1215 xenvif_fatal_tx_err(vif);
1215 continue; 1216 break;
1216 } 1217 }
1217 1218
1218 work_to_do = RING_HAS_UNCONSUMED_REQUESTS(&vif->tx); 1219 work_to_do = RING_HAS_UNCONSUMED_REQUESTS(&vif->tx);
@@ -1808,7 +1809,18 @@ int xenvif_kthread_guest_rx(void *data)
1808 while (!kthread_should_stop()) { 1809 while (!kthread_should_stop()) {
1809 wait_event_interruptible(vif->wq, 1810 wait_event_interruptible(vif->wq,
1810 rx_work_todo(vif) || 1811 rx_work_todo(vif) ||
1812 vif->disabled ||
1811 kthread_should_stop()); 1813 kthread_should_stop());
1814
1815 /* This frontend is found to be rogue, disable it in
1816 * kthread context. Currently this is only set when
1817 * netback finds out frontend sends malformed packet,
1818 * but we cannot disable the interface in softirq
1819 * context so we defer it here.
1820 */
1821 if (unlikely(vif->disabled && netif_carrier_ok(vif->dev)))
1822 xenvif_carrier_off(vif);
1823
1812 if (kthread_should_stop()) 1824 if (kthread_should_stop())
1813 break; 1825 break;
1814 1826