Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 
0003 #include <net/xsk_buff_pool.h>
0004 #include <net/xdp_sock.h>
0005 #include <net/xdp_sock_drv.h>
0006 
0007 #include "xsk_queue.h"
0008 #include "xdp_umem.h"
0009 #include "xsk.h"
0010 
0011 void xp_add_xsk(struct xsk_buff_pool *pool, struct xdp_sock *xs)
0012 {
0013     unsigned long flags;
0014 
0015     if (!xs->tx)
0016         return;
0017 
0018     spin_lock_irqsave(&pool->xsk_tx_list_lock, flags);
0019     list_add_rcu(&xs->tx_list, &pool->xsk_tx_list);
0020     spin_unlock_irqrestore(&pool->xsk_tx_list_lock, flags);
0021 }
0022 
0023 void xp_del_xsk(struct xsk_buff_pool *pool, struct xdp_sock *xs)
0024 {
0025     unsigned long flags;
0026 
0027     if (!xs->tx)
0028         return;
0029 
0030     spin_lock_irqsave(&pool->xsk_tx_list_lock, flags);
0031     list_del_rcu(&xs->tx_list);
0032     spin_unlock_irqrestore(&pool->xsk_tx_list_lock, flags);
0033 }
0034 
0035 void xp_destroy(struct xsk_buff_pool *pool)
0036 {
0037     if (!pool)
0038         return;
0039 
0040     kvfree(pool->tx_descs);
0041     kvfree(pool->heads);
0042     kvfree(pool);
0043 }
0044 
0045 int xp_alloc_tx_descs(struct xsk_buff_pool *pool, struct xdp_sock *xs)
0046 {
0047     pool->tx_descs = kvcalloc(xs->tx->nentries, sizeof(*pool->tx_descs),
0048                   GFP_KERNEL);
0049     if (!pool->tx_descs)
0050         return -ENOMEM;
0051 
0052     return 0;
0053 }
0054 
0055 struct xsk_buff_pool *xp_create_and_assign_umem(struct xdp_sock *xs,
0056                         struct xdp_umem *umem)
0057 {
0058     bool unaligned = umem->flags & XDP_UMEM_UNALIGNED_CHUNK_FLAG;
0059     struct xsk_buff_pool *pool;
0060     struct xdp_buff_xsk *xskb;
0061     u32 i, entries;
0062 
0063     entries = unaligned ? umem->chunks : 0;
0064     pool = kvzalloc(struct_size(pool, free_heads, entries), GFP_KERNEL);
0065     if (!pool)
0066         goto out;
0067 
0068     pool->heads = kvcalloc(umem->chunks, sizeof(*pool->heads), GFP_KERNEL);
0069     if (!pool->heads)
0070         goto out;
0071 
0072     if (xs->tx)
0073         if (xp_alloc_tx_descs(pool, xs))
0074             goto out;
0075 
0076     pool->chunk_mask = ~((u64)umem->chunk_size - 1);
0077     pool->addrs_cnt = umem->size;
0078     pool->heads_cnt = umem->chunks;
0079     pool->free_heads_cnt = umem->chunks;
0080     pool->headroom = umem->headroom;
0081     pool->chunk_size = umem->chunk_size;
0082     pool->chunk_shift = ffs(umem->chunk_size) - 1;
0083     pool->unaligned = unaligned;
0084     pool->frame_len = umem->chunk_size - umem->headroom -
0085         XDP_PACKET_HEADROOM;
0086     pool->umem = umem;
0087     pool->addrs = umem->addrs;
0088     INIT_LIST_HEAD(&pool->free_list);
0089     INIT_LIST_HEAD(&pool->xsk_tx_list);
0090     spin_lock_init(&pool->xsk_tx_list_lock);
0091     spin_lock_init(&pool->cq_lock);
0092     refcount_set(&pool->users, 1);
0093 
0094     pool->fq = xs->fq_tmp;
0095     pool->cq = xs->cq_tmp;
0096 
0097     for (i = 0; i < pool->free_heads_cnt; i++) {
0098         xskb = &pool->heads[i];
0099         xskb->pool = pool;
0100         xskb->xdp.frame_sz = umem->chunk_size - umem->headroom;
0101         INIT_LIST_HEAD(&xskb->free_list_node);
0102         if (pool->unaligned)
0103             pool->free_heads[i] = xskb;
0104         else
0105             xp_init_xskb_addr(xskb, pool, i * pool->chunk_size);
0106     }
0107 
0108     return pool;
0109 
0110 out:
0111     xp_destroy(pool);
0112     return NULL;
0113 }
0114 
0115 void xp_set_rxq_info(struct xsk_buff_pool *pool, struct xdp_rxq_info *rxq)
0116 {
0117     u32 i;
0118 
0119     for (i = 0; i < pool->heads_cnt; i++)
0120         pool->heads[i].xdp.rxq = rxq;
0121 }
0122 EXPORT_SYMBOL(xp_set_rxq_info);
0123 
0124 static void xp_disable_drv_zc(struct xsk_buff_pool *pool)
0125 {
0126     struct netdev_bpf bpf;
0127     int err;
0128 
0129     ASSERT_RTNL();
0130 
0131     if (pool->umem->zc) {
0132         bpf.command = XDP_SETUP_XSK_POOL;
0133         bpf.xsk.pool = NULL;
0134         bpf.xsk.queue_id = pool->queue_id;
0135 
0136         err = pool->netdev->netdev_ops->ndo_bpf(pool->netdev, &bpf);
0137 
0138         if (err)
0139             WARN(1, "Failed to disable zero-copy!\n");
0140     }
0141 }
0142 
0143 int xp_assign_dev(struct xsk_buff_pool *pool,
0144           struct net_device *netdev, u16 queue_id, u16 flags)
0145 {
0146     bool force_zc, force_copy;
0147     struct netdev_bpf bpf;
0148     int err = 0;
0149 
0150     ASSERT_RTNL();
0151 
0152     force_zc = flags & XDP_ZEROCOPY;
0153     force_copy = flags & XDP_COPY;
0154 
0155     if (force_zc && force_copy)
0156         return -EINVAL;
0157 
0158     if (xsk_get_pool_from_qid(netdev, queue_id))
0159         return -EBUSY;
0160 
0161     pool->netdev = netdev;
0162     pool->queue_id = queue_id;
0163     err = xsk_reg_pool_at_qid(netdev, pool, queue_id);
0164     if (err)
0165         return err;
0166 
0167     if (flags & XDP_USE_NEED_WAKEUP)
0168         pool->uses_need_wakeup = true;
0169     /* Tx needs to be explicitly woken up the first time.  Also
0170      * for supporting drivers that do not implement this
0171      * feature. They will always have to call sendto() or poll().
0172      */
0173     pool->cached_need_wakeup = XDP_WAKEUP_TX;
0174 
0175     dev_hold(netdev);
0176 
0177     if (force_copy)
0178         /* For copy-mode, we are done. */
0179         return 0;
0180 
0181     if (!netdev->netdev_ops->ndo_bpf ||
0182         !netdev->netdev_ops->ndo_xsk_wakeup) {
0183         err = -EOPNOTSUPP;
0184         goto err_unreg_pool;
0185     }
0186 
0187     bpf.command = XDP_SETUP_XSK_POOL;
0188     bpf.xsk.pool = pool;
0189     bpf.xsk.queue_id = queue_id;
0190 
0191     err = netdev->netdev_ops->ndo_bpf(netdev, &bpf);
0192     if (err)
0193         goto err_unreg_pool;
0194 
0195     if (!pool->dma_pages) {
0196         WARN(1, "Driver did not DMA map zero-copy buffers");
0197         err = -EINVAL;
0198         goto err_unreg_xsk;
0199     }
0200     pool->umem->zc = true;
0201     return 0;
0202 
0203 err_unreg_xsk:
0204     xp_disable_drv_zc(pool);
0205 err_unreg_pool:
0206     if (!force_zc)
0207         err = 0; /* fallback to copy mode */
0208     if (err) {
0209         xsk_clear_pool_at_qid(netdev, queue_id);
0210         dev_put(netdev);
0211     }
0212     return err;
0213 }
0214 
0215 int xp_assign_dev_shared(struct xsk_buff_pool *pool, struct xdp_sock *umem_xs,
0216              struct net_device *dev, u16 queue_id)
0217 {
0218     u16 flags;
0219     struct xdp_umem *umem = umem_xs->umem;
0220 
0221     /* One fill and completion ring required for each queue id. */
0222     if (!pool->fq || !pool->cq)
0223         return -EINVAL;
0224 
0225     flags = umem->zc ? XDP_ZEROCOPY : XDP_COPY;
0226     if (umem_xs->pool->uses_need_wakeup)
0227         flags |= XDP_USE_NEED_WAKEUP;
0228 
0229     return xp_assign_dev(pool, dev, queue_id, flags);
0230 }
0231 
0232 void xp_clear_dev(struct xsk_buff_pool *pool)
0233 {
0234     if (!pool->netdev)
0235         return;
0236 
0237     xp_disable_drv_zc(pool);
0238     xsk_clear_pool_at_qid(pool->netdev, pool->queue_id);
0239     dev_put(pool->netdev);
0240     pool->netdev = NULL;
0241 }
0242 
0243 static void xp_release_deferred(struct work_struct *work)
0244 {
0245     struct xsk_buff_pool *pool = container_of(work, struct xsk_buff_pool,
0246                           work);
0247 
0248     rtnl_lock();
0249     xp_clear_dev(pool);
0250     rtnl_unlock();
0251 
0252     if (pool->fq) {
0253         xskq_destroy(pool->fq);
0254         pool->fq = NULL;
0255     }
0256 
0257     if (pool->cq) {
0258         xskq_destroy(pool->cq);
0259         pool->cq = NULL;
0260     }
0261 
0262     xdp_put_umem(pool->umem, false);
0263     xp_destroy(pool);
0264 }
0265 
0266 void xp_get_pool(struct xsk_buff_pool *pool)
0267 {
0268     refcount_inc(&pool->users);
0269 }
0270 
0271 bool xp_put_pool(struct xsk_buff_pool *pool)
0272 {
0273     if (!pool)
0274         return false;
0275 
0276     if (refcount_dec_and_test(&pool->users)) {
0277         INIT_WORK(&pool->work, xp_release_deferred);
0278         schedule_work(&pool->work);
0279         return true;
0280     }
0281 
0282     return false;
0283 }
0284 
0285 static struct xsk_dma_map *xp_find_dma_map(struct xsk_buff_pool *pool)
0286 {
0287     struct xsk_dma_map *dma_map;
0288 
0289     list_for_each_entry(dma_map, &pool->umem->xsk_dma_list, list) {
0290         if (dma_map->netdev == pool->netdev)
0291             return dma_map;
0292     }
0293 
0294     return NULL;
0295 }
0296 
0297 static struct xsk_dma_map *xp_create_dma_map(struct device *dev, struct net_device *netdev,
0298                          u32 nr_pages, struct xdp_umem *umem)
0299 {
0300     struct xsk_dma_map *dma_map;
0301 
0302     dma_map = kzalloc(sizeof(*dma_map), GFP_KERNEL);
0303     if (!dma_map)
0304         return NULL;
0305 
0306     dma_map->dma_pages = kvcalloc(nr_pages, sizeof(*dma_map->dma_pages), GFP_KERNEL);
0307     if (!dma_map->dma_pages) {
0308         kfree(dma_map);
0309         return NULL;
0310     }
0311 
0312     dma_map->netdev = netdev;
0313     dma_map->dev = dev;
0314     dma_map->dma_need_sync = false;
0315     dma_map->dma_pages_cnt = nr_pages;
0316     refcount_set(&dma_map->users, 1);
0317     list_add(&dma_map->list, &umem->xsk_dma_list);
0318     return dma_map;
0319 }
0320 
0321 static void xp_destroy_dma_map(struct xsk_dma_map *dma_map)
0322 {
0323     list_del(&dma_map->list);
0324     kvfree(dma_map->dma_pages);
0325     kfree(dma_map);
0326 }
0327 
0328 static void __xp_dma_unmap(struct xsk_dma_map *dma_map, unsigned long attrs)
0329 {
0330     dma_addr_t *dma;
0331     u32 i;
0332 
0333     for (i = 0; i < dma_map->dma_pages_cnt; i++) {
0334         dma = &dma_map->dma_pages[i];
0335         if (*dma) {
0336             *dma &= ~XSK_NEXT_PG_CONTIG_MASK;
0337             dma_unmap_page_attrs(dma_map->dev, *dma, PAGE_SIZE,
0338                          DMA_BIDIRECTIONAL, attrs);
0339             *dma = 0;
0340         }
0341     }
0342 
0343     xp_destroy_dma_map(dma_map);
0344 }
0345 
0346 void xp_dma_unmap(struct xsk_buff_pool *pool, unsigned long attrs)
0347 {
0348     struct xsk_dma_map *dma_map;
0349 
0350     if (pool->dma_pages_cnt == 0)
0351         return;
0352 
0353     dma_map = xp_find_dma_map(pool);
0354     if (!dma_map) {
0355         WARN(1, "Could not find dma_map for device");
0356         return;
0357     }
0358 
0359     if (!refcount_dec_and_test(&dma_map->users))
0360         return;
0361 
0362     __xp_dma_unmap(dma_map, attrs);
0363     kvfree(pool->dma_pages);
0364     pool->dma_pages_cnt = 0;
0365     pool->dev = NULL;
0366 }
0367 EXPORT_SYMBOL(xp_dma_unmap);
0368 
0369 static void xp_check_dma_contiguity(struct xsk_dma_map *dma_map)
0370 {
0371     u32 i;
0372 
0373     for (i = 0; i < dma_map->dma_pages_cnt - 1; i++) {
0374         if (dma_map->dma_pages[i] + PAGE_SIZE == dma_map->dma_pages[i + 1])
0375             dma_map->dma_pages[i] |= XSK_NEXT_PG_CONTIG_MASK;
0376         else
0377             dma_map->dma_pages[i] &= ~XSK_NEXT_PG_CONTIG_MASK;
0378     }
0379 }
0380 
0381 static int xp_init_dma_info(struct xsk_buff_pool *pool, struct xsk_dma_map *dma_map)
0382 {
0383     if (!pool->unaligned) {
0384         u32 i;
0385 
0386         for (i = 0; i < pool->heads_cnt; i++) {
0387             struct xdp_buff_xsk *xskb = &pool->heads[i];
0388 
0389             xp_init_xskb_dma(xskb, pool, dma_map->dma_pages, xskb->orig_addr);
0390         }
0391     }
0392 
0393     pool->dma_pages = kvcalloc(dma_map->dma_pages_cnt, sizeof(*pool->dma_pages), GFP_KERNEL);
0394     if (!pool->dma_pages)
0395         return -ENOMEM;
0396 
0397     pool->dev = dma_map->dev;
0398     pool->dma_pages_cnt = dma_map->dma_pages_cnt;
0399     pool->dma_need_sync = dma_map->dma_need_sync;
0400     memcpy(pool->dma_pages, dma_map->dma_pages,
0401            pool->dma_pages_cnt * sizeof(*pool->dma_pages));
0402 
0403     return 0;
0404 }
0405 
0406 int xp_dma_map(struct xsk_buff_pool *pool, struct device *dev,
0407            unsigned long attrs, struct page **pages, u32 nr_pages)
0408 {
0409     struct xsk_dma_map *dma_map;
0410     dma_addr_t dma;
0411     int err;
0412     u32 i;
0413 
0414     dma_map = xp_find_dma_map(pool);
0415     if (dma_map) {
0416         err = xp_init_dma_info(pool, dma_map);
0417         if (err)
0418             return err;
0419 
0420         refcount_inc(&dma_map->users);
0421         return 0;
0422     }
0423 
0424     dma_map = xp_create_dma_map(dev, pool->netdev, nr_pages, pool->umem);
0425     if (!dma_map)
0426         return -ENOMEM;
0427 
0428     for (i = 0; i < dma_map->dma_pages_cnt; i++) {
0429         dma = dma_map_page_attrs(dev, pages[i], 0, PAGE_SIZE,
0430                      DMA_BIDIRECTIONAL, attrs);
0431         if (dma_mapping_error(dev, dma)) {
0432             __xp_dma_unmap(dma_map, attrs);
0433             return -ENOMEM;
0434         }
0435         if (dma_need_sync(dev, dma))
0436             dma_map->dma_need_sync = true;
0437         dma_map->dma_pages[i] = dma;
0438     }
0439 
0440     if (pool->unaligned)
0441         xp_check_dma_contiguity(dma_map);
0442 
0443     err = xp_init_dma_info(pool, dma_map);
0444     if (err) {
0445         __xp_dma_unmap(dma_map, attrs);
0446         return err;
0447     }
0448 
0449     return 0;
0450 }
0451 EXPORT_SYMBOL(xp_dma_map);
0452 
0453 static bool xp_addr_crosses_non_contig_pg(struct xsk_buff_pool *pool,
0454                       u64 addr)
0455 {
0456     return xp_desc_crosses_non_contig_pg(pool, addr, pool->chunk_size);
0457 }
0458 
0459 static bool xp_check_unaligned(struct xsk_buff_pool *pool, u64 *addr)
0460 {
0461     *addr = xp_unaligned_extract_addr(*addr);
0462     if (*addr >= pool->addrs_cnt ||
0463         *addr + pool->chunk_size > pool->addrs_cnt ||
0464         xp_addr_crosses_non_contig_pg(pool, *addr))
0465         return false;
0466     return true;
0467 }
0468 
0469 static bool xp_check_aligned(struct xsk_buff_pool *pool, u64 *addr)
0470 {
0471     *addr = xp_aligned_extract_addr(pool, *addr);
0472     return *addr < pool->addrs_cnt;
0473 }
0474 
0475 static struct xdp_buff_xsk *__xp_alloc(struct xsk_buff_pool *pool)
0476 {
0477     struct xdp_buff_xsk *xskb;
0478     u64 addr;
0479     bool ok;
0480 
0481     if (pool->free_heads_cnt == 0)
0482         return NULL;
0483 
0484     for (;;) {
0485         if (!xskq_cons_peek_addr_unchecked(pool->fq, &addr)) {
0486             pool->fq->queue_empty_descs++;
0487             return NULL;
0488         }
0489 
0490         ok = pool->unaligned ? xp_check_unaligned(pool, &addr) :
0491              xp_check_aligned(pool, &addr);
0492         if (!ok) {
0493             pool->fq->invalid_descs++;
0494             xskq_cons_release(pool->fq);
0495             continue;
0496         }
0497         break;
0498     }
0499 
0500     if (pool->unaligned) {
0501         xskb = pool->free_heads[--pool->free_heads_cnt];
0502         xp_init_xskb_addr(xskb, pool, addr);
0503         if (pool->dma_pages_cnt)
0504             xp_init_xskb_dma(xskb, pool, pool->dma_pages, addr);
0505     } else {
0506         xskb = &pool->heads[xp_aligned_extract_idx(pool, addr)];
0507     }
0508 
0509     xskq_cons_release(pool->fq);
0510     return xskb;
0511 }
0512 
0513 struct xdp_buff *xp_alloc(struct xsk_buff_pool *pool)
0514 {
0515     struct xdp_buff_xsk *xskb;
0516 
0517     if (!pool->free_list_cnt) {
0518         xskb = __xp_alloc(pool);
0519         if (!xskb)
0520             return NULL;
0521     } else {
0522         pool->free_list_cnt--;
0523         xskb = list_first_entry(&pool->free_list, struct xdp_buff_xsk,
0524                     free_list_node);
0525         list_del_init(&xskb->free_list_node);
0526     }
0527 
0528     xskb->xdp.data = xskb->xdp.data_hard_start + XDP_PACKET_HEADROOM;
0529     xskb->xdp.data_meta = xskb->xdp.data;
0530 
0531     if (pool->dma_need_sync) {
0532         dma_sync_single_range_for_device(pool->dev, xskb->dma, 0,
0533                          pool->frame_len,
0534                          DMA_BIDIRECTIONAL);
0535     }
0536     return &xskb->xdp;
0537 }
0538 EXPORT_SYMBOL(xp_alloc);
0539 
0540 static u32 xp_alloc_new_from_fq(struct xsk_buff_pool *pool, struct xdp_buff **xdp, u32 max)
0541 {
0542     u32 i, cached_cons, nb_entries;
0543 
0544     if (max > pool->free_heads_cnt)
0545         max = pool->free_heads_cnt;
0546     max = xskq_cons_nb_entries(pool->fq, max);
0547 
0548     cached_cons = pool->fq->cached_cons;
0549     nb_entries = max;
0550     i = max;
0551     while (i--) {
0552         struct xdp_buff_xsk *xskb;
0553         u64 addr;
0554         bool ok;
0555 
0556         __xskq_cons_read_addr_unchecked(pool->fq, cached_cons++, &addr);
0557 
0558         ok = pool->unaligned ? xp_check_unaligned(pool, &addr) :
0559             xp_check_aligned(pool, &addr);
0560         if (unlikely(!ok)) {
0561             pool->fq->invalid_descs++;
0562             nb_entries--;
0563             continue;
0564         }
0565 
0566         if (pool->unaligned) {
0567             xskb = pool->free_heads[--pool->free_heads_cnt];
0568             xp_init_xskb_addr(xskb, pool, addr);
0569             if (pool->dma_pages_cnt)
0570                 xp_init_xskb_dma(xskb, pool, pool->dma_pages, addr);
0571         } else {
0572             xskb = &pool->heads[xp_aligned_extract_idx(pool, addr)];
0573         }
0574 
0575         *xdp = &xskb->xdp;
0576         xdp++;
0577     }
0578 
0579     xskq_cons_release_n(pool->fq, max);
0580     return nb_entries;
0581 }
0582 
0583 static u32 xp_alloc_reused(struct xsk_buff_pool *pool, struct xdp_buff **xdp, u32 nb_entries)
0584 {
0585     struct xdp_buff_xsk *xskb;
0586     u32 i;
0587 
0588     nb_entries = min_t(u32, nb_entries, pool->free_list_cnt);
0589 
0590     i = nb_entries;
0591     while (i--) {
0592         xskb = list_first_entry(&pool->free_list, struct xdp_buff_xsk, free_list_node);
0593         list_del_init(&xskb->free_list_node);
0594 
0595         *xdp = &xskb->xdp;
0596         xdp++;
0597     }
0598     pool->free_list_cnt -= nb_entries;
0599 
0600     return nb_entries;
0601 }
0602 
0603 u32 xp_alloc_batch(struct xsk_buff_pool *pool, struct xdp_buff **xdp, u32 max)
0604 {
0605     u32 nb_entries1 = 0, nb_entries2;
0606 
0607     if (unlikely(pool->dma_need_sync)) {
0608         struct xdp_buff *buff;
0609 
0610         /* Slow path */
0611         buff = xp_alloc(pool);
0612         if (buff)
0613             *xdp = buff;
0614         return !!buff;
0615     }
0616 
0617     if (unlikely(pool->free_list_cnt)) {
0618         nb_entries1 = xp_alloc_reused(pool, xdp, max);
0619         if (nb_entries1 == max)
0620             return nb_entries1;
0621 
0622         max -= nb_entries1;
0623         xdp += nb_entries1;
0624     }
0625 
0626     nb_entries2 = xp_alloc_new_from_fq(pool, xdp, max);
0627     if (!nb_entries2)
0628         pool->fq->queue_empty_descs++;
0629 
0630     return nb_entries1 + nb_entries2;
0631 }
0632 EXPORT_SYMBOL(xp_alloc_batch);
0633 
0634 bool xp_can_alloc(struct xsk_buff_pool *pool, u32 count)
0635 {
0636     if (pool->free_list_cnt >= count)
0637         return true;
0638     return xskq_cons_has_entries(pool->fq, count - pool->free_list_cnt);
0639 }
0640 EXPORT_SYMBOL(xp_can_alloc);
0641 
0642 void xp_free(struct xdp_buff_xsk *xskb)
0643 {
0644     if (!list_empty(&xskb->free_list_node))
0645         return;
0646 
0647     xskb->pool->free_list_cnt++;
0648     list_add(&xskb->free_list_node, &xskb->pool->free_list);
0649 }
0650 EXPORT_SYMBOL(xp_free);
0651 
0652 void *xp_raw_get_data(struct xsk_buff_pool *pool, u64 addr)
0653 {
0654     addr = pool->unaligned ? xp_unaligned_add_offset_to_addr(addr) : addr;
0655     return pool->addrs + addr;
0656 }
0657 EXPORT_SYMBOL(xp_raw_get_data);
0658 
0659 dma_addr_t xp_raw_get_dma(struct xsk_buff_pool *pool, u64 addr)
0660 {
0661     addr = pool->unaligned ? xp_unaligned_add_offset_to_addr(addr) : addr;
0662     return (pool->dma_pages[addr >> PAGE_SHIFT] &
0663         ~XSK_NEXT_PG_CONTIG_MASK) +
0664         (addr & ~PAGE_MASK);
0665 }
0666 EXPORT_SYMBOL(xp_raw_get_dma);
0667 
0668 void xp_dma_sync_for_cpu_slow(struct xdp_buff_xsk *xskb)
0669 {
0670     dma_sync_single_range_for_cpu(xskb->pool->dev, xskb->dma, 0,
0671                       xskb->pool->frame_len, DMA_BIDIRECTIONAL);
0672 }
0673 EXPORT_SYMBOL(xp_dma_sync_for_cpu_slow);
0674 
0675 void xp_dma_sync_for_device_slow(struct xsk_buff_pool *pool, dma_addr_t dma,
0676                  size_t size)
0677 {
0678     dma_sync_single_range_for_device(pool->dev, dma, 0,
0679                      size, DMA_BIDIRECTIONAL);
0680 }
0681 EXPORT_SYMBOL(xp_dma_sync_for_device_slow);