Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b48565f5 authored by David S. Miller's avatar David S. Miller
Browse files


Jeff Kirsher says:

====================
100GbE Intel Wired LAN Driver Updates 2015-12-05

This series contains updates to fm10k only.

Jacob provides the remaining fm10k patches in the series.  First change
ensures that all the logic regarding the setting of netdev features is
consolidated in one place of the driver.  Fixed an issue where an assumption
was being made on how many queues are available, especially when init_hw_vf()
errors out.  Fixed up an number of issues with init_hw() where failures
were not being handled properly or at all, so update the driver to check
returned error codes and respond appropriately.  Fixed up typecasting
issues found where either the incorrect typecast size was used or
explicitly typecast values.  Added additional debugging statistics and
rename statistic to better reflect its true value.  Added support for
ITR scaling based on PCIe link speed for fm10k.  Fixed up code comment
where "hardware" was misspelled.

v2: Dropped patches #1 and #10 from original submission, patch #1 was from
    Nick Krause and due to his past kernel interactions, dropping his patch.
    Patch #10 had questions and concerns from Tom Herbert which cannot be
    addressed at this time since the author (Jacob Keller) is currently on
    sabbatical, so dropping this patch for now until we can properly address
    Tom's questions and concerns.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents b82583ec 03d13a51
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -164,14 +164,20 @@ struct fm10k_ring_container {
	unsigned int total_packets;	/* total packets processed this int */
	u16 work_limit;			/* total work allowed per interrupt */
	u16 itr;			/* interrupt throttle rate value */
	u8 itr_scale;			/* ITR adjustment scaler based on PCI speed */
	u8 count;			/* total number of rings in vector */
};

#define FM10K_ITR_MAX		0x0FFF	/* maximum value for ITR */
#define FM10K_ITR_10K		100	/* 100us */
#define FM10K_ITR_20K		50	/* 50us */
#define FM10K_ITR_40K		25	/* 25us */
#define FM10K_ITR_ADAPTIVE	0x8000	/* adaptive interrupt moderation flag */

#define ITR_IS_ADAPTIVE(itr) (!!(itr & FM10K_ITR_ADAPTIVE))

#define FM10K_TX_ITR_DEFAULT	FM10K_ITR_40K
#define FM10K_RX_ITR_DEFAULT	FM10K_ITR_20K
#define FM10K_ITR_ENABLE	(FM10K_ITR_AUTOMASK | FM10K_ITR_MASK_CLEAR)

static inline struct netdev_queue *txring_txq(const struct fm10k_ring *ring)
@@ -484,7 +490,7 @@ void fm10k_netpoll(struct net_device *netdev);
#endif

