aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/tun.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/tun.c')
-rw-r--r--drivers/net/tun.c22
1 files changed, 7 insertions, 15 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index b52258c327d2..7433bb2e4451 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -181,7 +181,6 @@ struct tun_file {
181 struct tun_struct *detached; 181 struct tun_struct *detached;
182 struct ptr_ring tx_ring; 182 struct ptr_ring tx_ring;
183 struct xdp_rxq_info xdp_rxq; 183 struct xdp_rxq_info xdp_rxq;
184 int xdp_pending_pkts;
185}; 184};
186 185
187struct tun_flow_entry { 186struct tun_flow_entry {
@@ -1643,6 +1642,7 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun,
1643 else 1642 else
1644 *skb_xdp = 0; 1643 *skb_xdp = 0;
1645 1644
1645 preempt_disable();
1646 rcu_read_lock(); 1646 rcu_read_lock();
1647 xdp_prog = rcu_dereference(tun->xdp_prog); 1647 xdp_prog = rcu_dereference(tun->xdp_prog);
1648 if (xdp_prog && !*skb_xdp) { 1648 if (xdp_prog && !*skb_xdp) {
@@ -1662,11 +1662,12 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun,
1662 case XDP_REDIRECT: 1662 case XDP_REDIRECT:
1663 get_page(alloc_frag->page); 1663 get_page(alloc_frag->page);
1664 alloc_frag->offset += buflen; 1664 alloc_frag->offset += buflen;
1665 ++tfile->xdp_pending_pkts;
1666 err = xdp_do_redirect(tun->dev, &xdp, xdp_prog); 1665 err = xdp_do_redirect(tun->dev, &xdp, xdp_prog);
1666 xdp_do_flush_map();
1667 if (err) 1667 if (err)
1668 goto err_redirect; 1668 goto err_redirect;
1669 rcu_read_unlock(); 1669 rcu_read_unlock();
1670 preempt_enable();
1670 return NULL; 1671 return NULL;
1671 case XDP_TX: 1672 case XDP_TX:
1672 xdp_xmit = true; 1673 xdp_xmit = true;
@@ -1688,6 +1689,7 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun,
1688 skb = build_skb(buf, buflen); 1689 skb = build_skb(buf, buflen);
1689 if (!skb) { 1690 if (!skb) {
1690 rcu_read_unlock(); 1691 rcu_read_unlock();
1692 preempt_enable();
1691 return ERR_PTR(-ENOMEM); 1693 return ERR_PTR(-ENOMEM);
1692 } 1694 }
1693 1695
@@ -1700,10 +1702,12 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun,
1700 skb->dev = tun->dev; 1702 skb->dev = tun->dev;
1701 generic_xdp_tx(skb, xdp_prog); 1703 generic_xdp_tx(skb, xdp_prog);
1702 rcu_read_unlock(); 1704 rcu_read_unlock();
1705 preempt_enable();
1703 return NULL; 1706 return NULL;
1704 } 1707 }
1705 1708
1706 rcu_read_unlock(); 1709 rcu_read_unlock();
1710 preempt_enable();
1707 1711
1708 return skb; 1712 return skb;
1709 1713
@@ -1711,6 +1715,7 @@ err_redirect:
1711 put_page(alloc_frag->page); 1715 put_page(alloc_frag->page);
1712err_xdp: 1716err_xdp:
1713 rcu_read_unlock(); 1717 rcu_read_unlock();
1718 preempt_enable();
1714 this_cpu_inc(tun->pcpu_stats->rx_dropped); 1719 this_cpu_inc(tun->pcpu_stats->rx_dropped);
1715 return NULL; 1720 return NULL;
1716} 1721}
@@ -1984,11 +1989,6 @@ static ssize_t tun_chr_write_iter(struct kiocb *iocb, struct iov_iter *from)
1984 result = tun_get_user(tun, tfile, NULL, from, 1989 result = tun_get_user(tun, tfile, NULL, from,
1985 file->f_flags & O_NONBLOCK, false); 1990 file->f_flags & O_NONBLOCK, false);
1986 1991
1987 if (tfile->xdp_pending_pkts) {
1988 tfile->xdp_pending_pkts = 0;
1989 xdp_do_flush_map();
1990 }
1991
1992 tun_put(tun); 1992 tun_put(tun);
1993 return result; 1993 return result;
1994} 1994}
@@ -2325,13 +2325,6 @@ static int tun_sendmsg(struct socket *sock, struct msghdr *m, size_t total_len)
2325 ret = tun_get_user(tun, tfile, m->msg_control, &m->msg_iter, 2325 ret = tun_get_user(tun, tfile, m->msg_control, &m->msg_iter,
2326 m->msg_flags & MSG_DONTWAIT, 2326 m->msg_flags & MSG_DONTWAIT,
2327 m->msg_flags & MSG_MORE); 2327 m->msg_flags & MSG_MORE);
2328
2329 if (tfile->xdp_pending_pkts >= NAPI_POLL_WEIGHT ||
2330 !(m->msg_flags & MSG_MORE)) {
2331 tfile->xdp_pending_pkts = 0;
2332 xdp_do_flush_map();
2333 }
2334
2335 tun_put(tun); 2328 tun_put(tun);
2336 return ret; 2329 return ret;
2337} 2330}
@@ -3163,7 +3156,6 @@ static int tun_chr_open(struct inode *inode, struct file * file)
3163 sock_set_flag(&tfile->sk, SOCK_ZEROCOPY); 3156 sock_set_flag(&tfile->sk, SOCK_ZEROCOPY);
3164 3157
3165 memset(&tfile->tx_ring, 0, sizeof(tfile->tx_ring)); 3158 memset(&tfile->tx_ring, 0, sizeof(tfile->tx_ring));
3166 tfile->xdp_pending_pkts = 0;
3167 3159
3168 return 0; 3160 return 0;
3169} 3161}