aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet
diff options
context:
space:
mode:
authorAlan Brady <alan.brady@intel.com>2017-12-29 08:50:34 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2018-02-12 13:51:54 -0500
commitfe09ed0ee1f57a818e4d7e41b25f16744487e678 (patch)
tree263805381135c6fb87e6c4ea9082146db1fd294a /drivers/net/ethernet
parent17b4d25c12abc9c9e9e111ad00968997b246b1c9 (diff)
i40e: use changed_flags to check I40E_FLAG_DISABLE_FW_LLDP
Currently in i40e_set_priv_flags we use new_flags to check for the I40E_FLAG_DISABLE_FW_LLDP flag. This is an issue for a few a reasons. DISABLE_FW_LLDP is persistent across reboots/driver reloads. This means we need some way to detect if FW LLDP is enabled on init. We do this by trying to init_dcb and if it fails with EPERM we know LLDP is disabled in FW. This could be a problem on older FW versions or NPAR enabled PFs because there are situations where the FW could disable LLDP, but they do _not_ support using this flag to change it. If we do end up in this situation, the flag will be set, then when the user tries to change any priv flags, the driver thinks the user is trying to disable FW LLDP on a FW that doesn't support it and essentially forbids any priv flag changes. The fix is simple, instead of checking if this flag is set, we should be checking if the user is trying to _change_ the flag on unsupported FW versions. This patch also adds a comment explaining that the cmpxchg is the point of no return. Once we put the new flags into pf->flags we can't back out. Signed-off-by: Alan Brady <alan.brady@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')
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_ethtool.c22
1 files changed, 15 insertions, 7 deletions
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
index 5ca63c5d36b4..5ee27358922a 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
@@ -4406,6 +4406,8 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags)
4406 } 4406 }
4407 4407
4408flags_complete: 4408flags_complete:
4409 changed_flags = orig_flags ^ new_flags;
4410
4409 /* Before we finalize any flag changes, we need to perform some 4411 /* Before we finalize any flag changes, we need to perform some
4410 * checks to ensure that the changes are supported and safe. 4412 * checks to ensure that the changes are supported and safe.
4411 */ 4413 */
@@ -4415,13 +4417,17 @@ flags_complete:
4415 !(pf->hw_features & I40E_HW_ATR_EVICT_CAPABLE)) 4417 !(pf->hw_features & I40E_HW_ATR_EVICT_CAPABLE))
4416 return -EOPNOTSUPP; 4418 return -EOPNOTSUPP;
4417 4419
4418 /* Disable FW LLDP not supported if NPAR active or if FW 4420 /* If the driver detected FW LLDP was disabled on init, this flag could
4419 * API version < 1.7 4421 * be set, however we do not support _changing_ the flag if NPAR is
4422 * enabled or FW API version < 1.7. There are situations where older
4423 * FW versions/NPAR enabled PFs could disable LLDP, however we _must_
4424 * not allow the user to enable/disable LLDP with this flag on
4425 * unsupported FW versions.
4420 */ 4426 */
4421 if (new_flags & I40E_FLAG_DISABLE_FW_LLDP) { 4427 if (changed_flags & I40E_FLAG_DISABLE_FW_LLDP) {
4422 if (pf->hw.func_caps.npar_enable) { 4428 if (pf->hw.func_caps.npar_enable) {
4423 dev_warn(&pf->pdev->dev, 4429 dev_warn(&pf->pdev->dev,
4424 "Unable to stop FW LLDP if NPAR active\n"); 4430 "Unable to change FW LLDP if NPAR active\n");
4425 return -EOPNOTSUPP; 4431 return -EOPNOTSUPP;
4426 } 4432 }
4427 4433
@@ -4429,7 +4435,7 @@ flags_complete:
4429 (pf->hw.aq.api_maj_ver == 1 && 4435 (pf->hw.aq.api_maj_ver == 1 &&
4430 pf->hw.aq.api_min_ver < 7)) { 4436 pf->hw.aq.api_min_ver < 7)) {
4431 dev_warn(&pf->pdev->dev, 4437 dev_warn(&pf->pdev->dev,
4432 "FW ver does not support stopping FW LLDP\n"); 4438 "FW ver does not support changing FW LLDP\n");
4433 return -EOPNOTSUPP; 4439 return -EOPNOTSUPP;
4434 } 4440 }
4435 } 4441 }
@@ -4439,6 +4445,10 @@ flags_complete:
4439 * something else has modified the flags variable since we copied it 4445 * something else has modified the flags variable since we copied it
4440 * originally. We'll just punt with an error and log something in the 4446 * originally. We'll just punt with an error and log something in the
4441 * message buffer. 4447 * message buffer.
4448 *
4449 * This is the point of no return for this function. We need to have
4450 * checked any discrepancies or misconfigurations and returned
4451 * EOPNOTSUPP before updating pf->flags here.
4442 */ 4452 */
4443 if (cmpxchg64(&pf->flags, orig_flags, new_flags) != orig_flags) { 4453 if (cmpxchg64(&pf->flags, orig_flags, new_flags) != orig_flags) {
4444 dev_warn(&pf->pdev->dev, 4454 dev_warn(&pf->pdev->dev,
@@ -4446,8 +4456,6 @@ flags_complete:
4446 return -EAGAIN; 4456 return -EAGAIN;
4447 } 4457 }
4448 4458
4449 changed_flags = orig_flags ^ new_flags;
4450
4451 /* Process any additional changes needed as a result of flag changes. 4459 /* Process any additional changes needed as a result of flag changes.
4452 * The changed_flags value reflects the list of bits that were 4460 * The changed_flags value reflects the list of bits that were
4453 * changed in the code above. 4461 * changed in the code above.