Skip to content

Commit

Permalink
ice: Add ethtool private flag to make forcing link down optional
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Bruce Allan authored and Jeff Kirsher committed Jan 15, 2019
1 parent b6f934f commit ab4ab73
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 6 deletions.
1 change: 1 addition & 0 deletions drivers/net/ethernet/intel/ice/ice.h
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ enum ice_pf_flags {
ICE_FLAG_RSS_ENA,
ICE_FLAG_SRIOV_ENA,
ICE_FLAG_SRIOV_CAPABLE,
ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA,
ICE_PF_FLAGS_NBITS /* must be last */
};

Expand Down
86 changes: 86 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,22 @@ static const u32 ice_regs_dump_list[] = {
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
* @hw: ptr to the hardware info
Expand Down Expand Up @@ -152,6 +168,7 @@ ice_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
sizeof(drvinfo->fw_version));
strlcpy(drvinfo->bus_info, pci_name(pf->pdev),
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)
Expand Down Expand Up @@ -292,6 +309,13 @@ static void ice_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
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;
default:
break;
Expand Down Expand Up @@ -321,6 +345,64 @@ ice_set_phys_id(struct net_device *netdev, enum ethtool_phys_id_state state)
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)
{
switch (sset) {
Expand All @@ -344,6 +426,8 @@ static int ice_get_sset_count(struct net_device *netdev, int sset)
* not safe.
*/
return ICE_ALL_STATS_LEN(netdev);
case ETH_SS_PRIV_FLAGS:
return ICE_PRIV_FLAG_ARRAY_SIZE;
default:
return -EOPNOTSUPP;
}
Expand Down Expand Up @@ -1753,6 +1837,8 @@ static const struct ethtool_ops ice_ethtool_ops = {
.get_strings = ice_get_strings,
.set_phys_id = ice_set_phys_id,
.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_rxnfc = ice_get_rxnfc,
.get_ringparam = ice_get_ringparam,
Expand Down
14 changes: 8 additions & 6 deletions drivers/net/ethernet/intel/ice/ice_main.c
Original file line number Diff line number Diff line change
Expand 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 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
* vsi->state __ICE_DOWN bit
Expand All @@ -3054,11 +3054,13 @@ int ice_down(struct ice_vsi *vsi)

ice_napi_disable_all(vsi);

link_err = ice_force_phys_link_state(vsi, false);
if (link_err)
netdev_err(vsi->netdev,
"Failed to set physical link down, VSI %d error %d\n",
vsi->vsi_num, link_err);
if (test_bit(ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, vsi->back->flags)) {
link_err = ice_force_phys_link_state(vsi, false);
if (link_err)
netdev_err(vsi->netdev,
"Failed to set physical link down, VSI %d error %d\n",
vsi->vsi_num, link_err);
}

ice_for_each_txq(vsi, i)
ice_clean_tx_ring(vsi->tx_rings[i]);
Expand Down

0 comments on commit ab4ab73

Please sign in to comment.