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

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


Jeff Kirsher says:

====================
Intel Wired LAN Driver Fixes 2018-08-23

This series contains bug fixes to the ice driver.

Anirudh provides several fixes, starting with static analysis fixes by
replacing a bitwise-and with a constant value and replace "magic"
numbers with defines.  Fixed the control queue processing by removing
unnecessary read/writes to registers, as well as getting a accurate
value for "pending".  Added additional checks to avoid NULL pointer
dereferences.  Fixed up code formatting issues, by cleaning up code
comments and coding style.

Bruce cleans up a duplicate check for owner, within the same function.
Also cleans up interrupt causes that are not handled or applicable.
Fix checkpatch warning about the use of bool in structures due to the
wasted space and size of bool, so convert struct members to u8 instead.

Jake fixes a number of potential bugs in the reporting of stats via
ethtool, by simply reporting all the queue statistics, even for the
queues that are not activated.  Fixed a compiler warning, as well as
make the code a bit cleaner but just using order_base_2() for
calculating the power-of-2.

Preethi adds a check to avoid a NULL pointer dereference crash during
initialization.

Brett clarifies the code when it comes to port VLANs and regular VLANs,
by renaming defines and field values to match their intended use and
purpose.

Jesse initializes a variable to avoid garbage values being returned to
the caller.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 0d092f06 3968540b
Loading
Loading
Loading
Loading
+11 −4
Original line number Diff line number Diff line
@@ -89,6 +89,13 @@ extern const char ice_drv_ver[];
#define ice_for_each_rxq(vsi, i) \
	for ((i) = 0; (i) < (vsi)->num_rxq; (i)++)

/* Macros for each allocated tx/rx ring whether used or not in a VSI */
#define ice_for_each_alloc_txq(vsi, i) \
	for ((i) = 0; (i) < (vsi)->alloc_txq; (i)++)

#define ice_for_each_alloc_rxq(vsi, i) \
	for ((i) = 0; (i) < (vsi)->alloc_rxq; (i)++)

