Something went wrong. Try again.
(I'm so sorry!) Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122// SPDX-License-Identifier: GPL-2.0-or-later
#include <net/netdev_queues.h>#include <net/netdev_rx_queue.h>#include <net/xdp_sock_drv.h>
#include "dev.h"
static struct device *__netdev_queue_get_dma_dev(struct net_device *dev, unsigned int idx){ const struct netdev_queue_mgmt_ops *queue_ops = dev->queue_mgmt_ops; struct device *dma_dev;
if (queue_ops && queue_ops->ndo_queue_get_dma_dev) dma_dev = queue_ops->ndo_queue_get_dma_dev(dev, idx); else dma_dev = dev->dev.parent;
return dma_dev && dma_dev->dma_mask ? dma_dev : NULL;}
/** * netdev_queue_get_dma_dev() - get dma device for zero-copy operations * @dev: net_device * @idx: queue index * @type: queue type (RX or TX) * * Get dma device for zero-copy operations to be used for this queue. If * the queue is an RX queue leased from a physical queue, we retrieve the * physical queue's dma device. When the dma device is not available or * valid, the function will return NULL. * * Return: Device or NULL on error */struct device *netdev_queue_get_dma_dev(struct net_device *dev, unsigned int idx, enum netdev_queue_type type){ struct netdev_rx_queue *hw_rxq; struct device *dma_dev;
netdev_assert_locked(dev);
/* Only RX side supports queue leasing today. */ if (type != NETDEV_QUEUE_TYPE_RX || !netif_rxq_is_leased(dev, idx)) return __netdev_queue_get_dma_dev(dev, idx); if (!netif_is_queue_leasee(dev)) return NULL;
hw_rxq = __netif_get_rx_queue(dev, idx)->lease;
netdev_lock(hw_rxq->dev); idx = get_netdev_rx_queue_index(hw_rxq); dma_dev = __netdev_queue_get_dma_dev(hw_rxq->dev, idx); netdev_unlock(hw_rxq->dev);
return dma_dev;}
bool netdev_can_create_queue(const struct net_device *dev, struct netlink_ext_ack *extack){ const char *msg = NULL;
if (dev->real_num_rx_queues < 1 || dev->real_num_tx_queues < 1) msg = "Device must have at least one real queue"; if (!dev->queue_mgmt_ops || !dev->queue_mgmt_ops->ndo_queue_create) msg = "Device does not support queue creation"; if (dev->dev.parent) msg = "Device is not a virtual device";
/* callers with extack=NULL are not from uAPI and don't want to trigger * the extack tracepoint. */ if (msg && extack) NL_SET_ERR_MSG_FMT(extack, "%s", msg);
return !msg;}
bool netdev_can_lease_queue(const struct net_device *dev, struct netlink_ext_ack *extack){ if (!dev->dev.parent) { NL_SET_ERR_MSG(extack, "Lease device is a virtual device"); return false; } if (!netif_device_present(dev)) { NL_SET_ERR_MSG(extack, "Lease device has been removed from the system"); return false; } if (!dev->queue_mgmt_ops) { NL_SET_ERR_MSG(extack, "Lease device does not support queue management operations"); return false; } return true;}
bool netdev_queue_busy(struct net_device *dev, unsigned int idx, enum netdev_queue_type type, struct netlink_ext_ack *extack){ if (xsk_get_pool_from_qid(dev, idx)) { NL_SET_ERR_MSG(extack, "Device queue in use by AF_XDP"); return true; } if (type == NETDEV_QUEUE_TYPE_TX) return false; if (netif_rxq_is_leased(dev, idx)) { NL_SET_ERR_MSG(extack, "Device queue in use due to queue leasing"); return true; } if (netif_rxq_has_mp(dev, idx)) { NL_SET_ERR_MSG(extack, "Device queue in use by memory provider"); return true; } return false;}