mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	igc: Link queues to NAPI instances
Link queues to NAPI instances via netdev-genl API so that users can
query this information with netlink. Handle a few cases in the driver:
  1. Link/unlink the NAPIs when XDP is enabled/disabled
  2. Handle IGC_FLAG_QUEUE_PAIRS enabled and disabled
Example output when IGC_FLAG_QUEUE_PAIRS is enabled:
$ ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/netdev.yaml \
                         --dump queue-get --json='{"ifindex": 2}'
[{'id': 0, 'ifindex': 2, 'napi-id': 8193, 'type': 'rx'},
 {'id': 1, 'ifindex': 2, 'napi-id': 8194, 'type': 'rx'},
 {'id': 2, 'ifindex': 2, 'napi-id': 8195, 'type': 'rx'},
 {'id': 3, 'ifindex': 2, 'napi-id': 8196, 'type': 'rx'},
 {'id': 0, 'ifindex': 2, 'napi-id': 8193, 'type': 'tx'},
 {'id': 1, 'ifindex': 2, 'napi-id': 8194, 'type': 'tx'},
 {'id': 2, 'ifindex': 2, 'napi-id': 8195, 'type': 'tx'},
 {'id': 3, 'ifindex': 2, 'napi-id': 8196, 'type': 'tx'}]
Since IGC_FLAG_QUEUE_PAIRS is enabled, you'll note that the same NAPI ID
is present for both rx and tx queues at the same index, for example
index 0:
{'id': 0, 'ifindex': 2, 'napi-id': 8193, 'type': 'rx'},
{'id': 0, 'ifindex': 2, 'napi-id': 8193, 'type': 'tx'},
To test IGC_FLAG_QUEUE_PAIRS disabled, a test system was booted using
the grub command line option "maxcpus=2" to force
igc_set_interrupt_capability to disable IGC_FLAG_QUEUE_PAIRS.
Example output when IGC_FLAG_QUEUE_PAIRS is disabled:
$ lscpu | grep "On-line CPU"
On-line CPU(s) list:      0,2
$ ethtool -l enp86s0  | tail -5
Current hardware settings:
RX:		n/a
TX:		n/a
Other:		1
Combined:	2
$ cat /proc/interrupts  | grep enp
 144: [...] enp86s0
 145: [...] enp86s0-rx-0
 146: [...] enp86s0-rx-1
 147: [...] enp86s0-tx-0
 148: [...] enp86s0-tx-1
1 "other" IRQ, and 2 IRQs for each of RX and Tx, so we expect netlink to
report 4 IRQs with unique NAPI IDs:
$ ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/netdev.yaml \
                         --dump napi-get --json='{"ifindex": 2}'
[{'id': 8196, 'ifindex': 2, 'irq': 148},
 {'id': 8195, 'ifindex': 2, 'irq': 147},
 {'id': 8194, 'ifindex': 2, 'irq': 146},
 {'id': 8193, 'ifindex': 2, 'irq': 145}]
Now we examine which queues these NAPIs are associated with, expecting
that since IGC_FLAG_QUEUE_PAIRS is disabled each RX and TX queue will
have its own NAPI instance:
$ ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/netdev.yaml \
                         --dump queue-get --json='{"ifindex": 2}'
[{'id': 0, 'ifindex': 2, 'napi-id': 8193, 'type': 'rx'},
 {'id': 1, 'ifindex': 2, 'napi-id': 8194, 'type': 'rx'},
 {'id': 0, 'ifindex': 2, 'napi-id': 8195, 'type': 'tx'},
 {'id': 1, 'ifindex': 2, 'napi-id': 8196, 'type': 'tx'}]
