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


Jeff Kirsher says:

====================
100GbE Intel Wired LAN Driver Updates 2019-03-22

This series contains updates to ice driver only.

Akeem enables MAC anti-spoofing by default when a new VSI is being
created.  Fixes an issue when reclaiming VF resources back to the pool
after reset, by freeing VF resources separately using the first VF
vector index to traverse the list, instead of starting at the last
assigned vectors list.  Added support for VF & PF promiscuous mode in
the ice driver.  Fixed the PF driver from letting the VF know it is "not
trusted" when it attempts to add more than its permitted additional MAC
addresses.  Altered how the driver gets the VF VSIs instances, instead
of using the mailbox messages to retrieve VSIs, get it directly via the
VF object in the PF data structure.

Bruce fixes return values to resolve static analysis warnings.  Made
whitespace changes to increase readability and reduce code wrapping.

Anirudh cleans up code by removing a function prototype that was never
implemented and removed an unused field in the ice_sched_vsi_info
structure.

Kiran fixes a potential divide by zero issue by adding a check.

Victor cleans up the transmit scheduler by adjusting the stack variable
usage and added/modified debug prints to make them more useful.

Yashaswini updates the driver in VEB mode to ensure that the LAN_EN bit
is set if all the right conditions are met.

Christopher ensures the loopback enable bit is not set for prune switch
rules, since all transmit traffic would be looped back to the internal
switch and dropped.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents bdaba895 f1ef73f5
Loading
Loading
Loading
Loading
+21 −2
Original line number Diff line number Diff line
@@ -125,6 +125,23 @@ extern const char ice_drv_ver[];
#define ice_for_each_q_vector(vsi, i) \
	for ((i) = 0; (i) < (vsi)->num_q_vectors; (i)++)

#define ICE_UCAST_PROMISC_BITS (ICE_PROMISC_UCAST_TX | ICE_PROMISC_MCAST_TX | \
				ICE_PROMISC_UCAST_RX | ICE_PROMISC_MCAST_RX)

#define ICE_UCAST_VLAN_PROMISC_BITS (ICE_PROMISC_UCAST_TX | \
				     ICE_PROMISC_MCAST_TX | \
				     ICE_PROMISC_UCAST_RX | \
				     ICE_PROMISC_MCAST_RX | \
				     ICE_PROMISC_VLAN_TX  | \
				     ICE_PROMISC_VLAN_RX)

#define ICE_MCAST_PROMISC_BITS (ICE_PROMISC_MCAST_TX | ICE_PROMISC_MCAST_RX)

#define ICE_MCAST_VLAN_PROMISC_BITS (ICE_PROMISC_MCAST_TX | \
				     ICE_PROMISC_MCAST_RX | \
				     ICE_PROMISC_VLAN_TX  | \
				     ICE_PROMISC_VLAN_RX)

