| 731 | } |
| 732 | |
| 733 | void rt_pci_enum_device(struct rt_pci_bus *bus, |
| 734 | rt_bool_t (callback(struct rt_pci_device *, void *)), void *data) |
| 735 | { |
| 736 | rt_bool_t is_end = RT_FALSE; |
| 737 | struct rt_spinlock *lock; |
| 738 | struct rt_pci_bus *parent; |
| 739 | struct rt_pci_device *pdev, *last_pdev = RT_NULL; |
| 740 | |
| 741 | /* Walk tree */ |
| 742 | while (bus && !is_end) |
| 743 | { |
| 744 | /* Goto bottom */ |
| 745 | for (;;) |
| 746 | { |
| 747 | lock = &bus->lock; |
| 748 | |
| 749 | spin_lock(lock); |
| 750 | if (rt_list_isempty(&bus->children_nodes)) |
| 751 | { |
| 752 | parent = bus->parent; |
| 753 | break; |
| 754 | } |
| 755 | bus = rt_list_entry(&bus->children_nodes, struct rt_pci_bus, list); |
| 756 | spin_unlock(lock); |
| 757 | } |
| 758 | |
| 759 | rt_list_for_each_entry(pdev, &bus->devices_nodes, list) |
| 760 | { |
| 761 | if (last_pdev) |
| 762 | { |
| 763 | spin_unlock(lock); |
| 764 | |
| 765 | if (callback(last_pdev, data)) |
| 766 | { |
| 767 | spin_lock(lock); |
| 768 | --last_pdev->parent.ref_count; |
| 769 | |
| 770 | is_end = RT_TRUE; |
| 771 | break; |
| 772 | } |
| 773 | |
| 774 | spin_lock(lock); |
| 775 | --last_pdev->parent.ref_count; |
| 776 | } |
| 777 | ++pdev->parent.ref_count; |
| 778 | last_pdev = pdev; |
| 779 | } |
| 780 | |
| 781 | if (!is_end && last_pdev) |
| 782 | { |
| 783 | spin_unlock(lock); |
| 784 | |
| 785 | if (callback(last_pdev, data)) |
| 786 | { |
| 787 | is_end = RT_TRUE; |
| 788 | } |
| 789 | |
| 790 | spin_lock(lock); |
no test coverage detected