Commit ab4ab73f authored by Bruce Allan's avatar Bruce Allan Committed by Jeff Kirsher

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: default avatarBruce Allan <bruce.w.allan@intel.com>
Signed-off-by: default avatarAnirudh Venkataramanan <anirudh.venkataramanan@intel.com>
Tested-by: default avatarAndrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent b6f934f0
...@@ -270,6 +270,7 @@ enum ice_pf_flags { ...@@ -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[] = { ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 = { ...@@ -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) ...@@ -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) ...@@ -3054,11 +3054,13 @@ int ice_down(struct ice_vsi *vsi)
ice_napi_disable_all(vsi); ice_napi_disable_all(vsi);
link_err = ice_force_phys_link_state(vsi, false); if (test_bit(ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, vsi->back->flags)) {
if (link_err) link_err = ice_force_phys_link_state(vsi, false);
netdev_err(vsi->netdev, if (link_err)
"Failed to set physical link down, VSI %d error %d\n", netdev_err(vsi->netdev,
vsi->vsi_num, link_err); "Failed to set physical link down, VSI %d error %d\n",
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]);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment