]> git.baikalelectronics.ru Git - kernel.git/commit
PCI: pciehp: Process all hotplug events before looking for new ones
authorMayurkumar Patel <mayurkumar.patel@intel.com>
Thu, 8 Sep 2016 20:07:56 +0000 (15:07 -0500)
committerBjorn Helgaas <bhelgaas@google.com>
Wed, 14 Sep 2016 19:24:31 +0000 (14:24 -0500)
commit6698aeaa959b5e34f8c6a0cf1850bf6b3db3ab4b
tree3f0c8367e3dcb08641f3fafe60996d6519b79d16
parenta7530dedecd0d3c32ca1d3714fafcbed39c92dc7
PCI: pciehp: Process all hotplug events before looking for new ones

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: Lukas Wunner <lukas@wunner.de>
Signed-off-by: Mayurkumar Patel <mayurkumar.patel@intel.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
drivers/pci/hotplug/pciehp_hpc.c