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

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


Jeff Kirsher says:

====================
Intel Wired LAN Driver Updates 2014-06-05

This series contains updates to i40e and i40evf.

Jesse fixes an issue reported by Dave Jones where a couple of FD checks
ended up using bitwise OR where it should have been bitwise AND.

Neerav removes unused defines and macros for receive LRO.  Fix the driver
from allowing the user to set a larger MTU size that the hardware was
being configured to support.  Refactors send version which moves code in
two places into a small helper function.

Kamil modifies register diagnostics since register ranges can vary among
the different NVMs to avoid false test results.  So now we try to identify
the full range and use it for a register test and if we fail to define the
proper register range, we will only test the first register from that
group.  Then removes the check for large buffer since this was added in the
case this structure changed in the future, since the AQ definition is now
mature enough that this check is no longer necessary.

Mitch fixes i40evf driver to allocate descriptors in groups of 32 since the
hardware requires it.  Also fixes a crash when the ring size changed because
it would change the count before deallocating resources, causing the driver
to either free nonexistent buffers or leak leftover buffers.  Fixed the
driver to notify the VF for all types of resets so the VF can attempt a
graceful reinit.

Shannon refactors stats collection to create a unifying stats update routine
to call the various stat collection routines.  Removes rx_errors and
rx_missed stats since they were removed from the chip design.  Added
missing VSI statistics that the hardware offers but are not apart of the
standard netdev stats.

v2: dropped patch "i40e: Allow disabling of DCB via debugfs" from Neerav
    based on feedback from David Miller.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ebbe495f 41a9e55c
Loading
Loading
Loading
Loading
+0 −6
Original line number Diff line number Diff line
@@ -1062,8 +1062,6 @@ i40e_status i40e_aq_add_vsi(struct i40e_hw *hw,
	cmd->vsi_flags = cpu_to_le16(vsi_ctx->flags);

	desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD));
	if (sizeof(vsi_ctx->info) > I40E_AQ_LARGE_BUF)
		desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_LB);

	status = i40e_asq_send_command(hw, &desc, &vsi_ctx->info,
				    sizeof(vsi_ctx->info), cmd_details);
@@ -1204,8 +1202,6 @@ i40e_status i40e_aq_get_vsi_params(struct i40e_hw *hw,
	cmd->uplink_seid = cpu_to_le16(vsi_ctx->seid);

	desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_BUF);
	if (sizeof(vsi_ctx->info) > I40E_AQ_LARGE_BUF)
		desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_LB);

	status = i40e_asq_send_command(hw, &desc, &vsi_ctx->info,
				    sizeof(vsi_ctx->info), NULL);
@@ -1244,8 +1240,6 @@ i40e_status i40e_aq_update_vsi_params(struct i40e_hw *hw,
	cmd->uplink_seid = cpu_to_le16(vsi_ctx->seid);

	desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD));
	if (sizeof(vsi_ctx->info) > I40E_AQ_LARGE_BUF)
		desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_LB);

	status = i40e_asq_send_command(hw, &desc, &vsi_ctx->info,
				    sizeof(vsi_ctx->info), cmd_details);
+4 −5
Original line number Diff line number Diff line
@@ -862,12 +862,11 @@ static void i40e_dbg_dump_eth_stats(struct i40e_pf *pf,
		 "    rx_bytes = \t%lld \trx_unicast = \t\t%lld \trx_multicast = \t%lld\n",
		estats->rx_bytes, estats->rx_unicast, estats->rx_multicast);
	dev_info(&pf->pdev->dev,
		 "    rx_broadcast = \t%lld \trx_discards = \t\t%lld \trx_errors = \t%lld\n",
		 estats->rx_broadcast, estats->rx_discards, estats->rx_errors);
		 "    rx_broadcast = \t%lld \trx_discards = \t\t%lld\n",
		 estats->rx_broadcast, estats->rx_discards);
	dev_info(&pf->pdev->dev,
		 "    rx_missed = \t%lld \trx_unknown_protocol = \t%lld \ttx_bytes = \t%lld\n",
		 estats->rx_missed, estats->rx_unknown_protocol,
		 estats->tx_bytes);
		 "    rx_unknown_protocol = \t%lld \ttx_bytes = \t%lld\n",
		 estats->rx_unknown_protocol, estats->tx_bytes);
	dev_info(&pf->pdev->dev,
		 "    tx_unicast = \t%lld \ttx_multicast = \t\t%lld \ttx_broadcast = \t%lld\n",
		 estats->tx_unicast, estats->tx_multicast, estats->tx_broadcast);
