e1000e: Separate signaling for link check/link up
authorBenjamin Poirier <bpoirier@suse.com>
Fri, 21 Jul 2017 18:36:26 +0000 (11:36 -0700)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Tue, 10 Oct 2017 15:35:01 +0000 (08:35 -0700)
commit19110cfbb34d4af0cdfe14cd243f3b09dc95b013
treed3e23b6c58c955bc6e38c0a31d3a0d1f7ad8de99
parentd3509f8bc7b0560044c15f0e3ecfde1d9af757a6
e1000e: Separate signaling for link check/link up

Lennart reported the following race condition:

\ e1000_watchdog_task
    \ e1000e_has_link
        \ hw->mac.ops.check_for_link() === e1000e_check_for_copper_link
            /* link is up */
            mac->get_link_status = false;

                            /* interrupt */
                            \ e1000_msix_other
                                hw->mac.get_link_status = true;

        link_active = !hw->mac.get_link_status
        /* link_active is false, wrongly */

This problem arises because the single flag get_link_status is used to
signal two different states: link status needs checking and link status is
down.

Avoid the problem by using the return value of .check_for_link to signal
the link status to e1000e_has_link().

Reported-by: Lennart Sorensen <lsorense@csclub.uwaterloo.ca>
Signed-off-by: Benjamin Poirier <bpoirier@suse.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/e1000e/mac.c
drivers/net/ethernet/intel/e1000e/netdev.c