(&mut self, bdf: PciBdf)
| 946 | } |
| 947 | |
| 948 | fn parse_capabilities(&mut self, bdf: PciBdf) { |
| 949 | if !self.has_capabilities() { |
| 950 | return; |
| 951 | } |
| 952 | |
| 953 | let mut cap_iter = self |
| 954 | .vfio_wrapper |
| 955 | .read_config_byte(PCI_CONFIG_CAPABILITY_OFFSET) |
| 956 | & PCI_CONFIG_CAPABILITY_PTR_MASK; |
| 957 | |
| 958 | let mut pci_express_cap_found = false; |
| 959 | let mut power_management_cap_found = false; |
| 960 | |
| 961 | while cap_iter != 0 { |
| 962 | let cap_id = self.vfio_wrapper.read_config_byte(cap_iter.into()); |
| 963 | |
| 964 | match PciCapabilityId::from(cap_id) { |
| 965 | PciCapabilityId::MessageSignalledInterrupts => { |
| 966 | if let Some(irq_info) = self.vfio_wrapper.get_irq_info(VFIO_PCI_MSI_IRQ_INDEX) |
| 967 | && irq_info.count > 0 |
| 968 | { |
| 969 | // Parse capability only if the VFIO device |
| 970 | // supports MSI. |
| 971 | let msg_ctl = self.parse_msi_capabilities(cap_iter); |
| 972 | self.initialize_msi(msg_ctl, cap_iter as u32, None); |
| 973 | } |
| 974 | } |
| 975 | PciCapabilityId::MsiX => { |
| 976 | if let Some(irq_info) = self.vfio_wrapper.get_irq_info(VFIO_PCI_MSIX_IRQ_INDEX) |
| 977 | && irq_info.count > 0 |
| 978 | { |
| 979 | // Parse capability only if the VFIO device |
| 980 | // supports MSI-X. |
| 981 | let msix_cap = self.parse_msix_capabilities(cap_iter); |
| 982 | self.initialize_msix(msix_cap, cap_iter as u32, bdf, None); |
| 983 | } |
| 984 | } |
| 985 | PciCapabilityId::PciExpress => pci_express_cap_found = true, |
| 986 | PciCapabilityId::PowerManagement => power_management_cap_found = true, |
| 987 | _ => {} |
| 988 | } |
| 989 | |
| 990 | let cap_next = self.vfio_wrapper.read_config_byte((cap_iter + 1).into()) |
| 991 | & PCI_CONFIG_CAPABILITY_PTR_MASK; |
| 992 | |
| 993 | // Break out of the loop, if we either find the end or we have a broken device. This |
| 994 | // doesn't handle all cases where a device might send us in a loop here, but it |
| 995 | // handles case of a device returning 0xFF instead of implementing a real |
| 996 | // capabilities list. |
| 997 | if cap_next == 0 || cap_next == cap_iter { |
| 998 | break; |
| 999 | } |
| 1000 | |
| 1001 | cap_iter = cap_next; |
| 1002 | } |
| 1003 | |
| 1004 | if let Some(clique_id) = self.x_nv_gpudirect_clique { |
| 1005 | self.add_nv_gpudirect_clique_cap(cap_iter, clique_id); |
no test coverage detected