PCI: pciehp: Add hotplug_lock to serialize hotplug events
Today it is there is no protection around pciehp_enable_slot() and pciehp_disable_slot() to ensure that they complete before another hot-plug operation can be done on that particular slot. This patch introduces the slot->hotplug_lock to ensure that any hotplug operations (add / remove) complete before another hotplug event can begin processing on that particular slot. 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>
This commit is contained in:

committed by
Bjorn Helgaas

parent
c4f2f5e498
commit
50b52fdee0
@@ -293,6 +293,7 @@ static void pciehp_power_thread(struct work_struct *work)
|
||||
struct power_work_info *info =
|
||||
container_of(work, struct power_work_info, work);
|
||||
struct slot *p_slot = info->p_slot;
|
||||
int ret;
|
||||
|
||||
switch (info->req) {
|
||||
case DISABLE_REQ:
|
||||
@@ -300,7 +301,9 @@ static void pciehp_power_thread(struct work_struct *work)
|
||||
"Disabling domain:bus:device=%04x:%02x:00\n",
|
||||
pci_domain_nr(p_slot->ctrl->pcie->port->subordinate),
|
||||
p_slot->ctrl->pcie->port->subordinate->number);
|
||||
mutex_lock(&p_slot->hotplug_lock);
|
||||
pciehp_disable_slot(p_slot);
|
||||
mutex_unlock(&p_slot->hotplug_lock);
|
||||
mutex_lock(&p_slot->lock);
|
||||
p_slot->state = STATIC_STATE;
|
||||
mutex_unlock(&p_slot->lock);
|
||||
@@ -310,7 +313,10 @@ static void pciehp_power_thread(struct work_struct *work)
|
||||
"Enabling domain:bus:device=%04x:%02x:00\n",
|
||||
pci_domain_nr(p_slot->ctrl->pcie->port->subordinate),
|
||||
p_slot->ctrl->pcie->port->subordinate->number);
|
||||
if (pciehp_enable_slot(p_slot))
|
||||
mutex_lock(&p_slot->hotplug_lock);
|
||||
ret = pciehp_enable_slot(p_slot);
|
||||
mutex_unlock(&p_slot->hotplug_lock);
|
||||
if (ret)
|
||||
pciehp_green_led_off(p_slot);
|
||||
mutex_lock(&p_slot->lock);
|
||||
p_slot->state = STATIC_STATE;
|
||||
@@ -546,6 +552,9 @@ static void interrupt_event_handler(struct work_struct *work)
|
||||
kfree(info);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: This function must be called with slot->hotplug_lock held
|
||||
*/
|
||||
int pciehp_enable_slot(struct slot *p_slot)
|
||||
{
|
||||
u8 getstatus = 0;
|
||||
@@ -584,7 +593,9 @@ int pciehp_enable_slot(struct slot *p_slot)
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Note: This function must be called with slot->hotplug_lock held
|
||||
*/
|
||||
int pciehp_disable_slot(struct slot *p_slot)
|
||||
{
|
||||
u8 getstatus = 0;
|
||||
@@ -617,7 +628,9 @@ int pciehp_sysfs_enable_slot(struct slot *p_slot)
|
||||
case STATIC_STATE:
|
||||
p_slot->state = POWERON_STATE;
|
||||
mutex_unlock(&p_slot->lock);
|
||||
mutex_lock(&p_slot->hotplug_lock);
|
||||
retval = pciehp_enable_slot(p_slot);
|
||||
mutex_unlock(&p_slot->hotplug_lock);
|
||||
mutex_lock(&p_slot->lock);
|
||||
p_slot->state = STATIC_STATE;
|
||||
break;
|
||||
|
Reference in New Issue
Block a user