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

====================
Intel Wired LAN Driver Updates 2022-11-02 (i40e, iavf)

This series contains updates to i40e and iavf drivers.

Joe Damato adds tracepoint information to i40e_napi_poll to expose helpful
debug information for users who'd like to get a better understanding of
how their NIC is performing as they adjust various parameters and tuning
knobs.

Note: this does not touch any XDP related code paths. This
tracepoint will only work when not using XDP. Care has been taken to avoid
changing control flow in i40e_napi_poll with this change.

Alicja adds error messaging for unsupported duplex settings for i40e.

Ye Xingchen replaces use of __FUNCTION__ with __func__ for iavf.

Bartosz changes tense of device removal message to be more clear on the
action for iavf.

* '40GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue:
  iavf: Change information about device removal in dmesg
  iavf: Replace __FUNCTION__ with __func__
  i40e: Add appropriate error message logged for incorrect duplex setting
  i40e: Add i40e_napi_poll tracepoint
  i40e: Record number of RXes cleaned during NAPI
  i40e: Record number TXes cleaned during NAPI
  i40e: Store the irq number in i40e_q_vector
====================

Link: https://lore.kernel.org/r/20221102211011.2944983-1-anthony.l.nguyen@intel.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 20224838 69b95744
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -992,6 +992,7 @@ struct i40e_q_vector {
	struct rcu_head rcu;	/* to avoid race with update stats on free */
	char name[I40E_INT_NAME_STR_LEN];
	bool arm_wb_state;
	int irq_num;		/* IRQ assigned to this q_vector */
} ____cacheline_internodealigned_in_smp;

/* lan device */
+3 −1
Original line number Diff line number Diff line
@@ -1287,8 +1287,10 @@ static int i40e_set_link_ksettings(struct net_device *netdev,
	 * trying to set something that we do not support.
	 */
	if (memcmp(&copy_ks.base, &safe_ks.base,
		   sizeof(struct ethtool_link_settings)))
		   sizeof(struct ethtool_link_settings))) {
		netdev_err(netdev, "Only speed and autoneg are supported.\n");
		return -EOPNOTSUPP;
	}

	while (test_and_set_bit(__I40E_CONFIG_BUSY, pf->state)) {
		timeout--;
+1 −0
Original line number Diff line number Diff line
@@ -4123,6 +4123,7 @@ static int i40e_vsi_request_irq_msix(struct i40e_vsi *vsi, char *basename)
		}

		/* register for affinity change notifications */
		q_vector->irq_num = irq_num;
		q_vector->affinity_notify.notify = i40e_irq_affinity_notify;
		q_vector->affinity_notify.release = i40e_irq_affinity_release;
		irq_set_affinity_notifier(irq_num, &q_vector->affinity_notify);
+49 −0
Original line number Diff line number Diff line
@@ -55,6 +55,55 @@
 * being built from shared code.
 */

#define NO_DEV "(i40e no_device)"

TRACE_EVENT(i40e_napi_poll,

	TP_PROTO(struct napi_struct *napi, struct i40e_q_vector *q, int budget,
		 int budget_per_ring, unsigned int rx_cleaned, unsigned int tx_cleaned,
		 bool rx_clean_complete, bool tx_clean_complete),

	TP_ARGS(napi, q, budget, budget_per_ring, rx_cleaned, tx_cleaned,
		rx_clean_complete, tx_clean_complete),

	TP_STRUCT__entry(
		__field(int, budget)
		__field(int, budget_per_ring)
		__field(unsigned int, rx_cleaned)
		__field(unsigned int, tx_cleaned)
		__field(int, rx_clean_complete)
		__field(int, tx_clean_complete)
		__field(int, irq_num)
		__field(int, curr_cpu)
		__string(qname, q->name)
		__string(dev_name, napi->dev ? napi->dev->name : NO_DEV)
		__bitmask(irq_affinity,	nr_cpumask_bits)
	),

	TP_fast_assign(
		__entry->budget = budget;
		__entry->budget_per_ring = budget_per_ring;
		__entry->rx_cleaned = rx_cleaned;
		__entry->tx_cleaned = tx_cleaned;
		__entry->rx_clean_complete = rx_clean_complete;
		__entry->tx_clean_complete = tx_clean_complete;
		__entry->irq_num = q->irq_num;
		__entry->curr_cpu = get_cpu();
		__assign_str(qname, q->name);
		__assign_str(dev_name, napi->dev ? napi->dev->name : NO_DEV);
		__assign_bitmask(irq_affinity, cpumask_bits(&q->affinity_mask),
				 nr_cpumask_bits);
	),

	TP_printk("i40e_napi_poll on dev %s q %s irq %d irq_mask %s curr_cpu %d "
		  "budget %d bpr %d rx_cleaned %u tx_cleaned %u "
		  "rx_clean_complete %d tx_clean_complete %d",
		__get_str(dev_name), __get_str(qname), __entry->irq_num,
		__get_bitmask(irq_affinity), __entry->curr_cpu, __entry->budget,
		__entry->budget_per_ring, __entry->rx_cleaned, __entry->tx_cleaned,
		__entry->rx_clean_complete, __entry->tx_clean_complete)
);