+37 −13
Original line number Diff line number Diff line
@@ -67,16 +67,24 @@ static i40e_status i40e_diag_reg_pattern_test(struct i40e_hw *hw,

struct i40e_diag_reg_test_info i40e_reg_list[] = {
	/* offset               mask         elements   stride */
	{I40E_QTX_CTL(0),       0x0000FFBF,   4, I40E_QTX_CTL(1) - I40E_QTX_CTL(0)},
	{I40E_PFINT_ITR0(0),    0x00000FFF,   3, I40E_PFINT_ITR0(1) - I40E_PFINT_ITR0(0)},
	{I40E_PFINT_ITRN(0, 0), 0x00000FFF,   8, I40E_PFINT_ITRN(0, 1) - I40E_PFINT_ITRN(0, 0)},
	{I40E_PFINT_ITRN(1, 0), 0x00000FFF,   8, I40E_PFINT_ITRN(1, 1) - I40E_PFINT_ITRN(1, 0)},
	{I40E_PFINT_ITRN(2, 0), 0x00000FFF,   8, I40E_PFINT_ITRN(2, 1) - I40E_PFINT_ITRN(2, 0)},
	{I40E_QTX_CTL(0),       0x0000FFBF, 1,
		I40E_QTX_CTL(1) - I40E_QTX_CTL(0)},
	{I40E_PFINT_ITR0(0),    0x00000FFF, 3,
		I40E_PFINT_ITR0(1) - I40E_PFINT_ITR0(0)},
	{I40E_PFINT_ITRN(0, 0), 0x00000FFF, 1,
		I40E_PFINT_ITRN(0, 1) - I40E_PFINT_ITRN(0, 0)},
	{I40E_PFINT_ITRN(1, 0), 0x00000FFF, 1,
		I40E_PFINT_ITRN(1, 1) - I40E_PFINT_ITRN(1, 0)},
	{I40E_PFINT_ITRN(2, 0), 0x00000FFF, 1,
		I40E_PFINT_ITRN(2, 1) - I40E_PFINT_ITRN(2, 0)},
	{I40E_PFINT_STAT_CTL0,  0x0000000C, 1, 0},
	{I40E_PFINT_LNKLST0,    0x00001FFF, 1, 0},
	{I40E_PFINT_LNKLSTN(0), 0x000007FF,  64, I40E_PFINT_LNKLSTN(1) - I40E_PFINT_LNKLSTN(0)},
	{I40E_QINT_TQCTL(0),    0x000000FF,  64, I40E_QINT_TQCTL(1) - I40E_QINT_TQCTL(0)},
	{I40E_QINT_RQCTL(0),    0x000000FF,  64, I40E_QINT_RQCTL(1) - I40E_QINT_RQCTL(0)},
	{I40E_PFINT_LNKLSTN(0), 0x000007FF, 1,
		I40E_PFINT_LNKLSTN(1) - I40E_PFINT_LNKLSTN(0)},
	{I40E_QINT_TQCTL(0),    0x000000FF, 1,
		I40E_QINT_TQCTL(1) - I40E_QINT_TQCTL(0)},
	{I40E_QINT_RQCTL(0),    0x000000FF, 1,
		I40E_QINT_RQCTL(1) - I40E_QINT_RQCTL(0)},
	{I40E_PFINT_ICR0_ENA,   0xF7F20000, 1, 0},
	{ 0 }
};
@@ -93,9 +101,25 @@ i40e_status i40e_diag_reg_test(struct i40e_hw *hw)
	u32 reg, mask;
	u32 i, j;

	for (i = 0; (i40e_reg_list[i].offset != 0) && !ret_code; i++) {
	for (i = 0; i40e_reg_list[i].offset != 0 &&
					     !ret_code; i++) {

		/* set actual reg range for dynamically allocated resources */
		if (i40e_reg_list[i].offset == I40E_QTX_CTL(0) &&
		    hw->func_caps.num_tx_qp != 0)
			i40e_reg_list[i].elements = hw->func_caps.num_tx_qp;
		if ((i40e_reg_list[i].offset == I40E_PFINT_ITRN(0, 0) ||
		     i40e_reg_list[i].offset == I40E_PFINT_ITRN(1, 0) ||
		     i40e_reg_list[i].offset == I40E_PFINT_ITRN(2, 0) ||
		     i40e_reg_list[i].offset == I40E_QINT_TQCTL(0) ||
		     i40e_reg_list[i].offset == I40E_QINT_RQCTL(0)) &&
		    hw->func_caps.num_msix_vectors != 0)
			i40e_reg_list[i].elements =
				hw->func_caps.num_msix_vectors - 1;

		/* test register access */
		mask = i40e_reg_list[i].mask;
		for (j = 0; (j < i40e_reg_list[i].elements) && !ret_code; j++) {
		for (j = 0; j < i40e_reg_list[i].elements && !ret_code; j++) {
			reg = i40e_reg_list[i].offset +
			      (j * i40e_reg_list[i].stride);
			ret_code = i40e_diag_reg_pattern_test(hw, reg, mask);
+18 −1
Original line number Diff line number Diff line
@@ -62,6 +62,12 @@ static const struct i40e_stats i40e_gstrings_net_stats[] = {
	I40E_NETDEV_STAT(rx_crc_errors),
};

static const struct i40e_stats i40e_gstrings_misc_stats[] = {
	I40E_VSI_STAT("rx_unknown_protocol", eth_stats.rx_unknown_protocol),
	I40E_VSI_STAT("rx_broadcast", eth_stats.rx_broadcast),
	I40E_VSI_STAT("tx_broadcast", eth_stats.tx_broadcast),
};

static int i40e_add_fdir_ethtool(struct i40e_vsi *vsi,
				 struct ethtool_rxnfc *cmd);

@@ -78,7 +84,6 @@ static int i40e_add_fdir_ethtool(struct i40e_vsi *vsi,
static struct i40e_stats i40e_gstrings_stats[] = {
	I40E_PF_STAT("rx_bytes", stats.eth.rx_bytes),
	I40E_PF_STAT("tx_bytes", stats.eth.tx_bytes),
	I40E_PF_STAT("rx_errors", stats.eth.rx_errors),
	I40E_PF_STAT("tx_errors", stats.eth.tx_errors),
	I40E_PF_STAT("rx_dropped", stats.eth.rx_discards),
	I40E_PF_STAT("tx_dropped", stats.eth.tx_discards),
@@ -126,7 +131,9 @@ static struct i40e_stats i40e_gstrings_stats[] = {
	    * (sizeof(struct i40e_queue_stats) / sizeof(u64)))
#define I40E_GLOBAL_STATS_LEN	ARRAY_SIZE(i40e_gstrings_stats)
#define I40E_NETDEV_STATS_LEN   ARRAY_SIZE(i40e_gstrings_net_stats)
#define I40E_MISC_STATS_LEN	ARRAY_SIZE(i40e_gstrings_misc_stats)
#define I40E_VSI_STATS_LEN(n)   (I40E_NETDEV_STATS_LEN + \
				 I40E_MISC_STATS_LEN + \
				 I40E_QUEUE_STATS_LEN((n)))
#define I40E_PFC_STATS_LEN ( \
		(FIELD_SIZEOF(struct i40e_pf, stats.priority_xoff_rx) + \
@@ -649,6 +656,11 @@ static void i40e_get_ethtool_stats(struct net_device *netdev,
		data[i++] = (i40e_gstrings_net_stats[j].sizeof_stat ==
			sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
	}
	for (j = 0; j < I40E_MISC_STATS_LEN; j++) {
		p = (char *)vsi + i40e_gstrings_misc_stats[j].stat_offset;
		data[i++] = (i40e_gstrings_misc_stats[j].sizeof_stat ==
			    sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
	}
	rcu_read_lock();
	for (j = 0; j < vsi->num_queue_pairs; j++) {
		tx_ring = ACCESS_ONCE(vsi->tx_rings[j]);
@@ -715,6 +727,11 @@ static void i40e_get_strings(struct net_device *netdev, u32 stringset,
				 i40e_gstrings_net_stats[i].stat_string);
			p += ETH_GSTRING_LEN;
		}
		for (i = 0; i < I40E_MISC_STATS_LEN; i++) {
			snprintf(p, ETH_GSTRING_LEN, "%s",
				 i40e_gstrings_misc_stats[i].stat_string);
			p += ETH_GSTRING_LEN;
		}
		for (i = 0; i < vsi->num_queue_pairs; i++) {
			snprintf(p, ETH_GSTRING_LEN, "tx-%u.tx_packets", i);
			p += ETH_GSTRING_LEN;
+219 −185
Original line number Diff line number Diff line
@@ -530,6 +530,12 @@ void i40e_update_eth_stats(struct i40e_vsi *vsi)
	i40e_stat_update32(hw, I40E_GLV_RDPC(stat_idx),
			   vsi->stat_offsets_loaded,
			   &oes->rx_discards, &es->rx_discards);
	i40e_stat_update32(hw, I40E_GLV_RUPP(stat_idx),
			   vsi->stat_offsets_loaded,
			   &oes->rx_unknown_protocol, &es->rx_unknown_protocol);
	i40e_stat_update32(hw, I40E_GLV_TEPC(stat_idx),
			   vsi->stat_offsets_loaded,
			   &oes->tx_errors, &es->tx_errors);

	i40e_stat_update48(hw, I40E_GLV_GORCH(stat_idx),
			   I40E_GLV_GORCL(stat_idx),
@@ -720,19 +726,18 @@ static void i40e_update_prio_xoff_rx(struct i40e_pf *pf)
}

/**
 * i40e_update_stats - Update the board statistics counters.
 * i40e_update_vsi_stats - Update the vsi statistics counters.
 * @vsi: the VSI to be updated
 *
 * There are a few instances where we store the same stat in a
 * couple of different structs.  This is partly because we have
 * the netdev stats that need to be filled out, which is slightly
 * different from the "eth_stats" defined by the chip and used in
 * VF communications.  We sort it all out here in a central place.
 * VF communications.  We sort it out here.
 **/
void i40e_update_stats(struct i40e_vsi *vsi)
static void i40e_update_vsi_stats(struct i40e_vsi *vsi)
{
	struct i40e_pf *pf = vsi->back;
	struct i40e_hw *hw = &pf->hw;
	struct rtnl_link_stats64 *ons;
	struct rtnl_link_stats64 *ns;   /* netdev stats */
	struct i40e_eth_stats *oes;
@@ -741,8 +746,6 @@ void i40e_update_stats(struct i40e_vsi *vsi)
	u32 rx_page, rx_buf;
	u64 rx_p, rx_b;
	u64 tx_p, tx_b;
	u32 val;
	int i;
	u16 q;

	if (test_bit(__I40E_DOWN, &vsi->state) ||
@@ -804,21 +807,36 @@ void i40e_update_stats(struct i40e_vsi *vsi)
	ns->tx_packets = tx_p;
	ns->tx_bytes = tx_b;

	i40e_update_eth_stats(vsi);
	/* update netdev stats from eth stats */
	ons->rx_errors = oes->rx_errors;
	ns->rx_errors = es->rx_errors;
	i40e_update_eth_stats(vsi);
	ons->tx_errors = oes->tx_errors;
	ns->tx_errors = es->tx_errors;
	ons->multicast = oes->rx_multicast;
	ns->multicast = es->rx_multicast;
	ons->rx_dropped = oes->rx_discards;
	ns->rx_dropped = es->rx_discards;
	ons->tx_dropped = oes->tx_discards;
	ns->tx_dropped = es->tx_discards;

	/* Get the port data only if this is the main PF VSI */
	/* pull in a couple PF stats if this is the main vsi */
	if (vsi == pf->vsi[pf->lan_vsi]) {
		struct i40e_hw_port_stats *nsd = &pf->stats;
		ns->rx_crc_errors = pf->stats.crc_errors;
		ns->rx_errors = pf->stats.crc_errors + pf->stats.illegal_bytes;
		ns->rx_length_errors = pf->stats.rx_length_errors;
	}
}

/**
 * i40e_update_pf_stats - Update the pf statistics counters.
 * @pf: the PF to be updated
 **/
static void i40e_update_pf_stats(struct i40e_pf *pf)
{
	struct i40e_hw_port_stats *osd = &pf->stats_offsets;
	struct i40e_hw_port_stats *nsd = &pf->stats;
	struct i40e_hw *hw = &pf->hw;
	u32 val;
	int i;

	i40e_stat_update48(hw, I40E_GLPRT_GORCH(hw->port),
			   I40E_GLPRT_GORCL(hw->port),
@@ -850,13 +868,10 @@ void i40e_update_stats(struct i40e_vsi *vsi)
	i40e_stat_update32(hw, I40E_GLPRT_CRCERRS(hw->port),
			   pf->stat_offsets_loaded,
			   &osd->crc_errors, &nsd->crc_errors);
		ns->rx_crc_errors = nsd->crc_errors;

	i40e_stat_update32(hw, I40E_GLPRT_ILLERRC(hw->port),
			   pf->stat_offsets_loaded,
			   &osd->illegal_bytes, &nsd->illegal_bytes);
		ns->rx_errors = nsd->crc_errors
				+ nsd->illegal_bytes;

	i40e_stat_update32(hw, I40E_GLPRT_MLFC(hw->port),
			   pf->stat_offsets_loaded,
@@ -871,7 +886,6 @@ void i40e_update_stats(struct i40e_vsi *vsi)
			   pf->stat_offsets_loaded,
			   &osd->rx_length_errors,
			   &nsd->rx_length_errors);
		ns->rx_length_errors = nsd->rx_length_errors;

	i40e_stat_update32(hw, I40E_GLPRT_LXONRXC(hw->port),
			   pf->stat_offsets_loaded,
@@ -988,11 +1002,26 @@ void i40e_update_stats(struct i40e_vsi *vsi)
	i40e_stat_update32(hw, I40E_PRTPM_RLPIC,
			   pf->stat_offsets_loaded,
			   &osd->rx_lpi_count, &nsd->rx_lpi_count);
	}

	pf->stat_offsets_loaded = true;
}

/**
 * i40e_update_stats - Update the various statistics counters.
 * @vsi: the VSI to be updated
 *
 * Update the various stats for this VSI and its related entities.
 **/
void i40e_update_stats(struct i40e_vsi *vsi)
{
	struct i40e_pf *pf = vsi->back;

	if (vsi == pf->vsi[pf->lan_vsi])
		i40e_update_pf_stats(pf);

	i40e_update_vsi_stats(vsi);
}

/**
 * i40e_find_filter - Search VSI filter list for specific mac/vlan filter
 * @vsi: the VSI to be searched
@@ -1698,7 +1727,7 @@ static void i40e_sync_filters_subtask(struct i40e_pf *pf)
static int i40e_change_mtu(struct net_device *netdev, int new_mtu)
{
	struct i40e_netdev_priv *np = netdev_priv(netdev);
	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
	struct i40e_vsi *vsi = np->vsi;

	/* MTU < 68 is an error and causes problems on some kernels */
@@ -4412,6 +4441,9 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags)

	WARN_ON(in_interrupt());

	if (i40e_check_asq_alive(&pf->hw))
		i40e_vc_notify_reset(pf);

	/* do the biggest reset indicated */
	if (reset_flags & (1 << __I40E_GLOBAL_RESET_REQUESTED)) {

@@ -5328,9 +5360,6 @@ static int i40e_prep_for_reset(struct i40e_pf *pf)

	dev_dbg(&pf->pdev->dev, "Tearing down internal switch for reset\n");

	if (i40e_check_asq_alive(hw))
		i40e_vc_notify_reset(pf);

	/* quiesce the VSIs and their queues that are not already DOWN */
	i40e_pf_quiesce_all_vsi(pf);

@@ -5350,6 +5379,22 @@ static int i40e_prep_for_reset(struct i40e_pf *pf)
	return ret;
}

/**
 * i40e_send_version - update firmware with driver version
 * @pf: PF struct
 */
static void i40e_send_version(struct i40e_pf *pf)
{
	struct i40e_driver_version dv;

	dv.major_version = DRV_VERSION_MAJOR;
	dv.minor_version = DRV_VERSION_MINOR;
	dv.build_version = DRV_VERSION_BUILD;
	dv.subbuild_version = 0;
	strncpy(dv.driver_string, DRV_VERSION, sizeof(dv.driver_string));
	i40e_aq_send_driver_version(&pf->hw, &dv, NULL);
}

/**
 * i40e_reset_and_rebuild - reset and rebuild using a saved config
 * @pf: board private structure
@@ -5357,7 +5402,6 @@ static int i40e_prep_for_reset(struct i40e_pf *pf)
 **/
static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit)
{
	struct i40e_driver_version dv;
	struct i40e_hw *hw = &pf->hw;
	i40e_status ret;
	u32 v;
@@ -5490,11 +5534,7 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit)
	}

	/* tell the firmware that we're starting */
	dv.major_version = DRV_VERSION_MAJOR;
	dv.minor_version = DRV_VERSION_MINOR;
	dv.build_version = DRV_VERSION_BUILD;
	dv.subbuild_version = 0;
	i40e_aq_send_driver_version(&pf->hw, &dv, NULL);
	i40e_send_version(pf);

	dev_info(&pf->pdev->dev, "reset complete\n");

@@ -8138,7 +8178,6 @@ static void i40e_print_features(struct i40e_pf *pf)
 **/
static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
	struct i40e_driver_version dv;
	struct i40e_pf *pf;
	struct i40e_hw *hw;
	static u16 pfs_found;
@@ -8393,12 +8432,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
	i40e_dbg_pf_init(pf);

	/* tell the firmware that we're starting */
	dv.major_version = DRV_VERSION_MAJOR;
	dv.minor_version = DRV_VERSION_MINOR;
	dv.build_version = DRV_VERSION_BUILD;
	dv.subbuild_version = 0;
	strncpy(dv.driver_string, DRV_VERSION, sizeof(dv.driver_string));
	i40e_aq_send_driver_version(&pf->hw, &dv, NULL);
	i40e_send_version(pf);

	/* since everything's happy, start the service_task timer */
	mod_timer(&pf->service_timer,
Loading