| 139 | |
| 140 | impl MsixConfig { |
| 141 | pub fn new( |
| 142 | msix_vectors: u16, |
| 143 | interrupt_source_group: MaybeMutInterruptSourceGroup, |
| 144 | devid: u32, |
| 145 | state: Option<MsixConfigState>, |
| 146 | ) -> result::Result<Self, Error> { |
| 147 | assert!(msix_vectors <= MAX_MSIX_VECTORS_PER_DEVICE); |
| 148 | |
| 149 | let (table_entries, pba_entries, masked, enabled) = if let Some(state) = state { |
| 150 | if state.enabled && !state.masked { |
| 151 | for (idx, table_entry) in state.table_entries.iter().enumerate() { |
| 152 | if table_entry.masked() { |
| 153 | continue; |
| 154 | } |
| 155 | |
| 156 | let config = MsiIrqSourceConfig { |
| 157 | high_addr: table_entry.msg_addr_hi, |
| 158 | low_addr: table_entry.msg_addr_lo, |
| 159 | data: table_entry.msg_data, |
| 160 | devid, |
| 161 | }; |
| 162 | |
| 163 | interrupt_source_group |
| 164 | .update( |
| 165 | idx as InterruptIndex, |
| 166 | InterruptSourceConfig::MsiIrq(config), |
| 167 | state.masked, |
| 168 | true, |
| 169 | ) |
| 170 | .map_err(Error::UpdateInterruptRoute)?; |
| 171 | |
| 172 | interrupt_source_group |
| 173 | .enable() |
| 174 | .map_err(Error::EnableInterruptRoute)?; |
| 175 | } |
| 176 | } |
| 177 | |
| 178 | ( |
| 179 | state.table_entries, |
| 180 | state.pba_entries, |
| 181 | state.masked, |
| 182 | state.enabled, |
| 183 | ) |
| 184 | } else { |
| 185 | let mut table_entries: Vec<MsixTableEntry> = Vec::new(); |
| 186 | table_entries.resize_with(msix_vectors as usize, Default::default); |
| 187 | let mut pba_entries: Vec<u64> = Vec::new(); |
| 188 | let num_pba_entries: usize = ((msix_vectors as usize) / BITS_PER_PBA_ENTRY) + 1; |
| 189 | pba_entries.resize_with(num_pba_entries, Default::default); |
| 190 | |
| 191 | (table_entries, pba_entries, true, false) |
| 192 | }; |
| 193 | |
| 194 | Ok(MsixConfig { |
| 195 | table_entries, |
| 196 | pba_entries, |
| 197 | devid, |
| 198 | interrupt_source_group, |