struct ice_tc_info {
	u16 qoffset;
	u16 qcount;
@@ -189,9 +196,9 @@ struct ice_vsi {
	struct list_head tmp_sync_list;		/* MAC filters to be synced */
	struct list_head tmp_unsync_list;	/* MAC filters to be unsynced */

	bool irqs_ready;
	bool current_isup;		 /* Sync 'link up' logging */
	bool stat_offsets_loaded;
	u8 irqs_ready;
	u8 current_isup;		 /* Sync 'link up' logging */
	u8 stat_offsets_loaded;

	/* queue information */
	u8 tx_mapping_mode;		 /* ICE_MAP_MODE_[CONTIG|SCATTER] */
@@ -262,7 +269,7 @@ struct ice_pf {
	struct ice_hw_port_stats stats;
	struct ice_hw_port_stats stats_prev;
	struct ice_hw hw;
	bool stat_prev_loaded;	/* has previous stats been loaded */
	u8 stat_prev_loaded;	/* has previous stats been loaded */
	char int_name[ICE_INT_NAME_STR_LEN];
};

+13 −12
Original line number Diff line number Diff line
@@ -329,19 +329,19 @@ struct ice_aqc_vsi_props {
	/* VLAN section */
	__le16 pvid; /* VLANS include priority bits */
	u8 pvlan_reserved[2];
	u8 port_vlan_flags;
#define ICE_AQ_VSI_PVLAN_MODE_S	0
#define ICE_AQ_VSI_PVLAN_MODE_M	(0x3 << ICE_AQ_VSI_PVLAN_MODE_S)
#define ICE_AQ_VSI_PVLAN_MODE_UNTAGGED	0x1
#define ICE_AQ_VSI_PVLAN_MODE_TAGGED	0x2
#define ICE_AQ_VSI_PVLAN_MODE_ALL	0x3
	u8 vlan_flags;
#define ICE_AQ_VSI_VLAN_MODE_S	0
#define ICE_AQ_VSI_VLAN_MODE_M	(0x3 << ICE_AQ_VSI_VLAN_MODE_S)
#define ICE_AQ_VSI_VLAN_MODE_UNTAGGED	0x1
#define ICE_AQ_VSI_VLAN_MODE_TAGGED	0x2
#define ICE_AQ_VSI_VLAN_MODE_ALL	0x3
#define ICE_AQ_VSI_PVLAN_INSERT_PVID	BIT(2)
#define ICE_AQ_VSI_PVLAN_EMOD_S	3
#define ICE_AQ_VSI_PVLAN_EMOD_M	(0x3 << ICE_AQ_VSI_PVLAN_EMOD_S)
#define ICE_AQ_VSI_PVLAN_EMOD_STR_BOTH	(0x0 << ICE_AQ_VSI_PVLAN_EMOD_S)
#define ICE_AQ_VSI_PVLAN_EMOD_STR_UP	(0x1 << ICE_AQ_VSI_PVLAN_EMOD_S)
#define ICE_AQ_VSI_PVLAN_EMOD_STR	(0x2 << ICE_AQ_VSI_PVLAN_EMOD_S)
#define ICE_AQ_VSI_PVLAN_EMOD_NOTHING	(0x3 << ICE_AQ_VSI_PVLAN_EMOD_S)
#define ICE_AQ_VSI_VLAN_EMOD_S		3
#define ICE_AQ_VSI_VLAN_EMOD_M		(0x3 << ICE_AQ_VSI_VLAN_EMOD_S)
#define ICE_AQ_VSI_VLAN_EMOD_STR_BOTH	(0x0 << ICE_AQ_VSI_VLAN_EMOD_S)
#define ICE_AQ_VSI_VLAN_EMOD_STR_UP	(0x1 << ICE_AQ_VSI_VLAN_EMOD_S)
#define ICE_AQ_VSI_VLAN_EMOD_STR	(0x2 << ICE_AQ_VSI_VLAN_EMOD_S)
#define ICE_AQ_VSI_VLAN_EMOD_NOTHING	(0x3 << ICE_AQ_VSI_VLAN_EMOD_S)
	u8 pvlan_reserved2[3];
	/* ingress egress up sections */
	__le32 ingress_table; /* bitmap, 3 bits per up */
@@ -594,6 +594,7 @@ struct ice_sw_rule_lg_act {
#define ICE_LG_ACT_GENERIC_OFFSET_M	(0x7 << ICE_LG_ACT_GENERIC_OFFSET_S)
#define ICE_LG_ACT_GENERIC_PRIORITY_S	22
#define ICE_LG_ACT_GENERIC_PRIORITY_M	(0x7 << ICE_LG_ACT_GENERIC_PRIORITY_S)
#define ICE_LG_ACT_GENERIC_OFF_RX_DESC_PROF_IDX	7

	/* Action = 7 - Set Stat count */
#define ICE_LG_ACT_STAT_COUNT		0x7
+18 −12
Original line number Diff line number Diff line
@@ -45,6 +45,9 @@ static enum ice_status ice_set_mac_type(struct ice_hw *hw)
/**
 * ice_clear_pf_cfg - Clear PF configuration
 * @hw: pointer to the hardware structure
 *
 * Clears any existing PF configuration (VSIs, VSI lists, switch rules, port
 * configuration, flow director filters, etc.).
 */
enum ice_status ice_clear_pf_cfg(struct ice_hw *hw)
{
@@ -1483,7 +1486,7 @@ enum ice_status ice_get_link_status(struct ice_port_info *pi, bool *link_up)
	struct ice_phy_info *phy_info;
	enum ice_status status = 0;

	if (!pi)
	if (!pi || !link_up)
		return ICE_ERR_PARAM;

	phy_info = &pi->phy;
@@ -1619,20 +1622,23 @@ __ice_aq_get_set_rss_lut(struct ice_hw *hw, u16 vsi_id, u8 lut_type, u8 *lut,
	}

	/* LUT size is only valid for Global and PF table types */
	if (lut_size == ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_128) {
		flags |= (ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_128_FLAG <<
			  ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S) &
			 ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_M;
	} else if (lut_size == ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_512) {
	switch (lut_size) {
	case ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_128:
		break;
	case ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_512:
		flags |= (ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_512_FLAG <<
			  ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S) &
			 ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_M;
	} else if ((lut_size == ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_2K) &&
		   (lut_type == ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF)) {
		break;
	case ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_2K:
		if (lut_type == ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF) {
			flags |= (ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_2K_FLAG <<
				  ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S) &
				 ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_M;
	} else {
			break;
		}
		/* fall-through */
	default:
		status = ICE_ERR_PARAM;
		goto ice_aq_get_set_rss_lut_exit;
	}
+20 −9
Original line number Diff line number Diff line
@@ -597,10 +597,14 @@ static enum ice_status ice_init_check_adminq(struct ice_hw *hw)
	return 0;

init_ctrlq_free_rq:
	if (cq->rq.head) {
		ice_shutdown_rq(hw, cq);
		mutex_destroy(&cq->rq_lock);
	}
	if (cq->sq.head) {
		ice_shutdown_sq(hw, cq);
		mutex_destroy(&cq->sq_lock);
	mutex_destroy(&cq->rq_lock);
	}
	return status;
}

@@ -706,11 +710,15 @@ static void ice_shutdown_ctrlq(struct ice_hw *hw, enum ice_ctl_q q_type)
		return;
	}

	if (cq->sq.head) {
		ice_shutdown_sq(hw, cq);
	ice_shutdown_rq(hw, cq);
		mutex_destroy(&cq->sq_lock);
	}
	if (cq->rq.head) {
		ice_shutdown_rq(hw, cq);
		mutex_destroy(&cq->rq_lock);
	}
}

/**
 * ice_shutdown_all_ctrlq - shutdown routine for all control queues
@@ -1057,8 +1065,11 @@ ice_clean_rq_elem(struct ice_hw *hw, struct ice_ctl_q_info *cq,

clean_rq_elem_out:
	/* Set pending if needed, unlock and return */
	if (pending)
	if (pending) {
		/* re-read HW head to calculate actual pending messages */
		ntu = (u16)(rd32(hw, cq->rq.head) & cq->rq.head_mask);
		*pending = (u16)((ntc > ntu ? cq->rq.count : 0) + (ntu - ntc));
	}
clean_rq_elem_err:
	mutex_unlock(&cq->rq_lock);

+39 −13
Original line number Diff line number Diff line
@@ -26,7 +26,7 @@ static int ice_q_stats_len(struct net_device *netdev)
{
	struct ice_netdev_priv *np = netdev_priv(netdev);

	return ((np->vsi->num_txq + np->vsi->num_rxq) *
	return ((np->vsi->alloc_txq + np->vsi->alloc_rxq) *
		(sizeof(struct ice_q_stats) / sizeof(u64)));
}

@@ -218,7 +218,7 @@ static void ice_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
			p += ETH_GSTRING_LEN;
		}

		ice_for_each_txq(vsi, i) {
		ice_for_each_alloc_txq(vsi, i) {
			snprintf(p, ETH_GSTRING_LEN,
				 "tx-queue-%u.tx_packets", i);
			p += ETH_GSTRING_LEN;
@@ -226,7 +226,7 @@ static void ice_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
			p += ETH_GSTRING_LEN;
		}

		ice_for_each_rxq(vsi, i) {
		ice_for_each_alloc_rxq(vsi, i) {
			snprintf(p, ETH_GSTRING_LEN,
				 "rx-queue-%u.rx_packets", i);
			p += ETH_GSTRING_LEN;
@@ -253,6 +253,24 @@ static int ice_get_sset_count(struct net_device *netdev, int sset)
{
	switch (sset) {
	case ETH_SS_STATS:
		/* The number (and order) of strings reported *must* remain
		 * constant for a given netdevice. This function must not
		 * report a different number based on run time parameters
		 * (such as the number of queues in use, or the setting of
		 * a private ethtool flag). This is due to the nature of the
		 * ethtool stats API.
		 *
		 * User space programs such as ethtool must make 3 separate
		 * ioctl requests, one for size, one for the strings, and
		 * finally one for the stats. Since these cross into
		 * user space, changes to the number or size could result in
		 * undefined memory access or incorrect string<->value
		 * correlations for statistics.
		 *
		 * Even if it appears to be safe, changes to the size or
		 * order of strings will suffer from race conditions and are
		 * not safe.
		 */
		return ICE_ALL_STATS_LEN(netdev);
	default:
		return -EOPNOTSUPP;
@@ -280,18 +298,26 @@ ice_get_ethtool_stats(struct net_device *netdev,
	/* populate per queue stats */
	rcu_read_lock();

	ice_for_each_txq(vsi, j) {
	ice_for_each_alloc_txq(vsi, j) {
		ring = READ_ONCE(vsi->tx_rings[j]);
		if (!ring)
			continue;
		if (ring) {
			data[i++] = ring->stats.pkts;
			data[i++] = ring->stats.bytes;
		} else {
			data[i++] = 0;
			data[i++] = 0;
		}
	}

	ice_for_each_rxq(vsi, j) {
	ice_for_each_alloc_rxq(vsi, j) {
		ring = READ_ONCE(vsi->rx_rings[j]);
		if (ring) {
			data[i++] = ring->stats.pkts;
			data[i++] = ring->stats.bytes;
		} else {
			data[i++] = 0;
			data[i++] = 0;
		}
	}

	rcu_read_unlock();
@@ -519,7 +545,7 @@ ice_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring)
		goto done;
	}

	for (i = 0; i < vsi->num_txq; i++) {
	for (i = 0; i < vsi->alloc_txq; i++) {
		/* clone ring and setup updated count */
		tx_rings[i] = *vsi->tx_rings[i];
		tx_rings[i].count = new_tx_cnt;
@@ -551,7 +577,7 @@ ice_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring)
		goto done;
	}

	for (i = 0; i < vsi->num_rxq; i++) {
	for (i = 0; i < vsi->alloc_rxq; i++) {
		/* clone ring and setup updated count */
		rx_rings[i] = *vsi->rx_rings[i];
		rx_rings[i].count = new_rx_cnt;
Loading