/* Events related to a vsi & ring */
DECLARE_EVENT_CLASS(
	i40e_tx_template,
+21 −6
Original line number Diff line number Diff line
@@ -923,11 +923,13 @@ void i40e_detect_recover_hung(struct i40e_vsi *vsi)
 * @vsi: the VSI we care about
 * @tx_ring: Tx ring to clean
 * @napi_budget: Used to determine if we are in netpoll
 * @tx_cleaned: Out parameter set to the number of TXes cleaned
 *
 * Returns true if there's any budget left (e.g. the clean is finished)
 **/
static bool i40e_clean_tx_irq(struct i40e_vsi *vsi,
			      struct i40e_ring *tx_ring, int napi_budget)
			      struct i40e_ring *tx_ring, int napi_budget,
			      unsigned int *tx_cleaned)
{
	int i = tx_ring->next_to_clean;
	struct i40e_tx_buffer *tx_buf;
@@ -1048,6 +1050,7 @@ static bool i40e_clean_tx_irq(struct i40e_vsi *vsi,
		}
	}

	*tx_cleaned = total_packets;
	return !!budget;
}

@@ -2422,6 +2425,7 @@ static void i40e_inc_ntc(struct i40e_ring *rx_ring)
 * i40e_clean_rx_irq - Clean completed descriptors from Rx ring - bounce buf
 * @rx_ring: rx descriptor ring to transact packets on
 * @budget: Total limit on number of packets to process
 * @rx_cleaned: Out parameter of the number of packets processed
 *
 * This function provides a "bounce buffer" approach to Rx interrupt
 * processing.  The advantage to this is that on systems that have
@@ -2430,7 +2434,8 @@ static void i40e_inc_ntc(struct i40e_ring *rx_ring)
 *
 * Returns amount of work completed
 **/
static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget,
			     unsigned int *rx_cleaned)
{
	unsigned int total_rx_bytes = 0, total_rx_packets = 0, frame_sz = 0;
	u16 cleaned_count = I40E_DESC_UNUSED(rx_ring);
@@ -2567,6 +2572,8 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)

	i40e_update_rx_stats(rx_ring, total_rx_bytes, total_rx_packets);

	*rx_cleaned = total_rx_packets;

	/* guarantee a trip back through this routine if there was a failure */
	return failure ? budget : (int)total_rx_packets;
}
@@ -2689,6 +2696,10 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)
			       container_of(napi, struct i40e_q_vector, napi);
	struct i40e_vsi *vsi = q_vector->vsi;
	struct i40e_ring *ring;
	bool tx_clean_complete = true;
	bool rx_clean_complete = true;
	unsigned int tx_cleaned = 0;
	unsigned int rx_cleaned = 0;
	bool clean_complete = true;
	bool arm_wb = false;
	int budget_per_ring;
@@ -2705,10 +2716,10 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)
	i40e_for_each_ring(ring, q_vector->tx) {
		bool wd = ring->xsk_pool ?
			  i40e_clean_xdp_tx_irq(vsi, ring) :
			  i40e_clean_tx_irq(vsi, ring, budget);
			  i40e_clean_tx_irq(vsi, ring, budget, &tx_cleaned);

		if (!wd) {
			clean_complete = false;
			clean_complete = tx_clean_complete = false;
			continue;
		}
		arm_wb |= ring->arm_wb;
@@ -2733,14 +2744,18 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)
	i40e_for_each_ring(ring, q_vector->rx) {
		int cleaned = ring->xsk_pool ?
			      i40e_clean_rx_irq_zc(ring, budget_per_ring) :
			      i40e_clean_rx_irq(ring, budget_per_ring);
			      i40e_clean_rx_irq(ring, budget_per_ring, &rx_cleaned);

		work_done += cleaned;
		/* if we clean as many as budgeted, we must not be done */
		if (cleaned >= budget_per_ring)
			clean_complete = false;
			clean_complete = rx_clean_complete = false;
	}

	if (!i40e_enabled_xdp_vsi(vsi))
		trace_i40e_napi_poll(napi, q_vector, budget, budget_per_ring, rx_cleaned,
				     tx_cleaned, rx_clean_complete, tx_clean_complete);

	/* If work not completed, return budget and polling will return */
	if (!clean_complete) {
		int cpu_id = smp_processor_id();
Loading