forked from mirrors/linux
		
	ice: Add ethtool private flag to make forcing link down optional
Add new infrastructure for implementing ethtool private flags using the existing pf->flags bitmap to store them, and add the link-down-on-close ethtool private flag to optionally bring down the PHY link when the interface is administratively downed. Signed-off-by: Bruce Allan <bruce.w.allan@intel.com> Signed-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@intel.com> Tested-by: Andrew Bowers <andrewx.bowers@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
		
							parent
							
								
									b6f934f027
								
							
						
					
					
						commit
						ab4ab73fc1
					
				
					 3 changed files with 95 additions and 6 deletions
				
			
		| 
						 | 
					@ -270,6 +270,7 @@ enum ice_pf_flags {
 | 
				
			||||||
	ICE_FLAG_RSS_ENA,
 | 
						ICE_FLAG_RSS_ENA,
 | 
				
			||||||
	ICE_FLAG_SRIOV_ENA,
 | 
						ICE_FLAG_SRIOV_ENA,
 | 
				
			||||||
	ICE_FLAG_SRIOV_CAPABLE,
 | 
						ICE_FLAG_SRIOV_CAPABLE,
 | 
				
			||||||
 | 
						ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA,
 | 
				
			||||||
	ICE_PF_FLAGS_NBITS		/* must be last */
 | 
						ICE_PF_FLAGS_NBITS		/* must be last */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -114,6 +114,22 @@ static const u32 ice_regs_dump_list[] = {
 | 
				
			||||||
	QRX_ITR(0),
 | 
						QRX_ITR(0),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ice_priv_flag {
 | 
				
			||||||
 | 
						char name[ETH_GSTRING_LEN];
 | 
				
			||||||
 | 
						u32 bitno;			/* bit position in pf->flags */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ICE_PRIV_FLAG(_name, _bitno) { \
 | 
				
			||||||
 | 
						.name = _name, \
 | 
				
			||||||
 | 
						.bitno = _bitno, \
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct ice_priv_flag ice_gstrings_priv_flags[] = {
 | 
				
			||||||
 | 
						ICE_PRIV_FLAG("link-down-on-close", ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA),
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ICE_PRIV_FLAG_ARRAY_SIZE	ARRAY_SIZE(ice_gstrings_priv_flags)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * ice_nvm_version_str - format the NVM version strings
 | 
					 * ice_nvm_version_str - format the NVM version strings
 | 
				
			||||||
 * @hw: ptr to the hardware info
 | 
					 * @hw: ptr to the hardware info
 | 
				
			||||||
| 
						 | 
					@ -152,6 +168,7 @@ ice_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
 | 
				
			||||||
		sizeof(drvinfo->fw_version));
 | 
							sizeof(drvinfo->fw_version));
 | 
				
			||||||
	strlcpy(drvinfo->bus_info, pci_name(pf->pdev),
 | 
						strlcpy(drvinfo->bus_info, pci_name(pf->pdev),
 | 
				
			||||||
		sizeof(drvinfo->bus_info));
 | 
							sizeof(drvinfo->bus_info));
 | 
				
			||||||
 | 
						drvinfo->n_priv_flags = ICE_PRIV_FLAG_ARRAY_SIZE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int ice_get_regs_len(struct net_device __always_unused *netdev)
 | 
					static int ice_get_regs_len(struct net_device __always_unused *netdev)
 | 
				
			||||||
| 
						 | 
					@ -292,6 +309,13 @@ static void ice_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
 | 
				
			||||||
			p += ETH_GSTRING_LEN;
 | 
								p += ETH_GSTRING_LEN;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case ETH_SS_PRIV_FLAGS:
 | 
				
			||||||
 | 
							for (i = 0; i < ICE_PRIV_FLAG_ARRAY_SIZE; i++) {
 | 
				
			||||||
 | 
								snprintf(p, ETH_GSTRING_LEN, "%s",
 | 
				
			||||||
 | 
									 ice_gstrings_priv_flags[i].name);
 | 
				
			||||||
 | 
								p += ETH_GSTRING_LEN;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
| 
						 | 
					@ -321,6 +345,64 @@ ice_set_phys_id(struct net_device *netdev, enum ethtool_phys_id_state state)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * ice_get_priv_flags - report device private flags
 | 
				
			||||||
 | 
					 * @netdev: network interface device structure
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The get string set count and the string set should be matched for each
 | 
				
			||||||
 | 
					 * flag returned.  Add new strings for each flag to the ice_gstrings_priv_flags
 | 
				
			||||||
 | 
					 * array.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns a u32 bitmap of flags.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static u32 ice_get_priv_flags(struct net_device *netdev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ice_netdev_priv *np = netdev_priv(netdev);
 | 
				
			||||||
 | 
						struct ice_vsi *vsi = np->vsi;
 | 
				
			||||||
 | 
						struct ice_pf *pf = vsi->back;
 | 
				
			||||||
 | 
						u32 i, ret_flags = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < ICE_PRIV_FLAG_ARRAY_SIZE; i++) {
 | 
				
			||||||
 | 
							const struct ice_priv_flag *priv_flag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							priv_flag = &ice_gstrings_priv_flags[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (test_bit(priv_flag->bitno, pf->flags))
 | 
				
			||||||
 | 
								ret_flags |= BIT(i);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret_flags;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * ice_set_priv_flags - set private flags
 | 
				
			||||||
 | 
					 * @netdev: network interface device structure
 | 
				
			||||||
 | 
					 * @flags: bit flags to be set
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int ice_set_priv_flags(struct net_device *netdev, u32 flags)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ice_netdev_priv *np = netdev_priv(netdev);
 | 
				
			||||||
 | 
						struct ice_vsi *vsi = np->vsi;
 | 
				
			||||||
 | 
						struct ice_pf *pf = vsi->back;
 | 
				
			||||||
 | 
						u32 i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (flags > BIT(ICE_PRIV_FLAG_ARRAY_SIZE))
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < ICE_PRIV_FLAG_ARRAY_SIZE; i++) {
 | 
				
			||||||
 | 
							const struct ice_priv_flag *priv_flag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							priv_flag = &ice_gstrings_priv_flags[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (flags & BIT(i))
 | 
				
			||||||
 | 
								set_bit(priv_flag->bitno, pf->flags);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								clear_bit(priv_flag->bitno, pf->flags);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int ice_get_sset_count(struct net_device *netdev, int sset)
 | 
					static int ice_get_sset_count(struct net_device *netdev, int sset)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	switch (sset) {
 | 
						switch (sset) {
 | 
				
			||||||
| 
						 | 
					@ -344,6 +426,8 @@ static int ice_get_sset_count(struct net_device *netdev, int sset)
 | 
				
			||||||
		 * not safe.
 | 
							 * not safe.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		return ICE_ALL_STATS_LEN(netdev);
 | 
							return ICE_ALL_STATS_LEN(netdev);
 | 
				
			||||||
 | 
						case ETH_SS_PRIV_FLAGS:
 | 
				
			||||||
 | 
							return ICE_PRIV_FLAG_ARRAY_SIZE;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return -EOPNOTSUPP;
 | 
							return -EOPNOTSUPP;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -1753,6 +1837,8 @@ static const struct ethtool_ops ice_ethtool_ops = {
 | 
				
			||||||
	.get_strings		= ice_get_strings,
 | 
						.get_strings		= ice_get_strings,
 | 
				
			||||||
	.set_phys_id		= ice_set_phys_id,
 | 
						.set_phys_id		= ice_set_phys_id,
 | 
				
			||||||
	.get_ethtool_stats      = ice_get_ethtool_stats,
 | 
						.get_ethtool_stats      = ice_get_ethtool_stats,
 | 
				
			||||||
 | 
						.get_priv_flags		= ice_get_priv_flags,
 | 
				
			||||||
 | 
						.set_priv_flags		= ice_set_priv_flags,
 | 
				
			||||||
	.get_sset_count		= ice_get_sset_count,
 | 
						.get_sset_count		= ice_get_sset_count,
 | 
				
			||||||
	.get_rxnfc		= ice_get_rxnfc,
 | 
						.get_rxnfc		= ice_get_rxnfc,
 | 
				
			||||||
	.get_ringparam		= ice_get_ringparam,
 | 
						.get_ringparam		= ice_get_ringparam,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3029,7 +3029,7 @@ static int ice_force_phys_link_state(struct ice_vsi *vsi, bool link_up)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int ice_down(struct ice_vsi *vsi)
 | 
					int ice_down(struct ice_vsi *vsi)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int i, tx_err, rx_err, link_err;
 | 
						int i, tx_err, rx_err, link_err = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Caller of this function is expected to set the
 | 
						/* Caller of this function is expected to set the
 | 
				
			||||||
	 * vsi->state __ICE_DOWN bit
 | 
						 * vsi->state __ICE_DOWN bit
 | 
				
			||||||
| 
						 | 
					@ -3054,11 +3054,13 @@ int ice_down(struct ice_vsi *vsi)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ice_napi_disable_all(vsi);
 | 
						ice_napi_disable_all(vsi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (test_bit(ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, vsi->back->flags)) {
 | 
				
			||||||
		link_err = ice_force_phys_link_state(vsi, false);
 | 
							link_err = ice_force_phys_link_state(vsi, false);
 | 
				
			||||||
		if (link_err)
 | 
							if (link_err)
 | 
				
			||||||
			netdev_err(vsi->netdev,
 | 
								netdev_err(vsi->netdev,
 | 
				
			||||||
				   "Failed to set physical link down, VSI %d error %d\n",
 | 
									   "Failed to set physical link down, VSI %d error %d\n",
 | 
				
			||||||
				   vsi->vsi_num, link_err);
 | 
									   vsi->vsi_num, link_err);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ice_for_each_txq(vsi, i)
 | 
						ice_for_each_txq(vsi, i)
 | 
				
			||||||
		ice_clean_tx_ring(vsi->tx_rings[i]);
 | 
							ice_clean_tx_ring(vsi->tx_rings[i]);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue