1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (C) 2023, Intel Corporation. */ 3 4 #include "ice.h" 5 #include "ice_lib.h" 6 #include "ice_irq.h" 7 8 /** 9 * ice_init_irq_tracker - initialize interrupt tracker 10 * @pf: board private structure 11 * @max_vectors: maximum number of vectors that tracker can hold 12 * @num_static: number of preallocated interrupts 13 */ 14 static void 15 ice_init_irq_tracker(struct ice_pf *pf, unsigned int max_vectors, 16 unsigned int num_static) 17 { 18 pf->irq_tracker.num_entries = max_vectors; 19 pf->irq_tracker.num_static = num_static; 20 xa_init_flags(&pf->irq_tracker.entries, XA_FLAGS_ALLOC); 21 } 22 23 static int 24 ice_init_virt_irq_tracker(struct ice_pf *pf, u32 base, u32 num_entries) 25 { 26 pf->virt_irq_tracker.bm = bitmap_zalloc(num_entries, GFP_KERNEL); 27 if (!pf->virt_irq_tracker.bm) 28 return -ENOMEM; 29 30 pf->virt_irq_tracker.num_entries = num_entries; 31 pf->virt_irq_tracker.base = base; 32 33 return 0; 34 } 35 36 /** 37 * ice_deinit_irq_tracker - free xarray tracker 38 * @pf: board private structure 39 */ 40 static void ice_deinit_irq_tracker(struct ice_pf *pf) 41 { 42 xa_destroy(&pf->irq_tracker.entries); 43 } 44 45 static void ice_deinit_virt_irq_tracker(struct ice_pf *pf) 46 { 47 bitmap_free(pf->virt_irq_tracker.bm); 48 } 49 50 /** 51 * ice_free_irq_res - free a block of resources 52 * @pf: board private structure 53 * @index: starting index previously returned by ice_get_res 54 */ 55 static void ice_free_irq_res(struct ice_pf *pf, u16 index) 56 { 57 struct ice_irq_entry *entry; 58 59 entry = xa_erase(&pf->irq_tracker.entries, index); 60 kfree(entry); 61 } 62 63 /** 64 * ice_get_irq_res - get an interrupt resource 65 * @pf: board private structure 66 * @dyn_allowed: allow entry to be dynamically allocated 67 * 68 * Allocate new irq entry in the free slot of the tracker. Since xarray 69 * is used, always allocate new entry at the lowest possible index. Set 70 * proper allocation limit for maximum tracker entries. 71 * 72 * Returns allocated irq entry or NULL on failure. 73 */ 74 static struct ice_irq_entry *ice_get_irq_res(struct ice_pf *pf, 75 bool dyn_allowed) 76 { 77 struct xa_limit limit = { .max = pf->irq_tracker.num_entries - 1, 78 .min = 0 }; 79 unsigned int num_static = pf->irq_tracker.num_static - 1; 80 struct ice_irq_entry *entry; 81 unsigned int index; 82 int ret; 83 84 entry = kzalloc(sizeof(*entry), GFP_KERNEL); 85 if (!entry) 86 return NULL; 87 88 /* only already allocated if the caller says so */ 89 if (!dyn_allowed) 90 limit.max = num_static; 91 92 ret = xa_alloc(&pf->irq_tracker.entries, &index, entry, limit, 93 GFP_KERNEL); 94 95 if (ret) { 96 kfree(entry); 97 entry = NULL; 98 } else { 99 entry->index = index; 100 entry->dynamic = index > num_static; 101 } 102 103 return entry; 104 } 105 106 #define ICE_RDMA_AEQ_MSIX 1 107 static int ice_get_default_msix_amount(struct ice_pf *pf) 108 { 109 return ICE_MIN_LAN_OICR_MSIX + netif_get_num_default_rss_queues() + 110 (test_bit(ICE_FLAG_FD_ENA, pf->flags) ? ICE_FDIR_MSIX : 0) + 111 (ice_is_rdma_ena(pf) ? netif_get_num_default_rss_queues() + 112 ICE_RDMA_AEQ_MSIX : 0); 113 } 114 115 /** 116 * ice_clear_interrupt_scheme - Undo things done by ice_init_interrupt_scheme 117 * @pf: board private structure 118 */ 119 void ice_clear_interrupt_scheme(struct ice_pf *pf) 120 { 121 pci_free_irq_vectors(pf->pdev); 122 ice_deinit_irq_tracker(pf); 123 ice_deinit_virt_irq_tracker(pf); 124 } 125 126 /** 127 * ice_init_interrupt_scheme - Determine proper interrupt scheme 128 * @pf: board private structure to initialize 129 */ 130 int ice_init_interrupt_scheme(struct ice_pf *pf) 131 { 132 int total_vectors = pf->hw.func_caps.common_cap.num_msix_vectors; 133 int vectors; 134 135 /* load default PF MSI-X range */ 136 if (!pf->msix.min) 137 pf->msix.min = ICE_MIN_MSIX; 138 139 if (!pf->msix.max) 140 pf->msix.max = min(total_vectors, 141 ice_get_default_msix_amount(pf)); 142 143 pf->msix.total = total_vectors; 144 pf->msix.rest = total_vectors - pf->msix.max; 145 146 if (pci_msix_can_alloc_dyn(pf->pdev)) 147 vectors = pf->msix.min; 148 else 149 vectors = pf->msix.max; 150 151 vectors = pci_alloc_irq_vectors(pf->pdev, pf->msix.min, vectors, 152 PCI_IRQ_MSIX); 153 if (vectors < 0) 154 return vectors; 155 156 ice_init_irq_tracker(pf, pf->msix.max, vectors); 157 158 return ice_init_virt_irq_tracker(pf, pf->msix.max, pf->msix.rest); 159 } 160 161 /** 162 * ice_alloc_irq - Allocate new interrupt vector 163 * @pf: board private structure 164 * @dyn_allowed: allow dynamic allocation of the interrupt 165 * 166 * Allocate new interrupt vector for a given owner id. 167 * return struct msi_map with interrupt details and track 168 * allocated interrupt appropriately. 169 * 170 * This function reserves new irq entry from the irq_tracker. 171 * if according to the tracker information all interrupts that 172 * were allocated with ice_pci_alloc_irq_vectors are already used 173 * and dynamically allocated interrupts are supported then new 174 * interrupt will be allocated with pci_msix_alloc_irq_at. 175 * 176 * Some callers may only support dynamically allocated interrupts. 177 * This is indicated with dyn_allowed flag. 178 * 179 * On failure, return map with negative .index. The caller 180 * is expected to check returned map index. 181 * 182 */ 183 struct msi_map ice_alloc_irq(struct ice_pf *pf, bool dyn_allowed) 184 { 185 struct msi_map map = { .index = -ENOENT }; 186 struct device *dev = ice_pf_to_dev(pf); 187 struct ice_irq_entry *entry; 188 189 entry = ice_get_irq_res(pf, dyn_allowed); 190 if (!entry) 191 return map; 192 193 if (pci_msix_can_alloc_dyn(pf->pdev) && entry->dynamic) { 194 map = pci_msix_alloc_irq_at(pf->pdev, entry->index, NULL); 195 if (map.index < 0) 196 goto exit_free_res; 197 dev_dbg(dev, "allocated new irq at index %d\n", map.index); 198 } else { 199 map.index = entry->index; 200 map.virq = pci_irq_vector(pf->pdev, map.index); 201 } 202 203 return map; 204 205 exit_free_res: 206 dev_err(dev, "Could not allocate irq at idx %d\n", entry->index); 207 ice_free_irq_res(pf, entry->index); 208 return map; 209 } 210 211 /** 212 * ice_free_irq - Free interrupt vector 213 * @pf: board private structure 214 * @map: map with interrupt details 215 * 216 * Remove allocated interrupt from the interrupt tracker. If interrupt was 217 * allocated dynamically, free respective interrupt vector. 218 */ 219 void ice_free_irq(struct ice_pf *pf, struct msi_map map) 220 { 221 struct ice_irq_entry *entry; 222 223 entry = xa_load(&pf->irq_tracker.entries, map.index); 224 225 if (!entry) { 226 dev_err(ice_pf_to_dev(pf), "Failed to get MSIX interrupt entry at index %d", 227 map.index); 228 return; 229 } 230 231 dev_dbg(ice_pf_to_dev(pf), "Free irq at index %d\n", map.index); 232 233 if (entry->dynamic) 234 pci_msix_free_irq(pf->pdev, map); 235 236 ice_free_irq_res(pf, map.index); 237 } 238 239 /** 240 * ice_virt_get_irqs - get irqs for SR-IOV usacase 241 * @pf: pointer to PF structure 242 * @needed: number of irqs to get 243 * 244 * This returns the first MSI-X vector index in PF space that is used by this 245 * VF. This index is used when accessing PF relative registers such as 246 * GLINT_VECT2FUNC and GLINT_DYN_CTL. 247 * This will always be the OICR index in the AVF driver so any functionality 248 * using vf->first_vector_idx for queue configuration_id: id of VF which will 249 * use this irqs 250 */ 251 int ice_virt_get_irqs(struct ice_pf *pf, u32 needed) 252 { 253 int res = bitmap_find_next_zero_area(pf->virt_irq_tracker.bm, 254 pf->virt_irq_tracker.num_entries, 255 0, needed, 0); 256 257 if (res >= pf->virt_irq_tracker.num_entries) 258 return -ENOENT; 259 260 bitmap_set(pf->virt_irq_tracker.bm, res, needed); 261 262 /* conversion from number in bitmap to global irq index */ 263 return res + pf->virt_irq_tracker.base; 264 } 265 266 /** 267 * ice_virt_free_irqs - free irqs used by the VF 268 * @pf: pointer to PF structure 269 * @index: first index to be free 270 * @irqs: number of irqs to free 271 */ 272 void ice_virt_free_irqs(struct ice_pf *pf, u32 index, u32 irqs) 273 { 274 bitmap_clear(pf->virt_irq_tracker.bm, index - pf->virt_irq_tracker.base, 275 irqs); 276 } 277