190-4-5-e1000e-Separate-signaling-for-link-check-link-up.patch 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. From patchwork Fri Jul 21 18:36:26 2017
  2. Content-Type: text/plain; charset="utf-8"
  3. MIME-Version: 1.0
  4. Content-Transfer-Encoding: 7bit
  5. Subject: [4/5] e1000e: Separate signaling for link check/link up
  6. From: Benjamin Poirier <[email protected]>
  7. X-Patchwork-Id: 9857491
  8. Message-Id: <[email protected]>
  9. To: Jeff Kirsher <[email protected]>
  10. Cc: Lennart Sorensen <[email protected]>,
  11. [email protected], [email protected],
  12. [email protected]
  13. Date: Fri, 21 Jul 2017 11:36:26 -0700
  14. Lennart reported the following race condition:
  15. \ e1000_watchdog_task
  16. \ e1000e_has_link
  17. \ hw->mac.ops.check_for_link() === e1000e_check_for_copper_link
  18. /* link is up */
  19. mac->get_link_status = false;
  20. /* interrupt */
  21. \ e1000_msix_other
  22. hw->mac.get_link_status = true;
  23. link_active = !hw->mac.get_link_status
  24. /* link_active is false, wrongly */
  25. This problem arises because the single flag get_link_status is used to
  26. signal two different states: link status needs checking and link status is
  27. down.
  28. Avoid the problem by using the return value of .check_for_link to signal
  29. the link status to e1000e_has_link().
  30. Reported-by: Lennart Sorensen <[email protected]>
  31. Signed-off-by: Benjamin Poirier <[email protected]>
  32. ---
  33. drivers/net/ethernet/intel/e1000e/mac.c | 11 ++++++++---
  34. drivers/net/ethernet/intel/e1000e/netdev.c | 2 +-
  35. 2 files changed, 9 insertions(+), 4 deletions(-)
  36. --- a/drivers/net/ethernet/intel/e1000e/mac.c
  37. +++ b/drivers/net/ethernet/intel/e1000e/mac.c
  38. @@ -410,6 +410,9 @@ void e1000e_clear_hw_cntrs_base(struct e
  39. * Checks to see of the link status of the hardware has changed. If a
  40. * change in link status has been detected, then we read the PHY registers
  41. * to get the current speed/duplex if link exists.
  42. + *
  43. + * Returns a negative error code (-E1000_ERR_*) or 0 (link down) or 1 (link
  44. + * up).
  45. **/
  46. s32 e1000e_check_for_copper_link(struct e1000_hw *hw)
  47. {
  48. @@ -423,7 +426,7 @@ s32 e1000e_check_for_copper_link(struct
  49. * Change or Rx Sequence Error interrupt.
  50. */
  51. if (!mac->get_link_status)
  52. - return 0;
  53. + return 1;
  54. /* First we want to see if the MII Status Register reports
  55. * link. If so, then we want to get the current speed/duplex
  56. @@ -461,10 +464,12 @@ s32 e1000e_check_for_copper_link(struct
  57. * different link partner.
  58. */
  59. ret_val = e1000e_config_fc_after_link_up(hw);
  60. - if (ret_val)
  61. + if (ret_val) {
  62. e_dbg("Error configuring flow control\n");
  63. + return ret_val;
  64. + }
  65. - return ret_val;
  66. + return 1;
  67. }
  68. /**
  69. --- a/drivers/net/ethernet/intel/e1000e/netdev.c
  70. +++ b/drivers/net/ethernet/intel/e1000e/netdev.c
  71. @@ -5056,7 +5056,7 @@ static bool e1000e_has_link(struct e1000
  72. case e1000_media_type_copper:
  73. if (hw->mac.get_link_status) {
  74. ret_val = hw->mac.ops.check_for_link(hw);
  75. - link_active = !hw->mac.get_link_status;
  76. + link_active = ret_val > 0;
  77. } else {
  78. link_active = true;
  79. }