aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeith Busch <keith.busch@intel.com>2018-09-20 12:27:16 -0400
committerBjorn Helgaas <bhelgaas@google.com>2018-10-02 17:04:40 -0400
commita6bd101b8f84f9b98768e9ab1e418c239e2e669f (patch)
tree916bea7101fb1de3444e351c583205653cfc464a
parent7b42d97e99d3a2babffd1b3456ded08b54981538 (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.h60
-rw-r--r--drivers/pci/pcie/err.c10
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 */
308static 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
302static inline int pci_dev_set_disconnected(struct pci_dev *dev, void *unused) 346static 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
308static inline bool pci_dev_is_disconnected(const struct pci_dev *dev) 355static 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
313static inline void pci_dev_assign_added(struct pci_dev *dev, bool added) 363static 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;