[lkml]   [2010]   [Aug]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
Messages in this thread
    Patch in this message
    Subject[11/34] e1000e: dont inadvertently re-set INTX_DISABLE
    2.6.32-stable review patch.  If anyone has any objections, please let us know.


    From: Dean Nelson <>

    commit 36f2407fe52c55566221f8c68c8fb808abffd2f5 upstream.

    Should e1000_test_msi() fail to see an msi interrupt, it attempts to
    fallback to legacy INTx interrupts. But an error in the code may prevent
    this from happening correctly.

    Before calling e1000_test_msi_interrupt(), e1000_test_msi() disables SERR
    by clearing the SERR bit from the just read PCI_COMMAND bits as it writes
    them back out.

    Upon return from calling e1000_test_msi_interrupt(), it re-enables SERR
    by writing out the version of PCI_COMMAND it had previously read.

    The problem with this is that e1000_test_msi_interrupt() calls
    pci_disable_msi(), which eventually ends up in pci_intx(). And because
    pci_intx() was called with enable set to 1, the INTX_DISABLE bit gets
    cleared from PCI_COMMAND, which is what we want. But when we get back to
    e1000_test_msi(), the INTX_DISABLE bit gets inadvertently re-set because
    of the attempt by e1000_test_msi() to re-enable SERR.

    The solution is to have e1000_test_msi() re-read the PCI_COMMAND bits as
    part of its attempt to re-enable SERR.

    During debugging/testing of this issue I found that not all the systems
    I ran on had the SERR bit set to begin with. And on some of the systems
    the same could be said for the INTX_DISABLE bit. Needless to say these
    latter systems didn't have a problem falling back to legacy INTx
    interrupts with the code as is.

    Signed-off-by: Dean Nelson <>
    Tested-by: Emil Tantilov <>
    Signed-off-by: Jeff Kirsher <>
    Signed-off-by: David S. Miller <>
    Signed-off-by: Greg Kroah-Hartman <>

    drivers/net/e1000e/netdev.c | 13 +++++++++----
    1 file changed, 9 insertions(+), 4 deletions(-)

    --- a/drivers/net/e1000e/netdev.c
    +++ b/drivers/net/e1000e/netdev.c
    @@ -3073,13 +3073,18 @@ static int e1000_test_msi(struct e1000_a

    /* disable SERR in case the MSI write causes a master abort */
    pci_read_config_word(adapter->pdev, PCI_COMMAND, &pci_cmd);
    - pci_write_config_word(adapter->pdev, PCI_COMMAND,
    - pci_cmd & ~PCI_COMMAND_SERR);
    + if (pci_cmd & PCI_COMMAND_SERR)
    + pci_write_config_word(adapter->pdev, PCI_COMMAND,
    + pci_cmd & ~PCI_COMMAND_SERR);

    err = e1000_test_msi_interrupt(adapter);

    - /* restore previous setting of command word */
    - pci_write_config_word(adapter->pdev, PCI_COMMAND, pci_cmd);
    + /* re-enable SERR */
    + if (pci_cmd & PCI_COMMAND_SERR) {
    + pci_read_config_word(adapter->pdev, PCI_COMMAND, &pci_cmd);
    + pci_cmd |= PCI_COMMAND_SERR;
    + pci_write_config_word(adapter->pdev, PCI_COMMAND, pci_cmd);
    + }

    /* success ! */
    if (!err)

     \ /
      Last update: 2010-08-06 21:17    [W:0.037 / U:3.492 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site