• Mayurkumar Patel's avatar
    PCI: pciehp: Process all hotplug events before looking for new ones · fad214b0
    Mayurkumar Patel authored
    Previously we accumulated hotplug events, then processed them, essentially
    like this:
    
      events = 0
      do {
        status = read(Slot Status)
        status &= EVENT_MASK              # only look at events
        events |= status                  # accumulate events
        write(Slot Status, events)        # clear events
      } while (status)
      process events
    
    The problem is that as soon as we clear events in Slot Status, the hardware
    may send notifications for new events, and we lose information about the
    first events.  For example, we might see two Presence Detect Changed
    events, but lose the fact that the slot was temporarily empty:
    
      read  PCI_EXP_SLTSTA_PDC set, PCI_EXP_SLTSTA_PDS clear  # slot empty
      write PCI_EXP_SLTSTA_PDC                                # clear PDC event
      read  PCI_EXP_SLTSTA_PDC set, PCI_EXP_SLTSTA_PDS set    # slot occupied
    
    The current code does not process a removal; it only processes the
    insertion, which fails because we didn't remove the original device.
    
    To avoid this problem, read Slot Status once and process all the events
    before reading it again, like this:
    
      do {
        read events
        clear events
        process events
      } while (events)
    
    [bhelgaas: changelog, add external loop around pciehp_isr()]
    Tested-by: default avatarLukas Wunner <lukas@wunner.de>
    Signed-off-by: default avatarMayurkumar Patel <mayurkumar.patel@intel.com>
    Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
    Reviewed-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
    fad214b0
pciehp_hpc.c 22.6 KB