PCI/PM: Fix deadlock when unbinding device if parent in D3cold
[cascardo/linux.git] / drivers / pci / pcie / aer / aerdrv_core.c
index 06bad96..af4e31c 100644 (file)
@@ -213,6 +213,7 @@ static int report_error_detected(struct pci_dev *dev, void *data)
        struct aer_broadcast_data *result_data;
        result_data = (struct aer_broadcast_data *) data;
 
+       device_lock(&dev->dev);
        dev->error_state = result_data->state;
 
        if (!dev->driver ||
@@ -231,12 +232,14 @@ static int report_error_detected(struct pci_dev *dev, void *data)
                                   dev->driver ?
                                   "no AER-aware driver" : "no driver");
                }
-               return 0;
+               goto out;
        }
 
        err_handler = dev->driver->err_handler;
        vote = err_handler->error_detected(dev, result_data->state);
        result_data->result = merge_result(result_data->result, vote);
+out:
+       device_unlock(&dev->dev);
        return 0;
 }
 
@@ -247,14 +250,17 @@ static int report_mmio_enabled(struct pci_dev *dev, void *data)
        struct aer_broadcast_data *result_data;
        result_data = (struct aer_broadcast_data *) data;
 
+       device_lock(&dev->dev);
        if (!dev->driver ||
                !dev->driver->err_handler ||
                !dev->driver->err_handler->mmio_enabled)
-               return 0;
+               goto out;
 
        err_handler = dev->driver->err_handler;
        vote = err_handler->mmio_enabled(dev);
        result_data->result = merge_result(result_data->result, vote);
+out:
+       device_unlock(&dev->dev);
        return 0;
 }
 
@@ -265,14 +271,17 @@ static int report_slot_reset(struct pci_dev *dev, void *data)
        struct aer_broadcast_data *result_data;
        result_data = (struct aer_broadcast_data *) data;
 
+       device_lock(&dev->dev);
        if (!dev->driver ||
                !dev->driver->err_handler ||
                !dev->driver->err_handler->slot_reset)
-               return 0;
+               goto out;
 
        err_handler = dev->driver->err_handler;
        vote = err_handler->slot_reset(dev);
        result_data->result = merge_result(result_data->result, vote);
+out:
+       device_unlock(&dev->dev);
        return 0;
 }
 
@@ -280,15 +289,18 @@ static int report_resume(struct pci_dev *dev, void *data)
 {
        const struct pci_error_handlers *err_handler;
 
+       device_lock(&dev->dev);
        dev->error_state = pci_channel_io_normal;
 
        if (!dev->driver ||
                !dev->driver->err_handler ||
                !dev->driver->err_handler->resume)
-               return 0;
+               goto out;
 
        err_handler = dev->driver->err_handler;
        err_handler->resume(dev);
+out:
+       device_unlock(&dev->dev);
        return 0;
 }