diff options
author | Keith Busch <keith.busch@intel.com> | 2018-09-20 12:27:16 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2018-10-02 17:04:40 -0400 |
commit | a6bd101b8f84f9b98768e9ab1e418c239e2e669f (patch) | |
tree | 916bea7101fb1de3444e351c583205653cfc464a | |
parent | 7b42d97e99d3a2babffd1b3456ded08b54981538 (diff) |
PCI: Unify device inaccessible
Bring surprise removals and permanent failures together so we no longer
need separate flags. The implementation enforces that error handling will
not be able to override a surprise removal's permanent channel failure.
Signed-off-by: Keith Busch <keith.busch@intel.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Sinan Kaya <okaya@kernel.org>
-rw-r--r-- | drivers/pci/pci.h | 60 | ||||
-rw-r--r-- | drivers/pci/pcie/err.c | 10 |
2 files changed, 59 insertions, 11 deletions
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 9b279805489f..eb3125decffe 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -295,21 +295,71 @@ struct pci_sriov { | |||
295 | bool drivers_autoprobe; /* Auto probing of VFs by driver */ | 295 | bool drivers_autoprobe; /* Auto probing of VFs by driver */ |
296 | }; | 296 | }; |
297 | 297 | ||
298 | /* pci_dev priv_flags */ | 298 | /** |
299 | #define PCI_DEV_DISCONNECTED 0 | 299 | * pci_dev_set_io_state - Set the new error state if possible. |
300 | #define PCI_DEV_ADDED 1 | 300 | * |
301 | * @dev - pci device to set new error_state | ||
302 | * @new - the state we want dev to be in | ||
303 | * | ||
304 | * Must be called with device_lock held. | ||
305 | * | ||
306 | * Returns true if state has been changed to the requested state. | ||
307 | */ | ||
308 | static inline bool pci_dev_set_io_state(struct pci_dev *dev, | ||
309 | pci_channel_state_t new) | ||
310 | { | ||
311 | bool changed = false; | ||
312 | |||
313 | device_lock_assert(&dev->dev); | ||
314 | switch (new) { | ||
315 | case pci_channel_io_perm_failure: | ||
316 | switch (dev->error_state) { | ||
317 | case pci_channel_io_frozen: | ||
318 | case pci_channel_io_normal: | ||
319 | case pci_channel_io_perm_failure: | ||
320 | changed = true; | ||
321 | break; | ||
322 | } | ||
323 | break; | ||
324 | case pci_channel_io_frozen: | ||
325 | switch (dev->error_state) { | ||
326 | case pci_channel_io_frozen: | ||
327 | case pci_channel_io_normal: | ||
328 | changed = true; | ||
329 | break; | ||
330 | } | ||
331 | break; | ||
332 | case pci_channel_io_normal: | ||
333 | switch (dev->error_state) { | ||
334 | case pci_channel_io_frozen: | ||
335 | case pci_channel_io_normal: | ||
336 | changed = true; | ||
337 | break; | ||
338 | } | ||
339 | break; | ||
340 | } | ||
341 | if (changed) | ||
342 | dev->error_state = new; | ||
343 | return changed; | ||
344 | } | ||
301 | 345 | ||
302 | static inline int pci_dev_set_disconnected(struct pci_dev *dev, void *unused) | 346 | static inline int pci_dev_set_disconnected(struct pci_dev *dev, void *unused) |
303 | { | 347 | { |
304 | set_bit(PCI_DEV_DISCONNECTED, &dev->priv_flags); | 348 | device_lock(&dev->dev); |
349 | pci_dev_set_io_state(dev, pci_channel_io_perm_failure); | ||
350 | device_unlock(&dev->dev); | ||
351 | |||
305 | return 0; | 352 | return 0; |
306 | } | 353 | } |
307 | 354 | ||
308 | static inline bool pci_dev_is_disconnected(const struct pci_dev *dev) | 355 | static inline bool pci_dev_is_disconnected(const struct pci_dev *dev) |
309 | { | 356 | { |
310 | return test_bit(PCI_DEV_DISCONNECTED, &dev->priv_flags); | 357 | return dev->error_state == pci_channel_io_perm_failure; |
311 | } | 358 | } |
312 | 359 | ||
360 | /* pci_dev priv_flags */ | ||
361 | #define PCI_DEV_ADDED 0 | ||
362 | |||
313 | static inline void pci_dev_assign_added(struct pci_dev *dev, bool added) | 363 | static inline void pci_dev_assign_added(struct pci_dev *dev, bool added) |
314 | { | 364 | { |
315 | assign_bit(PCI_DEV_ADDED, &dev->priv_flags, added); | 365 | assign_bit(PCI_DEV_ADDED, &dev->priv_flags, added); |
diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c index 31e8a4314384..4da2a62b4f77 100644 --- a/drivers/pci/pcie/err.c +++ b/drivers/pci/pcie/err.c | |||
@@ -52,9 +52,8 @@ static int report_error_detected(struct pci_dev *dev, | |||
52 | const struct pci_error_handlers *err_handler; | 52 | const struct pci_error_handlers *err_handler; |
53 | 53 | ||
54 | device_lock(&dev->dev); | 54 | device_lock(&dev->dev); |
55 | dev->error_state = state; | 55 | if (!pci_dev_set_io_state(dev, state) || |
56 | 56 | !dev->driver || | |
57 | if (!dev->driver || | ||
58 | !dev->driver->err_handler || | 57 | !dev->driver->err_handler || |
59 | !dev->driver->err_handler->error_detected) { | 58 | !dev->driver->err_handler->error_detected) { |
60 | /* | 59 | /* |
@@ -130,9 +129,8 @@ static int report_resume(struct pci_dev *dev, void *data) | |||
130 | const struct pci_error_handlers *err_handler; | 129 | const struct pci_error_handlers *err_handler; |
131 | 130 | ||
132 | device_lock(&dev->dev); | 131 | device_lock(&dev->dev); |
133 | dev->error_state = pci_channel_io_normal; | 132 | if (!pci_dev_set_io_state(dev, pci_channel_io_normal) || |
134 | 133 | !dev->driver || | |
135 | if (!dev->driver || | ||
136 | !dev->driver->err_handler || | 134 | !dev->driver->err_handler || |
137 | !dev->driver->err_handler->resume) | 135 | !dev->driver->err_handler->resume) |
138 | goto out; | 136 | goto out; |