summaryrefslogtreecommitdiffstats
path: root/drivers/pci/bus.c
diff options
context:
space:
mode:
authorRajat Jain <rajatxjain@gmail.com>2014-02-04 18:30:56 -0800
committerBjorn Helgaas <bhelgaas@google.com>2014-02-11 16:13:01 -0700
commitc4f2f5e4981073a5aa0739f93b6733060cd37648 (patch)
tree36ee3f06a3a82f73b1a862d86d5ae237e2679319 /drivers/pci/bus.c
parent06a8d89af551b6151fa2289dd8660647ea9d2faa (diff)
downloadblackbird-op-linux-c4f2f5e4981073a5aa0739f93b6733060cd37648.tar.gz
blackbird-op-linux-c4f2f5e4981073a5aa0739f93b6733060cd37648.zip
PCI: pciehp: Ensure very fast hotplug events are also processed
Today, this is how all the hotplug and unplug events work: Hotplug / Removal needs to be done => Set slot->state (protected by slot->lock) to either POWERON_STATE (for enabling) or POWEROFF_STATE (for disabling). => Submit the work item for pciehp_power_thread() to slot->wq. Problem: There is a problem if the hotplug events can happen fast enough that they do not give SW enough time to add or remove the new devices. => Assume: Event for unplug comes (e.g. surprise removal). But before the pciehp_power_thread() work item was executed, the card was replaced by another card, causing surprise hotplug event. => What goes wrong: => The hot-removal event sets slot->state to POWEROFF_STATE, and schedules the pciehp_power_thread(). => The hot-add event sets slot->state to POWERON_STATE, and schedules the pciehp_power_thread(). => Now the pciehp_power_thread() is scheduled twice, and on both occasions it will find POWERON_STATE and will try to add the devices on the slot, and will fail complaining that the devices already exist. => Why this is a problem: If the device was replaced between the hot removal and hot-add, then we should unload the old driver and reload the new one. This does not happen today. The kernel or the driver is not even aware that the device was replaced. The problem is that the pciehp_power_thread() only looks at the slot->state which would only contain the *latest* state - not the actual event (add / remove) that was the intent of the IRQ handler who submitted the work. What this patch does: => Hotplug events pass on an actual request (for addition or removal) to pciehp_power_thread() which is local to that work item submission. => pciehp_power_thread() does not need to look at slote->state and hence no locks needed in that. => Essentially this results in all the hotplug and unplug events "replayed" by pciehp_power_thread(). Signed-off-by: Rajat Jain <rajatxjain@gmail.com> Signed-off-by: Rajat Jain <rajatjain@juniper.net> Signed-off-by: Guenter Roeck <groeck@juniper.net> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci/bus.c')
0 files changed, 0 insertions, 0 deletions
OpenPOWER on IntegriCloud