/* Netdev */
struct net_device *fm10k_alloc_netdev(void);
struct net_device *fm10k_alloc_netdev(const struct fm10k_info *info);
int fm10k_setup_rx_resources(struct fm10k_ring *);
int fm10k_setup_tx_resources(struct fm10k_ring *);
void fm10k_free_rx_resources(struct fm10k_ring *);
+7 −7
Original line number Diff line number Diff line
@@ -111,12 +111,14 @@ static const struct fm10k_stats fm10k_gstrings_pf_stats[] = {

static const struct fm10k_stats fm10k_gstrings_mbx_stats[] = {
	FM10K_MBX_STAT("mbx_tx_busy", tx_busy),
	FM10K_MBX_STAT("mbx_tx_oversized", tx_dropped),
	FM10K_MBX_STAT("mbx_tx_dropped", tx_dropped),
	FM10K_MBX_STAT("mbx_tx_messages", tx_messages),
	FM10K_MBX_STAT("mbx_tx_dwords", tx_dwords),
	FM10K_MBX_STAT("mbx_tx_mbmem_pulled", tx_mbmem_pulled),
	FM10K_MBX_STAT("mbx_rx_messages", rx_messages),
	FM10K_MBX_STAT("mbx_rx_dwords", rx_dwords),
	FM10K_MBX_STAT("mbx_rx_parse_err", rx_parse_err),
	FM10K_MBX_STAT("mbx_rx_mbmem_pushed", rx_mbmem_pushed),
};

#define FM10K_GLOBAL_STATS_LEN ARRAY_SIZE(fm10k_gstrings_global_stats)
@@ -699,12 +701,10 @@ static int fm10k_get_coalesce(struct net_device *dev,
{
	struct fm10k_intfc *interface = netdev_priv(dev);

	ec->use_adaptive_tx_coalesce =
		!!(interface->tx_itr & FM10K_ITR_ADAPTIVE);
	ec->use_adaptive_tx_coalesce = ITR_IS_ADAPTIVE(interface->tx_itr);
	ec->tx_coalesce_usecs = interface->tx_itr & ~FM10K_ITR_ADAPTIVE;

	ec->use_adaptive_rx_coalesce =
		!!(interface->rx_itr & FM10K_ITR_ADAPTIVE);
	ec->use_adaptive_rx_coalesce = ITR_IS_ADAPTIVE(interface->rx_itr);
	ec->rx_coalesce_usecs = interface->rx_itr & ~FM10K_ITR_ADAPTIVE;

	return 0;
@@ -729,10 +729,10 @@ static int fm10k_set_coalesce(struct net_device *dev,

	/* set initial values for adaptive ITR */
	if (ec->use_adaptive_tx_coalesce)
		tx_itr = FM10K_ITR_ADAPTIVE | FM10K_ITR_10K;
		tx_itr = FM10K_ITR_ADAPTIVE | FM10K_TX_ITR_DEFAULT;

	if (ec->use_adaptive_rx_coalesce)
		rx_itr = FM10K_ITR_ADAPTIVE | FM10K_ITR_20K;
		rx_itr = FM10K_ITR_ADAPTIVE | FM10K_RX_ITR_DEFAULT;

	/* update interface */
	interface->tx_itr = tx_itr;
+44 −16
Original line number Diff line number Diff line
@@ -1094,11 +1094,11 @@ static void fm10k_tx_map(struct fm10k_ring *tx_ring,
netdev_tx_t fm10k_xmit_frame_ring(struct sk_buff *skb,
				  struct fm10k_ring *tx_ring)
{
	u16 count = TXD_USE_COUNT(skb_headlen(skb));
	struct fm10k_tx_buffer *first;
	int tso;
	u32 tx_flags = 0;
	unsigned short f;
	u16 count = TXD_USE_COUNT(skb_headlen(skb));
	u32 tx_flags = 0;
	int tso;

	/* need: 1 descriptor per page * PAGE_SIZE/FM10K_MAX_DATA_PER_TXD,
	 *       + 1 desc for skb_headlen/FM10K_MAX_DATA_PER_TXD,
@@ -1363,10 +1363,10 @@ static bool fm10k_clean_tx_irq(struct fm10k_q_vector *q_vector,
 **/
static void fm10k_update_itr(struct fm10k_ring_container *ring_container)
{
	unsigned int avg_wire_size, packets;
	unsigned int avg_wire_size, packets, itr_round;

	/* Only update ITR if we are using adaptive setting */
	if (!(ring_container->itr & FM10K_ITR_ADAPTIVE))
	if (!ITR_IS_ADAPTIVE(ring_container->itr))
		goto clear_counts;

	packets = ring_container->total_packets;
@@ -1375,18 +1375,44 @@ static void fm10k_update_itr(struct fm10k_ring_container *ring_container)

	avg_wire_size = ring_container->total_bytes / packets;

	/* Add 24 bytes to size to account for CRC, preamble, and gap */
	avg_wire_size += 24;

	/* Don't starve jumbo frames */
	if (avg_wire_size > 3000)
		avg_wire_size = 3000;
	/* The following is a crude approximation of:
	 *  wmem_default / (size + overhead) = desired_pkts_per_int
	 *  rate / bits_per_byte / (size + ethernet overhead) = pkt_rate
	 *  (desired_pkt_rate / pkt_rate) * usecs_per_sec = ITR value
	 *
	 * Assuming wmem_default is 212992 and overhead is 640 bytes per
	 * packet, (256 skb, 64 headroom, 320 shared info), we can reduce the
	 * formula down to
	 *
	 *  (34 * (size + 24)) / (size + 640) = ITR
	 *
	 * We first do some math on the packet size and then finally bitshift
	 * by 8 after rounding up. We also have to account for PCIe link speed
	 * difference as ITR scales based on this.
	 */
	if (avg_wire_size <= 360) {
		/* Start at 250K ints/sec and gradually drop to 77K ints/sec */
		avg_wire_size *= 8;
		avg_wire_size += 376;
	} else if (avg_wire_size <= 1152) {
		/* 77K ints/sec to 45K ints/sec */
		avg_wire_size *= 3;
		avg_wire_size += 2176;
	} else if (avg_wire_size <= 1920) {
		/* 45K ints/sec to 38K ints/sec */
		avg_wire_size += 4480;
	} else {
		/* plateau at a limit of 38K ints/sec */
		avg_wire_size = 6656;
	}

	/* Give a little boost to mid-size frames */
	if ((avg_wire_size > 300) && (avg_wire_size < 1200))
		avg_wire_size /= 3;
	else
		avg_wire_size /= 2;
	/* Perform final bitshift for division after rounding up to ensure
	 * that the calculation will never get below a 1. The bit shift
	 * accounts for changes in the ITR due to PCIe link speed.
	 */
	itr_round = ACCESS_ONCE(ring_container->itr_scale) + 8;
	avg_wire_size += (1 << itr_round) - 1;
	avg_wire_size >>= itr_round;

	/* write back value and retain adaptive flag */
	ring_container->itr = avg_wire_size | FM10K_ITR_ADAPTIVE;
@@ -1604,6 +1630,7 @@ static int fm10k_alloc_q_vector(struct fm10k_intfc *interface,
	q_vector->tx.ring = ring;
	q_vector->tx.work_limit = FM10K_DEFAULT_TX_WORK;
	q_vector->tx.itr = interface->tx_itr;
	q_vector->tx.itr_scale = interface->hw.mac.itr_scale;
	q_vector->tx.count = txr_count;

	while (txr_count) {
@@ -1632,6 +1659,7 @@ static int fm10k_alloc_q_vector(struct fm10k_intfc *interface,
	/* save Rx ring container info */
	q_vector->rx.ring = ring;
	q_vector->rx.itr = interface->rx_itr;
	q_vector->rx.itr_scale = interface->hw.mac.itr_scale;
	q_vector->rx.count = rxr_count;

	while (rxr_count) {
+4 −0
Original line number Diff line number Diff line
@@ -375,6 +375,8 @@ static void fm10k_mbx_write_copy(struct fm10k_hw *hw,
			if (!tail)
				tail++;

			mbx->tx_mbmem_pulled++;

			/* write message to hardware FIFO */
			fm10k_write_reg(hw, mbmem + tail++, *(head++));
		} while (--len && --end);
@@ -459,6 +461,8 @@ static void fm10k_mbx_read_copy(struct fm10k_hw *hw,
			if (!head)
				head++;

			mbx->rx_mbmem_pushed++;

			/* read message from hardware FIFO */
			*(tail++) = fm10k_read_reg(hw, mbmem + head++);
		} while (--len && --end);
+3 −1
Original line number Diff line number Diff line
/* Intel Ethernet Switch Host Interface Driver
 * Copyright(c) 2013 - 2014 Intel Corporation.
 * Copyright(c) 2013 - 2015 Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
@@ -291,8 +291,10 @@ struct fm10k_mbx_info {
	u64 tx_dropped;
	u64 tx_messages;
	u64 tx_dwords;
	u64 tx_mbmem_pulled;
	u64 rx_messages;
	u64 rx_dwords;
	u64 rx_mbmem_pushed;
	u64 rx_parse_err;

	/* Buffer to store messages */
Loading