diff options
Diffstat (limited to 'drivers/net/tun.c')
-rw-r--r-- | drivers/net/tun.c | 22 |
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 | ||
187 | struct tun_flow_entry { | 186 | struct 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); |
1712 | err_xdp: | 1716 | err_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 | } |