Signed-off-by: Joe Damato <jdamato@fastly.com>
Reviewed-by: Vitaly Lifshits <vitaly.lifshits@intel.com>
Tested-by: Avigail Dahan <avigailx.dahan@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Link: https://patch.msgid.link/20250106221929.956999-15-anthony.l.nguyen@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
			
			
This commit is contained in:
		
							parent
							
								
									1a63399c13
								
							
						
					
					
						commit
						b65969856d
					
				
					 3 changed files with 51 additions and 9 deletions
				
			
		| 
						 | 
				
			
			@ -337,6 +337,8 @@ struct igc_adapter {
 | 
			
		|||
	struct igc_led_classdev *leds;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void igc_set_queue_napi(struct igc_adapter *adapter, int q_idx,
 | 
			
		||||
			struct napi_struct *napi);
 | 
			
		||||
void igc_up(struct igc_adapter *adapter);
 | 
			
		||||
void igc_down(struct igc_adapter *adapter);
 | 
			
		||||
int igc_open(struct net_device *netdev);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4942,6 +4942,22 @@ static int igc_sw_init(struct igc_adapter *adapter)
 | 
			
		|||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void igc_set_queue_napi(struct igc_adapter *adapter, int vector,
 | 
			
		||||
			struct napi_struct *napi)
 | 
			
		||||
{
 | 
			
		||||
	struct igc_q_vector *q_vector = adapter->q_vector[vector];
 | 
			
		||||
 | 
			
		||||
	if (q_vector->rx.ring)
 | 
			
		||||
		netif_queue_set_napi(adapter->netdev,
 | 
			
		||||
				     q_vector->rx.ring->queue_index,
 | 
			
		||||
				     NETDEV_QUEUE_TYPE_RX, napi);
 | 
			
		||||
 | 
			
		||||
	if (q_vector->tx.ring)
 | 
			
		||||
		netif_queue_set_napi(adapter->netdev,
 | 
			
		||||
				     q_vector->tx.ring->queue_index,
 | 
			
		||||
				     NETDEV_QUEUE_TYPE_TX, napi);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * igc_up - Open the interface and prepare it to handle traffic
 | 
			
		||||
 * @adapter: board private structure
 | 
			
		||||
| 
						 | 
				
			
			@ -4949,6 +4965,7 @@ static int igc_sw_init(struct igc_adapter *adapter)
 | 
			
		|||
void igc_up(struct igc_adapter *adapter)
 | 
			
		||||
{
 | 
			
		||||
	struct igc_hw *hw = &adapter->hw;
 | 
			
		||||
	struct napi_struct *napi;
 | 
			
		||||
	int i = 0;
 | 
			
		||||
 | 
			
		||||
	/* hardware has been reset, we need to reload some things */
 | 
			
		||||
| 
						 | 
				
			
			@ -4956,8 +4973,11 @@ void igc_up(struct igc_adapter *adapter)
 | 
			
		|||
 | 
			
		||||
	clear_bit(__IGC_DOWN, &adapter->state);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < adapter->num_q_vectors; i++)
 | 
			
		||||
		napi_enable(&adapter->q_vector[i]->napi);
 | 
			
		||||
	for (i = 0; i < adapter->num_q_vectors; i++) {
 | 
			
		||||
		napi = &adapter->q_vector[i]->napi;
 | 
			
		||||
		napi_enable(napi);
 | 
			
		||||
		igc_set_queue_napi(adapter, i, napi);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (adapter->msix_entries)
 | 
			
		||||
		igc_configure_msix(adapter);
 | 
			
		||||
| 
						 | 
				
			
			@ -5186,6 +5206,7 @@ void igc_down(struct igc_adapter *adapter)
 | 
			
		|||
	for (i = 0; i < adapter->num_q_vectors; i++) {
 | 
			
		||||
		if (adapter->q_vector[i]) {
 | 
			
		||||
			napi_synchronize(&adapter->q_vector[i]->napi);
 | 
			
		||||
			igc_set_queue_napi(adapter, i, NULL);
 | 
			
		||||
			napi_disable(&adapter->q_vector[i]->napi);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -6015,6 +6036,7 @@ static int __igc_open(struct net_device *netdev, bool resuming)
 | 
			
		|||
	struct igc_adapter *adapter = netdev_priv(netdev);
 | 
			
		||||
	struct pci_dev *pdev = adapter->pdev;
 | 
			
		||||
	struct igc_hw *hw = &adapter->hw;
 | 
			
		||||
	struct napi_struct *napi;
 | 
			
		||||
	int err = 0;
 | 
			
		||||
	int i = 0;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -6050,8 +6072,11 @@ static int __igc_open(struct net_device *netdev, bool resuming)
 | 
			
		|||
 | 
			
		||||
	clear_bit(__IGC_DOWN, &adapter->state);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < adapter->num_q_vectors; i++)
 | 
			
		||||
		napi_enable(&adapter->q_vector[i]->napi);
 | 
			
		||||
	for (i = 0; i < adapter->num_q_vectors; i++) {
 | 
			
		||||
		napi = &adapter->q_vector[i]->napi;
 | 
			
		||||
		napi_enable(napi);
 | 
			
		||||
		igc_set_queue_napi(adapter, i, napi);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Clear any pending interrupts. */
 | 
			
		||||
	rd32(IGC_ICR);
 | 
			
		||||
| 
						 | 
				
			
			@ -7296,7 +7321,7 @@ static void igc_deliver_wake_packet(struct net_device *netdev)
 | 
			
		|||
	netif_rx(skb);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int igc_resume(struct device *dev)
 | 
			
		||||
static int __igc_resume(struct device *dev, bool rpm)
 | 
			
		||||
{
 | 
			
		||||
	struct pci_dev *pdev = to_pci_dev(dev);
 | 
			
		||||
	struct net_device *netdev = pci_get_drvdata(pdev);
 | 
			
		||||
| 
						 | 
				
			
			@ -7339,7 +7364,11 @@ static int igc_resume(struct device *dev)
 | 
			
		|||
	wr32(IGC_WUS, ~0);
 | 
			
		||||
 | 
			
		||||
	if (netif_running(netdev)) {
 | 
			
		||||
		if (!rpm)
 | 
			
		||||
			rtnl_lock();
 | 
			
		||||
		err = __igc_open(netdev, true);
 | 
			
		||||
		if (!rpm)
 | 
			
		||||
			rtnl_unlock();
 | 
			
		||||
		if (!err)
 | 
			
		||||
			netif_device_attach(netdev);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -7347,9 +7376,14 @@ static int igc_resume(struct device *dev)
 | 
			
		|||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int igc_resume(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	return __igc_resume(dev, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int igc_runtime_resume(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	return igc_resume(dev);
 | 
			
		||||
	return __igc_resume(dev, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int igc_suspend(struct device *dev)
 | 
			
		||||
| 
						 | 
				
			
			@ -7394,14 +7428,18 @@ static pci_ers_result_t igc_io_error_detected(struct pci_dev *pdev,
 | 
			
		|||
	struct net_device *netdev = pci_get_drvdata(pdev);
 | 
			
		||||
	struct igc_adapter *adapter = netdev_priv(netdev);
 | 
			
		||||
 | 
			
		||||
	rtnl_lock();
 | 
			
		||||
	netif_device_detach(netdev);
 | 
			
		||||
 | 
			
		||||
	if (state == pci_channel_io_perm_failure)
 | 
			
		||||
	if (state == pci_channel_io_perm_failure) {
 | 
			
		||||
		rtnl_unlock();
 | 
			
		||||
		return PCI_ERS_RESULT_DISCONNECT;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (netif_running(netdev))
 | 
			
		||||
		igc_down(adapter);
 | 
			
		||||
	pci_disable_device(pdev);
 | 
			
		||||
	rtnl_unlock();
 | 
			
		||||
 | 
			
		||||
	/* Request a slot reset. */
 | 
			
		||||
	return PCI_ERS_RESULT_NEED_RESET;
 | 
			
		||||
| 
						 | 
				
			
			@ -7412,7 +7450,7 @@ static pci_ers_result_t igc_io_error_detected(struct pci_dev *pdev,
 | 
			
		|||
 *  @pdev: Pointer to PCI device
 | 
			
		||||
 *
 | 
			
		||||
 *  Restart the card from scratch, as if from a cold-boot. Implementation
 | 
			
		||||
 *  resembles the first-half of the igc_resume routine.
 | 
			
		||||
 *  resembles the first-half of the __igc_resume routine.
 | 
			
		||||
 **/
 | 
			
		||||
static pci_ers_result_t igc_io_slot_reset(struct pci_dev *pdev)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -7451,7 +7489,7 @@ static pci_ers_result_t igc_io_slot_reset(struct pci_dev *pdev)
 | 
			
		|||
 *
 | 
			
		||||
 *  This callback is called when the error recovery driver tells us that
 | 
			
		||||
 *  its OK to resume normal operation. Implementation resembles the
 | 
			
		||||
 *  second-half of the igc_resume routine.
 | 
			
		||||
 *  second-half of the __igc_resume routine.
 | 
			
		||||
 */
 | 
			
		||||
static void igc_io_resume(struct pci_dev *pdev)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -86,6 +86,7 @@ static int igc_xdp_enable_pool(struct igc_adapter *adapter,
 | 
			
		|||
		napi_disable(napi);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	igc_set_queue_napi(adapter, queue_id, NULL);
 | 
			
		||||
	set_bit(IGC_RING_FLAG_AF_XDP_ZC, &rx_ring->flags);
 | 
			
		||||
	set_bit(IGC_RING_FLAG_AF_XDP_ZC, &tx_ring->flags);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -135,6 +136,7 @@ static int igc_xdp_disable_pool(struct igc_adapter *adapter, u16 queue_id)
 | 
			
		|||
	xsk_pool_dma_unmap(pool, IGC_RX_DMA_ATTR);
 | 
			
		||||
	clear_bit(IGC_RING_FLAG_AF_XDP_ZC, &rx_ring->flags);
 | 
			
		||||
	clear_bit(IGC_RING_FLAG_AF_XDP_ZC, &tx_ring->flags);
 | 
			
		||||
	igc_set_queue_napi(adapter, queue_id, napi);
 | 
			
		||||
 | 
			
		||||
	if (needs_reset) {
 | 
			
		||||
		napi_enable(napi);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue