Commit 08906eac authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files
Tony Nguyen says:

====================
Intel Wired LAN Driver Updates 2025-04-29 (igb, igc, ixgbe, idpf)

For igb:
Kurt Kanzenbach adds linking of IRQs and queues to NAPI instances and
adds persistent NAPI config. Lastly, he removes undesired IRQs that
occur while busy polling.

For igc:
Kurt Kanzenbach switches the Tx mode for MQPRIO offload to harmonize the
current implementation with TAPRIO.

For ixgbe:
Jedrzej adds separate ethtool ops for E610 devices to account for device
differences.

Slawomir adds devlink region support for E610 devices.

For idpf:
Mateusz assigns and utilizes the ptype field out of libeth_rqe_info.

Michal removes unreachable code.

* '1GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue:
  idpf: remove unreachable code from setting mailbox
  idpf: assign extracted ptype to struct libeth_rqe_info field
  ixgbe: devlink: add devlink region support for E610
  ixgbe: add E610 .set_phys_id() callback implementation
  ixgbe: apply different rules for setting FC on E610
  ixgbe: add support for ACPI WOL for E610
  ixgbe: create E610 specific ethtool_ops structure
  igc: Change Tx mode for MQPRIO offloading
  igc: Limit netdev_tc calls to MQPRIO
  igb: Get rid of spurious interrupts
  igb: Add support for persistent NAPI config
  igb: Link queues to NAPI instances
  igb: Link IRQs to NAPI instances
====================

Link: https://patch.msgid.link/20250429234651.3982025-1-anthony.l.nguyen@intel.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 337079d3 c058c5f8
Loading
Loading
Loading
Loading
+49 −0
Original line number Diff line number Diff line
@@ -120,3 +120,52 @@ EMP firmware image.

The driver does not currently support reloading the driver via
``DEVLINK_RELOAD_ACTION_DRIVER_REINIT``.

Regions
=======

The ``ixgbe`` driver implements the following regions for accessing internal
device data.

.. list-table:: regions implemented
    :widths: 15 85

    * - Name
      - Description
    * - ``nvm-flash``
      - The contents of the entire flash chip, sometimes referred to as
        the device's Non Volatile Memory.
    * - ``shadow-ram``
      - The contents of the Shadow RAM, which is loaded from the beginning
        of the flash. Although the contents are primarily from the flash,
        this area also contains data generated during device boot which is
        not stored in flash.
    * - ``device-caps``
      - The contents of the device firmware's capabilities buffer. Useful to
        determine the current state and configuration of the device.

Both the ``nvm-flash`` and ``shadow-ram`` regions can be accessed without a
snapshot. The ``device-caps`` region requires a snapshot as the contents are
sent by firmware and can't be split into separate reads.

Users can request an immediate capture of a snapshot for all three regions
via the ``DEVLINK_CMD_REGION_NEW`` command.

.. code:: shell

    $ devlink region show
    pci/0000:01:00.0/nvm-flash: size 10485760 snapshot [] max 1
    pci/0000:01:00.0/device-caps: size 4096 snapshot [] max 10

    $ devlink region new pci/0000:01:00.0/nvm-flash snapshot 1

    $ devlink region dump pci/0000:01:00.0/nvm-flash snapshot 1
    0000000000000000 0014 95dc 0014 9514 0035 1670 0034 db30
    0000000000000010 0000 0000 ffff ff04 0029 8c00 0028 8cc8
    0000000000000020 0016 0bb8 0016 1720 0000 0000 c00f 3ffc
    0000000000000030 bada cce5 bada cce5 bada cce5 bada cce5

    $ devlink region read pci/0000:01:00.0/nvm-flash snapshot 1 address 0 length 16
    0000000000000000 0014 95dc 0014 9514 0035 1670 0034 db30

    $ devlink region delete pci/0000:01:00.0/device-caps snapshot 1
+1 −17
Original line number Diff line number Diff line
@@ -143,22 +143,6 @@ static int idpf_mb_intr_req_irq(struct idpf_adapter *adapter)
	return 0;
}

/**
 * idpf_set_mb_vec_id - Set vector index for mailbox
 * @adapter: adapter structure to access the vector chunks
 *
 * The first vector id in the requested vector chunks from the CP is for
 * the mailbox
 */
static void idpf_set_mb_vec_id(struct idpf_adapter *adapter)
{
	if (adapter->req_vec_chunks)
		adapter->mb_vector.v_idx =
			le16_to_cpu(adapter->caps.mailbox_vector_id);
	else
		adapter->mb_vector.v_idx = 0;
}

/**
 * idpf_mb_intr_init - Initialize the mailbox interrupt
 * @adapter: adapter structure to store the mailbox vector
@@ -349,7 +333,7 @@ int idpf_intr_req(struct idpf_adapter *adapter)
		goto free_irq;
	}

	idpf_set_mb_vec_id(adapter);
	adapter->mb_vector.v_idx = le16_to_cpu(adapter->caps.mailbox_vector_id);

	vecids = kcalloc(total_vecs, sizeof(u16), GFP_KERNEL);
	if (!vecids) {
+11 −14
Original line number Diff line number Diff line
@@ -891,7 +891,6 @@ bool idpf_rx_singleq_buf_hw_alloc_all(struct idpf_rx_queue *rx_q,
 * idpf_rx_singleq_extract_base_fields - Extract fields from the Rx descriptor
 * @rx_desc: the descriptor to process
 * @fields: storage for extracted values
 * @ptype: pointer that will store packet type
 *
 * Decode the Rx descriptor and extract relevant information including the
 * size and Rx packet type.
@@ -901,21 +900,20 @@ bool idpf_rx_singleq_buf_hw_alloc_all(struct idpf_rx_queue *rx_q,
 */
static void
idpf_rx_singleq_extract_base_fields(const union virtchnl2_rx_desc *rx_desc,
				    struct libeth_rqe_info *fields, u32 *ptype)
				    struct libeth_rqe_info *fields)
{
	u64 qword;

	qword = le64_to_cpu(rx_desc->base_wb.qword1.status_error_ptype_len);

	fields->len = FIELD_GET(VIRTCHNL2_RX_BASE_DESC_QW1_LEN_PBUF_M, qword);
	*ptype = FIELD_GET(VIRTCHNL2_RX_BASE_DESC_QW1_PTYPE_M, qword);
	fields->ptype = FIELD_GET(VIRTCHNL2_RX_BASE_DESC_QW1_PTYPE_M, qword);
}

/**
 * idpf_rx_singleq_extract_flex_fields - Extract fields from the Rx descriptor
 * @rx_desc: the descriptor to process
 * @fields: storage for extracted values
 * @ptype: pointer that will store packet type
 *
 * Decode the Rx descriptor and extract relevant information including the
 * size and Rx packet type.
@@ -925,11 +923,11 @@ idpf_rx_singleq_extract_base_fields(const union virtchnl2_rx_desc *rx_desc,
 */
static void
idpf_rx_singleq_extract_flex_fields(const union virtchnl2_rx_desc *rx_desc,
				    struct libeth_rqe_info *fields, u32 *ptype)
				    struct libeth_rqe_info *fields)
{
	fields->len = FIELD_GET(VIRTCHNL2_RX_FLEX_DESC_PKT_LEN_M,
				le16_to_cpu(rx_desc->flex_nic_wb.pkt_len));
	*ptype = FIELD_GET(VIRTCHNL2_RX_FLEX_DESC_PTYPE_M,
	fields->ptype = FIELD_GET(VIRTCHNL2_RX_FLEX_DESC_PTYPE_M,
				  le16_to_cpu(rx_desc->flex_nic_wb.ptype_flex_flags0));
}

@@ -938,18 +936,17 @@ idpf_rx_singleq_extract_flex_fields(const union virtchnl2_rx_desc *rx_desc,
 * @rx_q: Rx descriptor queue
 * @rx_desc: the descriptor to process
 * @fields: storage for extracted values
 * @ptype: pointer that will store packet type
 *
 */
static void
idpf_rx_singleq_extract_fields(const struct idpf_rx_queue *rx_q,
			       const union virtchnl2_rx_desc *rx_desc,
			       struct libeth_rqe_info *fields, u32 *ptype)
			       struct libeth_rqe_info *fields)
{
	if (rx_q->rxdids == VIRTCHNL2_RXDID_1_32B_BASE_M)
		idpf_rx_singleq_extract_base_fields(rx_desc, fields, ptype);
		idpf_rx_singleq_extract_base_fields(rx_desc, fields);
	else
		idpf_rx_singleq_extract_flex_fields(rx_desc, fields, ptype);
		idpf_rx_singleq_extract_flex_fields(rx_desc, fields);
}

/**
@@ -972,7 +969,6 @@ static int idpf_rx_singleq_clean(struct idpf_rx_queue *rx_q, int budget)
		struct libeth_rqe_info fields = { };
		union virtchnl2_rx_desc *rx_desc;
		struct idpf_rx_buf *rx_buf;
		u32 ptype;

		/* get the Rx desc from Rx queue based on 'next_to_clean' */
		rx_desc = &rx_q->rx[ntc];
@@ -993,7 +989,7 @@ static int idpf_rx_singleq_clean(struct idpf_rx_queue *rx_q, int budget)
		 */
		dma_rmb();

		idpf_rx_singleq_extract_fields(rx_q, rx_desc, &fields, &ptype);
		idpf_rx_singleq_extract_fields(rx_q, rx_desc, &fields);

		rx_buf = &rx_q->rx_buf[ntc];
		if (!libeth_rx_sync_for_cpu(rx_buf, fields.len))
@@ -1037,7 +1033,8 @@ static int idpf_rx_singleq_clean(struct idpf_rx_queue *rx_q, int budget)
		total_rx_bytes += skb->len;

		/* protocol */
		idpf_rx_singleq_process_skb_fields(rx_q, skb, rx_desc, ptype);
		idpf_rx_singleq_process_skb_fields(rx_q, skb, rx_desc,
						   fields.ptype);

		/* send completed skb up the stack */
		napi_gro_receive(rx_q->pp->p.napi, skb);
+4 −1
Original line number Diff line number Diff line
@@ -391,7 +391,8 @@ enum e1000_ring_flags_t {
	IGB_RING_FLAG_RX_LB_VLAN_BSWAP,
	IGB_RING_FLAG_TX_CTX_IDX,
	IGB_RING_FLAG_TX_DETECT_HANG,
	IGB_RING_FLAG_TX_DISABLED
	IGB_RING_FLAG_TX_DISABLED,
	IGB_RING_FLAG_RX_ALLOC_FAILED,
};

#define ring_uses_large_buffer(ring) \
@@ -722,6 +723,8 @@ enum igb_boards {

extern char igb_driver_name[];

void igb_set_queue_napi(struct igb_adapter *adapter, int q_idx,
			struct napi_struct *napi);
int igb_xmit_xdp_ring(struct igb_adapter *adapter,
		      struct igb_ring *ring,
		      struct xdp_frame *xdpf);
+68 −10
Original line number Diff line number Diff line
@@ -947,6 +947,9 @@ static int igb_request_msix(struct igb_adapter *adapter)
				  q_vector);
		if (err)
			goto err_free;

		netif_napi_set_irq(&q_vector->napi,
				   adapter->msix_entries[vector].vector);
	}

	igb_configure_msix(adapter);
@@ -1194,7 +1197,8 @@ static int igb_alloc_q_vector(struct igb_adapter *adapter,
		return -ENOMEM;

	/* initialize NAPI */
	netif_napi_add(adapter->netdev, &q_vector->napi, igb_poll);
	netif_napi_add_config(adapter->netdev, &q_vector->napi, igb_poll,
			      v_idx);

	/* tie q_vector and adapter together */
	adapter->q_vector[v_idx] = q_vector;
@@ -2096,6 +2100,22 @@ static void igb_check_swap_media(struct igb_adapter *adapter)
	wr32(E1000_CTRL_EXT, ctrl_ext);
}

void igb_set_queue_napi(struct igb_adapter *adapter, int vector,
			struct napi_struct *napi)
{
	struct igb_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);
}

/**
 *  igb_up - Open the interface and prepare it to handle traffic
 *  @adapter: board private structure
@@ -2103,6 +2123,7 @@ static void igb_check_swap_media(struct igb_adapter *adapter)
int igb_up(struct igb_adapter *adapter)
{
	struct e1000_hw *hw = &adapter->hw;
	struct napi_struct *napi;
	int i;

	/* hardware has been reset, we need to reload some things */
@@ -2110,8 +2131,11 @@ int igb_up(struct igb_adapter *adapter)

	clear_bit(__IGB_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);
		igb_set_queue_napi(adapter, i, napi);
	}

	if (adapter->flags & IGB_FLAG_HAS_MSIX)
		igb_configure_msix(adapter);
@@ -2181,6 +2205,7 @@ void igb_down(struct igb_adapter *adapter)
	for (i = 0; i < adapter->num_q_vectors; i++) {
		if (adapter->q_vector[i]) {
			napi_synchronize(&adapter->q_vector[i]->napi);
			igb_set_queue_napi(adapter, i, NULL);
			napi_disable(&adapter->q_vector[i]->napi);
		}
	}
@@ -4113,8 +4138,9 @@ static int igb_sw_init(struct igb_adapter *adapter)
static int __igb_open(struct net_device *netdev, bool resuming)
{
	struct igb_adapter *adapter = netdev_priv(netdev);
	struct e1000_hw *hw = &adapter->hw;
	struct pci_dev *pdev = adapter->pdev;
	struct e1000_hw *hw = &adapter->hw;
	struct napi_struct *napi;
	int err;
	int i;

@@ -4166,8 +4192,11 @@ static int __igb_open(struct net_device *netdev, bool resuming)
	/* From here on the code is the same as igb_up() */
	clear_bit(__IGB_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);
		igb_set_queue_napi(adapter, i, napi);
	}

	/* Clear any pending interrupts. */
	rd32(E1000_TSICR);
@@ -5726,12 +5755,30 @@ static void igb_watchdog_task(struct work_struct *work)
	if (adapter->flags & IGB_FLAG_HAS_MSIX) {
		u32 eics = 0;

		for (i = 0; i < adapter->num_q_vectors; i++)
			eics |= adapter->q_vector[i]->eims_value;
		for (i = 0; i < adapter->num_q_vectors; i++) {
			struct igb_q_vector *q_vector = adapter->q_vector[i];
			struct igb_ring *rx_ring;

			if (!q_vector->rx.ring)
				continue;

			rx_ring = adapter->rx_ring[q_vector->rx.ring->queue_index];

			if (test_bit(IGB_RING_FLAG_RX_ALLOC_FAILED, &rx_ring->flags)) {
				eics |= q_vector->eims_value;
				clear_bit(IGB_RING_FLAG_RX_ALLOC_FAILED, &rx_ring->flags);
			}
		}
		if (eics)
			wr32(E1000_EICS, eics);
	} else {
		struct igb_ring *rx_ring = adapter->rx_ring[0];

		if (test_bit(IGB_RING_FLAG_RX_ALLOC_FAILED, &rx_ring->flags)) {
			clear_bit(IGB_RING_FLAG_RX_ALLOC_FAILED, &rx_ring->flags);
			wr32(E1000_ICS, E1000_ICS_RXDMT0);
		}
	}

	igb_spoof_check(adapter);
	igb_ptp_rx_hang(adapter);
@@ -9061,6 +9108,7 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
		if (!xdp_res && !skb) {
			rx_ring->rx_stats.alloc_failed++;
			rx_buffer->pagecnt_bias++;
			set_bit(IGB_RING_FLAG_RX_ALLOC_FAILED, &rx_ring->flags);
			break;
		}

@@ -9120,6 +9168,7 @@ static bool igb_alloc_mapped_page(struct igb_ring *rx_ring,
	page = dev_alloc_pages(igb_rx_pg_order(rx_ring));
	if (unlikely(!page)) {
		rx_ring->rx_stats.alloc_failed++;
		set_bit(IGB_RING_FLAG_RX_ALLOC_FAILED, &rx_ring->flags);
		return false;
	}

@@ -9136,6 +9185,7 @@ static bool igb_alloc_mapped_page(struct igb_ring *rx_ring,
		__free_pages(page, igb_rx_pg_order(rx_ring));

		rx_ring->rx_stats.alloc_failed++;
		set_bit(IGB_RING_FLAG_RX_ALLOC_FAILED, &rx_ring->flags);
		return false;
	}

@@ -9674,8 +9724,11 @@ static pci_ers_result_t igb_io_error_detected(struct pci_dev *pdev,
	if (state == pci_channel_io_perm_failure)
		return PCI_ERS_RESULT_DISCONNECT;

	rtnl_lock();
	if (netif_running(netdev))
		igb_down(adapter);
	rtnl_unlock();

	pci_disable_device(pdev);

	/* Request a slot reset. */
@@ -9734,16 +9787,21 @@ static void igb_io_resume(struct pci_dev *pdev)
	struct net_device *netdev = pci_get_drvdata(pdev);
	struct igb_adapter *adapter = netdev_priv(netdev);

	rtnl_lock();
	if (netif_running(netdev)) {
		if (!test_bit(__IGB_DOWN, &adapter->state)) {
			dev_dbg(&pdev->dev, "Resuming from non-fatal error, do nothing.\n");
			rtnl_unlock();
			return;
		}

		if (igb_up(adapter)) {
			dev_err(&pdev->dev, "igb_up failed after reset\n");
			rtnl_unlock();
			return;
		}
	}
	rtnl_unlock();

	netif_device_attach(netdev);

Loading