struct ice_tc_info {
	u16 qoffset;
	u16 qcount_tx;
@@ -258,6 +275,7 @@ struct ice_vsi {
	u8 irqs_ready;
	u8 current_isup;		 /* Sync 'link up' logging */
	u8 stat_offsets_loaded;
	u8 vlan_ena;

	/* queue information */
	u8 tx_mapping_mode;		 /* ICE_MAP_MODE_[CONTIG|SCATTER] */
@@ -367,7 +385,8 @@ struct ice_netdev_priv {
 * @vsi: pointer to vsi struct, can be NULL
 * @q_vector: pointer to q_vector, can be NULL
 */
static inline void ice_irq_dynamic_ena(struct ice_hw *hw, struct ice_vsi *vsi,
static inline void
ice_irq_dynamic_ena(struct ice_hw *hw, struct ice_vsi *vsi,
		    struct ice_q_vector *q_vector)
{
	u32 vector = (vsi && q_vector) ? vsi->hw_base_vector + q_vector->v_idx :
+20 −17
Original line number Diff line number Diff line
@@ -331,7 +331,7 @@ ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,
	/* flag cleared so calling functions don't call AQ again */
	pi->phy.get_link_info = false;

	return status;
	return 0;
}

/**
@@ -1100,8 +1100,9 @@ const struct ice_ctx_ele ice_tlan_ctx_info[] = {
 *
 * Dumps debug log about control command with descriptor contents.
 */
void ice_debug_cq(struct ice_hw *hw, u32 __maybe_unused mask, void *desc,
		  void *buf, u16 buf_len)
void
ice_debug_cq(struct ice_hw *hw, u32 __maybe_unused mask, void *desc, void *buf,
	     u16 buf_len)
{
	struct ice_aq_desc *cq_desc = (struct ice_aq_desc *)desc;
	u16 len;
@@ -1620,8 +1621,8 @@ ice_aq_discover_caps(struct ice_hw *hw, void *buf, u16 buf_size, u32 *cap_count,
 * @hw: pointer to the hardware structure
 * @opc: capabilities type to discover - pass in the command opcode
 */
static enum ice_status ice_discover_caps(struct ice_hw *hw,
					 enum ice_adminq_opc opc)
static enum ice_status
ice_discover_caps(struct ice_hw *hw, enum ice_adminq_opc opc)
{
	enum ice_status status;
	u32 cap_count;
@@ -2548,8 +2549,8 @@ do_aq:
 * @dest_ctx: the context to be written to
 * @ce_info:  a description of the struct to be filled
 */
static void ice_write_byte(u8 *src_ctx, u8 *dest_ctx,
			   const struct ice_ctx_ele *ce_info)
static void
ice_write_byte(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
{
	u8 src_byte, dest_byte, mask;
	u8 *from, *dest;
@@ -2587,8 +2588,8 @@ static void ice_write_byte(u8 *src_ctx, u8 *dest_ctx,
 * @dest_ctx: the context to be written to
 * @ce_info:  a description of the struct to be filled
 */
static void ice_write_word(u8 *src_ctx, u8 *dest_ctx,
			   const struct ice_ctx_ele *ce_info)
static void
ice_write_word(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
{
	u16 src_word, mask;
	__le16 dest_word;
@@ -2630,8 +2631,8 @@ static void ice_write_word(u8 *src_ctx, u8 *dest_ctx,
 * @dest_ctx: the context to be written to
 * @ce_info:  a description of the struct to be filled
 */
static void ice_write_dword(u8 *src_ctx, u8 *dest_ctx,
			    const struct ice_ctx_ele *ce_info)
static void
ice_write_dword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
{
	u32 src_dword, mask;
	__le32 dest_dword;
@@ -2681,8 +2682,8 @@ static void ice_write_dword(u8 *src_ctx, u8 *dest_ctx,
 * @dest_ctx: the context to be written to
 * @ce_info:  a description of the struct to be filled
 */
static void ice_write_qword(u8 *src_ctx, u8 *dest_ctx,
			    const struct ice_ctx_ele *ce_info)
static void
ice_write_qword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
{
	u64 src_qword, mask;
	__le64 dest_qword;
@@ -3026,7 +3027,8 @@ void ice_replay_post(struct ice_hw *hw)
 * @prev_stat: ptr to previous loaded stat value
 * @cur_stat: ptr to current stat value
 */
void ice_stat_update40(struct ice_hw *hw, u32 hireg, u32 loreg,
void
ice_stat_update40(struct ice_hw *hw, u32 hireg, u32 loreg,
		  bool prev_stat_loaded, u64 *prev_stat, u64 *cur_stat)
{
	u64 new_data;
@@ -3057,7 +3059,8 @@ void ice_stat_update40(struct ice_hw *hw, u32 hireg, u32 loreg,
 * @prev_stat: ptr to previous loaded stat value
 * @cur_stat: ptr to current stat value
 */
void ice_stat_update32(struct ice_hw *hw, u32 reg, bool prev_stat_loaded,
void
ice_stat_update32(struct ice_hw *hw, u32 reg, bool prev_stat_loaded,
		  u64 *prev_stat, u64 *cur_stat)
{
	u32 new_data;
+10 −8
Original line number Diff line number Diff line
@@ -9,8 +9,8 @@
#include "ice_switch.h"
#include <linux/avf/virtchnl.h>

void ice_debug_cq(struct ice_hw *hw, u32 mask, void *desc, void *buf,
		  u16 buf_len);
void
ice_debug_cq(struct ice_hw *hw, u32 mask, void *desc, void *buf, u16 buf_len);
enum ice_status ice_init_hw(struct ice_hw *hw);
void ice_deinit_hw(struct ice_hw *hw);
enum ice_status ice_check_reset(struct ice_hw *hw);
@@ -28,8 +28,8 @@ ice_acquire_res(struct ice_hw *hw, enum ice_aq_res_ids res,
		enum ice_aq_res_access_type access, u32 timeout);
void ice_release_res(struct ice_hw *hw, enum ice_aq_res_ids res);
enum ice_status ice_init_nvm(struct ice_hw *hw);
enum ice_status ice_read_sr_buf(struct ice_hw *hw, u16 offset, u16 *words,
				u16 *data);
enum ice_status
ice_read_sr_buf(struct ice_hw *hw, u16 offset, u16 *words, u16 *data);
enum ice_status
ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq,
		struct ice_aq_desc *desc, void *buf, u16 buf_size,
@@ -106,8 +106,10 @@ ice_ena_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u8 num_qgrps,
enum ice_status ice_replay_vsi(struct ice_hw *hw, u16 vsi_handle);
void ice_replay_post(struct ice_hw *hw);
void ice_output_fw_log(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf);
void ice_stat_update40(struct ice_hw *hw, u32 hireg, u32 loreg,
void
ice_stat_update40(struct ice_hw *hw, u32 hireg, u32 loreg,
		  bool prev_stat_loaded, u64 *prev_stat, u64 *cur_stat);
void ice_stat_update32(struct ice_hw *hw, u32 reg, bool prev_stat_loaded,
void
ice_stat_update32(struct ice_hw *hw, u32 reg, bool prev_stat_loaded,
		  u64 *prev_stat, u64 *cur_stat);
#endif /* _ICE_COMMON_H_ */
+15 −10
Original line number Diff line number Diff line
@@ -1156,7 +1156,8 @@ ice_get_settings_link_down(struct ethtool_link_ksettings *ks,
 *
 * Reports speed/duplex settings based on media_type
 */
static int ice_get_link_ksettings(struct net_device *netdev,
static int
ice_get_link_ksettings(struct net_device *netdev,
		       struct ethtool_link_ksettings *ks)
{
	struct ice_netdev_priv *np = netdev_priv(netdev);
@@ -1565,7 +1566,8 @@ done:
 *
 * Returns Success if the command is supported.
 */
static int ice_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd,
static int
ice_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd,
	      u32 __always_unused *rule_locs)
{
	struct ice_netdev_priv *np = netdev_priv(netdev);
@@ -2023,8 +2025,9 @@ out:
 * Returns -EINVAL if the table specifies an invalid queue id, otherwise
 * returns 0 after programming the table.
 */
static int ice_set_rxfh(struct net_device *netdev, const u32 *indir,
			const u8 *key, const u8 hfunc)
static int
ice_set_rxfh(struct net_device *netdev, const u32 *indir, const u8 *key,
	     const u8 hfunc)
{
	struct ice_netdev_priv *np = netdev_priv(netdev);
	struct ice_vsi *vsi = np->vsi;
@@ -2179,7 +2182,8 @@ ice_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec)
	return __ice_get_coalesce(netdev, ec, -1);
}

static int ice_get_per_q_coalesce(struct net_device *netdev, u32 q_num,
static int
ice_get_per_q_coalesce(struct net_device *netdev, u32 q_num,
		       struct ethtool_coalesce *ec)
{
	return __ice_get_coalesce(netdev, ec, q_num);
@@ -2324,7 +2328,8 @@ ice_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec)
	return __ice_set_coalesce(netdev, ec, -1);
}

static int ice_set_per_q_coalesce(struct net_device *netdev, u32 q_num,
static int
ice_set_per_q_coalesce(struct net_device *netdev, u32 q_num,
		       struct ethtool_coalesce *ec)
{
	return __ice_set_coalesce(netdev, ec, q_num);
+79 −16
Original line number Diff line number Diff line
@@ -297,13 +297,19 @@ static void ice_vsi_set_num_desc(struct ice_vsi *vsi)
/**
 * ice_vsi_set_num_qs - Set number of queues, descriptors and vectors for a VSI
 * @vsi: the VSI being configured
 * @vf_id: Id of the VF being configured
 *
 * Return 0 on success and a negative value on error
 */
static void ice_vsi_set_num_qs(struct ice_vsi *vsi)
static void ice_vsi_set_num_qs(struct ice_vsi *vsi, u16 vf_id)
{
	struct ice_pf *pf = vsi->back;

	struct ice_vf *vf = NULL;

	if (vsi->type == ICE_VSI_VF)
		vsi->vf_id = vf_id;

	switch (vsi->type) {
	case ICE_VSI_PF:
		vsi->alloc_txq = pf->num_lan_tx;
@@ -311,8 +317,9 @@ static void ice_vsi_set_num_qs(struct ice_vsi *vsi)
		vsi->num_q_vectors = max_t(int, pf->num_lan_rx, pf->num_lan_tx);
		break;
	case ICE_VSI_VF:
		vsi->alloc_txq = pf->num_vf_qps;
		vsi->alloc_rxq = pf->num_vf_qps;
		vf = &pf->vf[vsi->vf_id];
		vsi->alloc_txq = vf->num_vf_qs;
		vsi->alloc_rxq = vf->num_vf_qs;
		/* pf->num_vf_msix includes (VF miscellaneous vector +
		 * data queue interrupts). Since vsi->num_q_vectors is number
		 * of queues vectors, subtract 1 from the original vector
@@ -472,10 +479,12 @@ static irqreturn_t ice_msix_clean_rings(int __always_unused irq, void *data)
 * ice_vsi_alloc - Allocates the next available struct VSI in the PF
 * @pf: board private structure
 * @type: type of VSI
 * @vf_id: Id of the VF being configured
 *
 * returns a pointer to a VSI on success, NULL on failure.
 */
static struct ice_vsi *ice_vsi_alloc(struct ice_pf *pf, enum ice_vsi_type type)
static struct ice_vsi *
ice_vsi_alloc(struct ice_pf *pf, enum ice_vsi_type type, u16 vf_id)
{
	struct ice_vsi *vsi = NULL;

@@ -501,7 +510,10 @@ static struct ice_vsi *ice_vsi_alloc(struct ice_pf *pf, enum ice_vsi_type type)
	vsi->idx = pf->next_vsi;
	vsi->work_lmt = ICE_DFLT_IRQ_WORK;

	ice_vsi_set_num_qs(vsi);
	if (type == ICE_VSI_VF)
		ice_vsi_set_num_qs(vsi, vf_id);
	else
		ice_vsi_set_num_qs(vsi, ICE_INVAL_VFID);

	switch (vsi->type) {
	case ICE_VSI_PF:
@@ -869,7 +881,18 @@ static void ice_vsi_setup_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt)
		tx_count += tx_numq_tc;
		ctxt->info.tc_mapping[i] = cpu_to_le16(qmap);
	}

	/* if offset is non-zero, means it is calculated correctly based on
	 * enabled TCs for a given VSI otherwise qcount_rx will always
	 * be correct and non-zero because it is based off - VSI's
	 * allocated Rx queues which is at least 1 (hence qcount_tx will be
	 * at least 1)
	 */
	if (offset)
		vsi->num_rxq = offset;
	else
		vsi->num_rxq = qcount_rx;

	vsi->num_txq = tx_count;

	if (vsi->type == ICE_VSI_VF && vsi->num_txq != vsi->num_rxq) {
@@ -940,6 +963,7 @@ static int ice_vsi_init(struct ice_vsi *vsi)
	if (!ctxt)
		return -ENOMEM;

	ctxt->info = vsi->info;
	switch (vsi->type) {
	case ICE_VSI_PF:
		ctxt->flags = ICE_AQ_VSI_TYPE_PF;
@@ -965,6 +989,14 @@ static int ice_vsi_init(struct ice_vsi *vsi)
	ctxt->info.sw_id = vsi->port_info->sw_id;
	ice_vsi_setup_q_map(vsi, ctxt);

	/* Enable MAC Antispoof with new VSI being initialized or updated */
	if (vsi->type == ICE_VSI_VF && pf->vf[vsi->vf_id].spoofchk) {
		ctxt->info.valid_sections |=
			cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID);
		ctxt->info.sec_flags |=
			ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF;
	}

	ret = ice_add_vsi(hw, vsi->idx, ctxt, NULL);
	if (ret) {
		dev_err(&pf->pdev->dev,
@@ -2075,8 +2107,9 @@ err_alloc_q_ids:
 * @rst_src: reset source
 * @rel_vmvf_num: Relative id of VF/VM
 */
int ice_vsi_stop_lan_tx_rings(struct ice_vsi *vsi,
			      enum ice_disq_rst_src rst_src, u16 rel_vmvf_num)
int
ice_vsi_stop_lan_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,
			  u16 rel_vmvf_num)
{
	return ice_vsi_stop_tx_rings(vsi, rst_src, rel_vmvf_num, vsi->tx_rings,
				     0);
@@ -2086,10 +2119,11 @@ int ice_vsi_stop_lan_tx_rings(struct ice_vsi *vsi,
 * ice_cfg_vlan_pruning - enable or disable VLAN pruning on the VSI
 * @vsi: VSI to enable or disable VLAN pruning on
 * @ena: set to true to enable VLAN pruning and false to disable it
 * @vlan_promisc: enable valid security flags if not in VLAN promiscuous mode
 *
 * returns 0 if VSI is updated, negative otherwise
 */
int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena)
int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena, bool vlan_promisc)
{
	struct ice_vsi_ctx *ctxt;
	struct device *dev;
@@ -2117,7 +2151,9 @@ int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena)
		ctxt->info.sw_flags2 &= ~ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA;
	}

	ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID |
	if (!vlan_promisc)
		ctxt->info.valid_sections =
			cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID |
				    ICE_AQ_VSI_PROP_SW_VALID);

	status = ice_update_vsi(&vsi->back->hw, vsi->idx, ctxt, NULL);
@@ -2162,7 +2198,11 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,
	struct ice_vsi *vsi;
	int ret, i;

	vsi = ice_vsi_alloc(pf, type);
	if (type == ICE_VSI_VF)
		vsi = ice_vsi_alloc(pf, type, vf_id);
	else
		vsi = ice_vsi_alloc(pf, type, ICE_INVAL_VFID);

	if (!vsi) {
		dev_err(dev, "could not allocate VSI\n");
		return NULL;
@@ -2646,6 +2686,7 @@ int ice_vsi_release(struct ice_vsi *vsi)
int ice_vsi_rebuild(struct ice_vsi *vsi)
{
	u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 };
	struct ice_vf *vf = NULL;
	struct ice_pf *pf;
	int ret, i;

@@ -2653,16 +2694,38 @@ int ice_vsi_rebuild(struct ice_vsi *vsi)
		return -EINVAL;

	pf = vsi->back;
	if (vsi->type == ICE_VSI_VF)
		vf = &pf->vf[vsi->vf_id];

	ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx);
	ice_vsi_free_q_vectors(vsi);
	ice_free_res(vsi->back->sw_irq_tracker, vsi->sw_base_vector, vsi->idx);
	ice_free_res(vsi->back->hw_irq_tracker, vsi->hw_base_vector, vsi->idx);

	if (vsi->type != ICE_VSI_VF) {
		/* reclaim SW interrupts back to the common pool */
		ice_free_res(pf->sw_irq_tracker, vsi->sw_base_vector, vsi->idx);
		pf->num_avail_sw_msix += vsi->num_q_vectors;
		vsi->sw_base_vector = 0;
		/* reclaim HW interrupts back to the common pool */
		ice_free_res(pf->hw_irq_tracker, vsi->hw_base_vector,
			     vsi->idx);
		pf->num_avail_hw_msix += vsi->num_q_vectors;
	} else {
		/* Reclaim VF resources back to the common pool for reset and
		 * and rebuild, with vector reassignment
		 */
		ice_free_res(pf->hw_irq_tracker, vf->first_vector_idx,
			     vsi->idx);
		pf->num_avail_hw_msix += pf->num_vf_msix;
	}
	vsi->hw_base_vector = 0;

	ice_vsi_clear_rings(vsi);
	ice_vsi_free_arrays(vsi, false);
	ice_dev_onetime_setup(&vsi->back->hw);
	ice_vsi_set_num_qs(vsi);
	if (vsi->type == ICE_VSI_VF)
		ice_vsi_set_num_qs(vsi, vf->vf_id);
	else
		ice_vsi_set_num_qs(vsi, ICE_INVAL_VFID);
	ice_vsi_set_tc_cfg(vsi);

	/* Initialize VSI struct elements and create VSI in FW */
Loading