diff options
| author | Bruce Allan <bruce.w.allan@intel.com> | 2018-12-19 13:03:26 -0500 |
|---|---|---|
| committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2019-01-15 13:32:59 -0500 |
| commit | ab4ab73fc1ec6dec548fa36c5e383ef5faa7b4c1 (patch) | |
| tree | 8dcbc39d30188abbf54dfc20b8f8f52358c2316f /drivers/net/ethernet/intel | |
| parent | b6f934f027bbdb53b7e2653b23758e222f3dd65a (diff) | |
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>
Diffstat (limited to 'drivers/net/ethernet/intel')
| -rw-r--r-- | drivers/net/ethernet/intel/ice/ice.h | 1 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/ice/ice_ethtool.c | 86 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/ice/ice_main.c | 14 |
3 files changed, 95 insertions, 6 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index a385575600f6..8af882a2b070 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h | |||
| @@ -270,6 +270,7 @@ enum ice_pf_flags { | |||
| 270 | ICE_FLAG_RSS_ENA, | 270 | ICE_FLAG_RSS_ENA, |
| 271 | ICE_FLAG_SRIOV_ENA, | 271 | ICE_FLAG_SRIOV_ENA, |
| 272 | ICE_FLAG_SRIOV_CAPABLE, | 272 | ICE_FLAG_SRIOV_CAPABLE, |
| 273 | ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, | ||
| 273 | ICE_PF_FLAGS_NBITS /* must be last */ | 274 | ICE_PF_FLAGS_NBITS /* must be last */ |
| 274 | }; | 275 | }; |
| 275 | 276 | ||
diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index 2a0bcd460d23..24c8aeaea2d5 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c | |||
| @@ -114,6 +114,22 @@ static const u32 ice_regs_dump_list[] = { | |||
| 114 | QRX_ITR(0), | 114 | QRX_ITR(0), |
| 115 | }; | 115 | }; |
| 116 | 116 | ||
| 117 | struct ice_priv_flag { | ||
| 118 | char name[ETH_GSTRING_LEN]; | ||
| 119 | u32 bitno; /* bit position in pf->flags */ | ||
| 120 | }; | ||
| 121 | |||
| 122 | #define ICE_PRIV_FLAG(_name, _bitno) { \ | ||
| 123 | .name = _name, \ | ||
| 124 | .bitno = _bitno, \ | ||
| 125 | } | ||
| 126 | |||
| 127 | static const struct ice_priv_flag ice_gstrings_priv_flags[] = { | ||
| 128 | ICE_PRIV_FLAG("link-down-on-close", ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA), | ||
| 129 | }; | ||
| 130 | |||
| 131 | #define ICE_PRIV_FLAG_ARRAY_SIZE ARRAY_SIZE(ice_gstrings_priv_flags) | ||
| 132 | |||
| 117 | /** | 133 | /** |
| 118 | * ice_nvm_version_str - format the NVM version strings | 134 | * ice_nvm_version_str - format the NVM version strings |
| 119 | * @hw: ptr to the hardware info | 135 | * @hw: ptr to the hardware info |
| @@ -152,6 +168,7 @@ ice_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) | |||
| 152 | sizeof(drvinfo->fw_version)); | 168 | sizeof(drvinfo->fw_version)); |
| 153 | strlcpy(drvinfo->bus_info, pci_name(pf->pdev), | 169 | strlcpy(drvinfo->bus_info, pci_name(pf->pdev), |
| 154 | sizeof(drvinfo->bus_info)); | 170 | sizeof(drvinfo->bus_info)); |
| 171 | drvinfo->n_priv_flags = ICE_PRIV_FLAG_ARRAY_SIZE; | ||
| 155 | } | 172 | } |
| 156 | 173 | ||
| 157 | static int ice_get_regs_len(struct net_device __always_unused *netdev) | 174 | static int ice_get_regs_len(struct net_device __always_unused *netdev) |
| @@ -293,6 +310,13 @@ static void ice_get_strings(struct net_device *netdev, u32 stringset, u8 *data) | |||
| 293 | } | 310 | } |
| 294 | 311 | ||
| 295 | break; | 312 | break; |
| 313 | case ETH_SS_PRIV_FLAGS: | ||
| 314 | for (i = 0; i < ICE_PRIV_FLAG_ARRAY_SIZE; i++) { | ||
| 315 | snprintf(p, ETH_GSTRING_LEN, "%s", | ||
| 316 | ice_gstrings_priv_flags[i].name); | ||
| 317 | p += ETH_GSTRING_LEN; | ||
| 318 | } | ||
| 319 | break; | ||
| 296 | default: | 320 | default: |
| 297 | break; | 321 | break; |
| 298 | } | 322 | } |
| @@ -321,6 +345,64 @@ ice_set_phys_id(struct net_device *netdev, enum ethtool_phys_id_state state) | |||
| 321 | return 0; | 345 | return 0; |
| 322 | } | 346 | } |
| 323 | 347 | ||
| 348 | /** | ||
| 349 | * ice_get_priv_flags - report device private flags | ||
| 350 | * @netdev: network interface device structure | ||
| 351 | * | ||
| 352 | * The get string set count and the string set should be matched for each | ||
| 353 | * flag returned. Add new strings for each flag to the ice_gstrings_priv_flags | ||
| 354 | * array. | ||
| 355 | * | ||
| 356 | * Returns a u32 bitmap of flags. | ||
| 357 | */ | ||
| 358 | static u32 ice_get_priv_flags(struct net_device *netdev) | ||
| 359 | { | ||
| 360 | struct ice_netdev_priv *np = netdev_priv(netdev); | ||
| 361 | struct ice_vsi *vsi = np->vsi; | ||
| 362 | struct ice_pf *pf = vsi->back; | ||
| 363 | u32 i, ret_flags = 0; | ||
| 364 | |||
| 365 | for (i = 0; i < ICE_PRIV_FLAG_ARRAY_SIZE; i++) { | ||
| 366 | const struct ice_priv_flag *priv_flag; | ||
| 367 | |||
| 368 | priv_flag = &ice_gstrings_priv_flags[i]; | ||
| 369 | |||
| 370 | if (test_bit(priv_flag->bitno, pf->flags)) | ||
| 371 | ret_flags |= BIT(i); | ||
| 372 | } | ||
| 373 | |||
| 374 | return ret_flags; | ||
| 375 | } | ||
| 376 | |||
| 377 | /** | ||
| 378 | * ice_set_priv_flags - set private flags | ||
| 379 | * @netdev: network interface device structure | ||
| 380 | * @flags: bit flags to be set | ||
| 381 | */ | ||
| 382 | static int ice_set_priv_flags(struct net_device *netdev, u32 flags) | ||
| 383 | { | ||
| 384 | struct ice_netdev_priv *np = netdev_priv(netdev); | ||
| 385 | struct ice_vsi *vsi = np->vsi; | ||
| 386 | struct ice_pf *pf = vsi->back; | ||
| 387 | u32 i; | ||
| 388 | |||
| 389 | if (flags > BIT(ICE_PRIV_FLAG_ARRAY_SIZE)) | ||
| 390 | return -EINVAL; | ||
| 391 | |||
| 392 | for (i = 0; i < ICE_PRIV_FLAG_ARRAY_SIZE; i++) { | ||
| 393 | const struct ice_priv_flag *priv_flag; | ||
| 394 | |||
| 395 | priv_flag = &ice_gstrings_priv_flags[i]; | ||
| 396 | |||
| 397 | if (flags & BIT(i)) | ||
| 398 | set_bit(priv_flag->bitno, pf->flags); | ||
| 399 | else | ||
| 400 | clear_bit(priv_flag->bitno, pf->flags); | ||
| 401 | } | ||
| 402 | |||
| 403 | return 0; | ||
| 404 | } | ||
| 405 | |||
| 324 | static int ice_get_sset_count(struct net_device *netdev, int sset) | 406 | static int ice_get_sset_count(struct net_device *netdev, int sset) |
| 325 | { | 407 | { |
| 326 | switch (sset) { | 408 | switch (sset) { |
| @@ -344,6 +426,8 @@ static int ice_get_sset_count(struct net_device *netdev, int sset) | |||
| 344 | * not safe. | 426 | * not safe. |
| 345 | */ | 427 | */ |
| 346 | return ICE_ALL_STATS_LEN(netdev); | 428 | return ICE_ALL_STATS_LEN(netdev); |
| 429 | case ETH_SS_PRIV_FLAGS: | ||
| 430 | return ICE_PRIV_FLAG_ARRAY_SIZE; | ||
| 347 | default: | 431 | default: |
| 348 | return -EOPNOTSUPP; | 432 | return -EOPNOTSUPP; |
| 349 | } | 433 | } |
| @@ -1753,6 +1837,8 @@ static const struct ethtool_ops ice_ethtool_ops = { | |||
| 1753 | .get_strings = ice_get_strings, | 1837 | .get_strings = ice_get_strings, |
| 1754 | .set_phys_id = ice_set_phys_id, | 1838 | .set_phys_id = ice_set_phys_id, |
| 1755 | .get_ethtool_stats = ice_get_ethtool_stats, | 1839 | .get_ethtool_stats = ice_get_ethtool_stats, |
| 1840 | .get_priv_flags = ice_get_priv_flags, | ||
| 1841 | .set_priv_flags = ice_set_priv_flags, | ||
| 1756 | .get_sset_count = ice_get_sset_count, | 1842 | .get_sset_count = ice_get_sset_count, |
| 1757 | .get_rxnfc = ice_get_rxnfc, | 1843 | .get_rxnfc = ice_get_rxnfc, |
| 1758 | .get_ringparam = ice_get_ringparam, | 1844 | .get_ringparam = ice_get_ringparam, |
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index b27bc7d6d605..e36db981f047 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c | |||
| @@ -3029,7 +3029,7 @@ out: | |||
| 3029 | */ | 3029 | */ |
| 3030 | int ice_down(struct ice_vsi *vsi) | 3030 | int ice_down(struct ice_vsi *vsi) |
| 3031 | { | 3031 | { |
| 3032 | int i, tx_err, rx_err, link_err; | 3032 | int i, tx_err, rx_err, link_err = 0; |
| 3033 | 3033 | ||
| 3034 | /* Caller of this function is expected to set the | 3034 | /* Caller of this function is expected to set the |
| 3035 | * vsi->state __ICE_DOWN bit | 3035 | * vsi->state __ICE_DOWN bit |
| @@ -3054,11 +3054,13 @@ int ice_down(struct ice_vsi *vsi) | |||
| 3054 | 3054 | ||
| 3055 | ice_napi_disable_all(vsi); | 3055 | ice_napi_disable_all(vsi); |
| 3056 | 3056 | ||
| 3057 | link_err = ice_force_phys_link_state(vsi, false); | 3057 | if (test_bit(ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, vsi->back->flags)) { |
| 3058 | if (link_err) | 3058 | link_err = ice_force_phys_link_state(vsi, false); |
| 3059 | netdev_err(vsi->netdev, | 3059 | if (link_err) |
| 3060 | "Failed to set physical link down, VSI %d error %d\n", | 3060 | netdev_err(vsi->netdev, |
| 3061 | vsi->vsi_num, link_err); | 3061 | "Failed to set physical link down, VSI %d error %d\n", |
| 3062 | vsi->vsi_num, link_err); | ||
| 3063 | } | ||
| 3062 | 3064 | ||
| 3063 | ice_for_each_txq(vsi, i) | 3065 | ice_for_each_txq(vsi, i) |
| 3064 | ice_clean_tx_ring(vsi->tx_rings[i]); | 3066 | ice_clean_tx_ring(vsi->tx_rings[i]); |
