diff options
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r-- | drivers/pci/pci.c | 91 |
1 files changed, 86 insertions, 5 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index cab05f31223f..460d046ab6fe 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -10,6 +10,8 @@ | |||
10 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
11 | #include <linux/delay.h> | 11 | #include <linux/delay.h> |
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/of.h> | ||
14 | #include <linux/of_pci.h> | ||
13 | #include <linux/pci.h> | 15 | #include <linux/pci.h> |
14 | #include <linux/pm.h> | 16 | #include <linux/pm.h> |
15 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
@@ -3197,7 +3199,7 @@ static int pci_pm_reset(struct pci_dev *dev, int probe) | |||
3197 | { | 3199 | { |
3198 | u16 csr; | 3200 | u16 csr; |
3199 | 3201 | ||
3200 | if (!dev->pm_cap) | 3202 | if (!dev->pm_cap || dev->dev_flags & PCI_DEV_FLAGS_NO_PM_RESET) |
3201 | return -ENOTTY; | 3203 | return -ENOTTY; |
3202 | 3204 | ||
3203 | pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &csr); | 3205 | pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &csr); |
@@ -3271,7 +3273,8 @@ static int pci_parent_bus_reset(struct pci_dev *dev, int probe) | |||
3271 | { | 3273 | { |
3272 | struct pci_dev *pdev; | 3274 | struct pci_dev *pdev; |
3273 | 3275 | ||
3274 | if (pci_is_root_bus(dev->bus) || dev->subordinate || !dev->bus->self) | 3276 | if (pci_is_root_bus(dev->bus) || dev->subordinate || |
3277 | !dev->bus->self || dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET) | ||
3275 | return -ENOTTY; | 3278 | return -ENOTTY; |
3276 | 3279 | ||
3277 | list_for_each_entry(pdev, &dev->bus->devices, bus_list) | 3280 | list_for_each_entry(pdev, &dev->bus->devices, bus_list) |
@@ -3305,7 +3308,8 @@ static int pci_dev_reset_slot_function(struct pci_dev *dev, int probe) | |||
3305 | { | 3308 | { |
3306 | struct pci_dev *pdev; | 3309 | struct pci_dev *pdev; |
3307 | 3310 | ||
3308 | if (dev->subordinate || !dev->slot) | 3311 | if (dev->subordinate || !dev->slot || |
3312 | dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET) | ||
3309 | return -ENOTTY; | 3313 | return -ENOTTY; |
3310 | 3314 | ||
3311 | list_for_each_entry(pdev, &dev->bus->devices, bus_list) | 3315 | list_for_each_entry(pdev, &dev->bus->devices, bus_list) |
@@ -3557,6 +3561,20 @@ int pci_try_reset_function(struct pci_dev *dev) | |||
3557 | } | 3561 | } |
3558 | EXPORT_SYMBOL_GPL(pci_try_reset_function); | 3562 | EXPORT_SYMBOL_GPL(pci_try_reset_function); |
3559 | 3563 | ||
3564 | /* Do any devices on or below this bus prevent a bus reset? */ | ||
3565 | static bool pci_bus_resetable(struct pci_bus *bus) | ||
3566 | { | ||
3567 | struct pci_dev *dev; | ||
3568 | |||
3569 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
3570 | if (dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET || | ||
3571 | (dev->subordinate && !pci_bus_resetable(dev->subordinate))) | ||
3572 | return false; | ||
3573 | } | ||
3574 | |||
3575 | return true; | ||
3576 | } | ||
3577 | |||
3560 | /* Lock devices from the top of the tree down */ | 3578 | /* Lock devices from the top of the tree down */ |
3561 | static void pci_bus_lock(struct pci_bus *bus) | 3579 | static void pci_bus_lock(struct pci_bus *bus) |
3562 | { | 3580 | { |
@@ -3607,6 +3625,22 @@ unlock: | |||
3607 | return 0; | 3625 | return 0; |
3608 | } | 3626 | } |
3609 | 3627 | ||
3628 | /* Do any devices on or below this slot prevent a bus reset? */ | ||
3629 | static bool pci_slot_resetable(struct pci_slot *slot) | ||
3630 | { | ||
3631 | struct pci_dev *dev; | ||
3632 | |||
3633 | list_for_each_entry(dev, &slot->bus->devices, bus_list) { | ||
3634 | if (!dev->slot || dev->slot != slot) | ||
3635 | continue; | ||
3636 | if (dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET || | ||
3637 | (dev->subordinate && !pci_bus_resetable(dev->subordinate))) | ||
3638 | return false; | ||
3639 | } | ||
3640 | |||
3641 | return true; | ||
3642 | } | ||
3643 | |||
3610 | /* Lock devices from the top of the tree down */ | 3644 | /* Lock devices from the top of the tree down */ |
3611 | static void pci_slot_lock(struct pci_slot *slot) | 3645 | static void pci_slot_lock(struct pci_slot *slot) |
3612 | { | 3646 | { |
@@ -3728,7 +3762,7 @@ static int pci_slot_reset(struct pci_slot *slot, int probe) | |||
3728 | { | 3762 | { |
3729 | int rc; | 3763 | int rc; |
3730 | 3764 | ||
3731 | if (!slot) | 3765 | if (!slot || !pci_slot_resetable(slot)) |
3732 | return -ENOTTY; | 3766 | return -ENOTTY; |
3733 | 3767 | ||
3734 | if (!probe) | 3768 | if (!probe) |
@@ -3820,7 +3854,7 @@ EXPORT_SYMBOL_GPL(pci_try_reset_slot); | |||
3820 | 3854 | ||
3821 | static int pci_bus_reset(struct pci_bus *bus, int probe) | 3855 | static int pci_bus_reset(struct pci_bus *bus, int probe) |
3822 | { | 3856 | { |
3823 | if (!bus->self) | 3857 | if (!bus->self || !pci_bus_resetable(bus)) |
3824 | return -ENOTTY; | 3858 | return -ENOTTY; |
3825 | 3859 | ||
3826 | if (probe) | 3860 | if (probe) |
@@ -4439,6 +4473,53 @@ int pci_get_new_domain_nr(void) | |||
4439 | { | 4473 | { |
4440 | return atomic_inc_return(&__domain_nr); | 4474 | return atomic_inc_return(&__domain_nr); |
4441 | } | 4475 | } |
4476 | |||
4477 | #ifdef CONFIG_PCI_DOMAINS_GENERIC | ||
4478 | void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent) | ||
4479 | { | ||
4480 | static int use_dt_domains = -1; | ||
4481 | int domain = of_get_pci_domain_nr(parent->of_node); | ||
4482 | |||
4483 | /* | ||
4484 | * Check DT domain and use_dt_domains values. | ||
4485 | * | ||
4486 | * If DT domain property is valid (domain >= 0) and | ||
4487 | * use_dt_domains != 0, the DT assignment is valid since this means | ||
4488 | * we have not previously allocated a domain number by using | ||
4489 | * pci_get_new_domain_nr(); we should also update use_dt_domains to | ||
4490 | * 1, to indicate that we have just assigned a domain number from | ||
4491 | * DT. | ||
4492 | * | ||
4493 | * If DT domain property value is not valid (ie domain < 0), and we | ||
4494 | * have not previously assigned a domain number from DT | ||
4495 | * (use_dt_domains != 1) we should assign a domain number by | ||
4496 | * using the: | ||
4497 | * | ||
4498 | * pci_get_new_domain_nr() | ||
4499 | * | ||
4500 | * API and update the use_dt_domains value to keep track of method we | ||
4501 | * are using to assign domain numbers (use_dt_domains = 0). | ||
4502 | * | ||
4503 | * All other combinations imply we have a platform that is trying | ||
4504 | * to mix domain numbers obtained from DT and pci_get_new_domain_nr(), | ||
4505 | * which is a recipe for domain mishandling and it is prevented by | ||
4506 | * invalidating the domain value (domain = -1) and printing a | ||
4507 | * corresponding error. | ||
4508 | */ | ||
4509 | if (domain >= 0 && use_dt_domains) { | ||
4510 | use_dt_domains = 1; | ||
4511 | } else if (domain < 0 && use_dt_domains != 1) { | ||
4512 | use_dt_domains = 0; | ||
4513 | domain = pci_get_new_domain_nr(); | ||
4514 | } else { | ||
4515 | dev_err(parent, "Node %s has inconsistent \"linux,pci-domain\" property in DT\n", | ||
4516 | parent->of_node->full_name); | ||
4517 | domain = -1; | ||
4518 | } | ||
4519 | |||
4520 | bus->domain_nr = domain; | ||
4521 | } | ||
4522 | #endif | ||
4442 | #endif | 4523 | #endif |
4443 | 4524 | ||
4444 | /** | 4525 | /** |