1 // SPDX-License-Identifier: GPL-2.0-or-later 2 3 #include <linux/netdevice.h> 4 #include <net/netdev_queues.h> 5 #include <net/netdev_rx_queue.h> 6 7 #include "page_pool_priv.h" 8 9 int netdev_rx_queue_restart(struct net_device *dev, unsigned int rxq_idx) 10 { 11 struct netdev_rx_queue *rxq = __netif_get_rx_queue(dev, rxq_idx); 12 void *new_mem, *old_mem; 13 int err; 14 15 if (!dev->queue_mgmt_ops || !dev->queue_mgmt_ops->ndo_queue_stop || 16 !dev->queue_mgmt_ops->ndo_queue_mem_free || 17 !dev->queue_mgmt_ops->ndo_queue_mem_alloc || 18 !dev->queue_mgmt_ops->ndo_queue_start) 19 return -EOPNOTSUPP; 20 21 ASSERT_RTNL(); 22 23 new_mem = kvzalloc(dev->queue_mgmt_ops->ndo_queue_mem_size, GFP_KERNEL); 24 if (!new_mem) 25 return -ENOMEM; 26 27 old_mem = kvzalloc(dev->queue_mgmt_ops->ndo_queue_mem_size, GFP_KERNEL); 28 if (!old_mem) { 29 err = -ENOMEM; 30 goto err_free_new_mem; 31 } 32 33 err = dev->queue_mgmt_ops->ndo_queue_mem_alloc(dev, new_mem, rxq_idx); 34 if (err) 35 goto err_free_old_mem; 36 37 err = page_pool_check_memory_provider(dev, rxq); 38 if (err) 39 goto err_free_new_queue_mem; 40 41 err = dev->queue_mgmt_ops->ndo_queue_stop(dev, old_mem, rxq_idx); 42 if (err) 43 goto err_free_new_queue_mem; 44 45 err = dev->queue_mgmt_ops->ndo_queue_start(dev, new_mem, rxq_idx); 46 if (err) 47 goto err_start_queue; 48 49 dev->queue_mgmt_ops->ndo_queue_mem_free(dev, old_mem); 50 51 kvfree(old_mem); 52 kvfree(new_mem); 53 54 return 0; 55 56 err_start_queue: 57 /* Restarting the queue with old_mem should be successful as we haven't 58 * changed any of the queue configuration, and there is not much we can 59 * do to recover from a failure here. 60 * 61 * WARN if we fail to recover the old rx queue, and at least free 62 * old_mem so we don't also leak that. 63 */ 64 if (dev->queue_mgmt_ops->ndo_queue_start(dev, old_mem, rxq_idx)) { 65 WARN(1, 66 "Failed to restart old queue in error path. RX queue %d may be unhealthy.", 67 rxq_idx); 68 dev->queue_mgmt_ops->ndo_queue_mem_free(dev, old_mem); 69 } 70 71 err_free_new_queue_mem: 72 dev->queue_mgmt_ops->ndo_queue_mem_free(dev, new_mem); 73 74 err_free_old_mem: 75 kvfree(old_mem); 76 77 err_free_new_mem: 78 kvfree(new_mem); 79 80 return err; 81 } 82
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.