@@ -32,7 +32,8 @@ struct apic_chip_data {
3232 unsigned int prev_cpu ;
3333 unsigned int irq ;
3434 struct hlist_node clist ;
35- u8 move_in_progress : 1 ;
35+ unsigned int move_in_progress : 1 ,
36+ is_managed : 1 ;
3637};
3738
3839struct irq_domain * x86_vector_domain ;
@@ -152,6 +153,28 @@ static void apic_update_vector(struct irq_data *irqd, unsigned int newvec,
152153 per_cpu (vector_irq , newcpu )[newvec ] = desc ;
153154}
154155
156+ static void vector_assign_managed_shutdown (struct irq_data * irqd )
157+ {
158+ unsigned int cpu = cpumask_first (cpu_online_mask );
159+
160+ apic_update_irq_cfg (irqd , MANAGED_IRQ_SHUTDOWN_VECTOR , cpu );
161+ }
162+
163+ static int reserve_managed_vector (struct irq_data * irqd )
164+ {
165+ const struct cpumask * affmsk = irq_data_get_affinity_mask (irqd );
166+ struct apic_chip_data * apicd = apic_chip_data (irqd );
167+ unsigned long flags ;
168+ int ret ;
169+
170+ raw_spin_lock_irqsave (& vector_lock , flags );
171+ apicd -> is_managed = true;
172+ ret = irq_matrix_reserve_managed (vector_matrix , affmsk );
173+ raw_spin_unlock_irqrestore (& vector_lock , flags );
174+ trace_vector_reserve_managed (irqd -> irq , ret );
175+ return ret ;
176+ }
177+
155178static int allocate_vector (struct irq_data * irqd , const struct cpumask * dest )
156179{
157180 struct apic_chip_data * apicd = apic_chip_data (irqd );
@@ -200,20 +223,65 @@ static int assign_irq_vector(struct irq_data *irqd, const struct cpumask *dest)
200223 return ret ;
201224}
202225
203- static int assign_irq_vector_policy (struct irq_data * irqd ,
204- struct irq_alloc_info * info , int node )
226+ static int assign_irq_vector_any_locked (struct irq_data * irqd )
227+ {
228+ int node = irq_data_get_node (irqd );
229+
230+ if (node != NUMA_NO_NODE ) {
231+ if (!assign_vector_locked (irqd , cpumask_of_node (node )))
232+ return 0 ;
233+ }
234+ return assign_vector_locked (irqd , cpu_online_mask );
235+ }
236+
237+ static int assign_irq_vector_any (struct irq_data * irqd )
238+ {
239+ unsigned long flags ;
240+ int ret ;
241+
242+ raw_spin_lock_irqsave (& vector_lock , flags );
243+ ret = assign_irq_vector_any_locked (irqd );
244+ raw_spin_unlock_irqrestore (& vector_lock , flags );
245+ return ret ;
246+ }
247+
248+ static int
249+ assign_irq_vector_policy (struct irq_data * irqd , struct irq_alloc_info * info )
205250{
251+ if (irqd_affinity_is_managed (irqd ))
252+ return reserve_managed_vector (irqd );
206253 if (info -> mask )
207254 return assign_irq_vector (irqd , info -> mask );
208- if (node != NUMA_NO_NODE &&
209- !assign_irq_vector (irqd , cpumask_of_node (node )))
255+ return assign_irq_vector_any (irqd );
256+ }
257+
258+ static int
259+ assign_managed_vector (struct irq_data * irqd , const struct cpumask * dest )
260+ {
261+ const struct cpumask * affmsk = irq_data_get_affinity_mask (irqd );
262+ struct apic_chip_data * apicd = apic_chip_data (irqd );
263+ int vector , cpu ;
264+
265+ cpumask_and (vector_searchmask , vector_searchmask , affmsk );
266+ cpu = cpumask_first (vector_searchmask );
267+ if (cpu >= nr_cpu_ids )
268+ return - EINVAL ;
269+ /* set_affinity might call here for nothing */
270+ if (apicd -> vector && cpumask_test_cpu (apicd -> cpu , vector_searchmask ))
210271 return 0 ;
211- return assign_irq_vector (irqd , cpu_online_mask );
272+ vector = irq_matrix_alloc_managed (vector_matrix , cpu );
273+ trace_vector_alloc_managed (irqd -> irq , vector , vector );
274+ if (vector < 0 )
275+ return vector ;
276+ apic_update_vector (irqd , vector , cpu );
277+ apic_update_irq_cfg (irqd , vector , cpu );
278+ return 0 ;
212279}
213280
214281static void clear_irq_vector (struct irq_data * irqd )
215282{
216283 struct apic_chip_data * apicd = apic_chip_data (irqd );
284+ bool managed = irqd_affinity_is_managed (irqd );
217285 unsigned int vector = apicd -> vector ;
218286
219287 lockdep_assert_held (& vector_lock );
@@ -225,7 +293,7 @@ static void clear_irq_vector(struct irq_data *irqd)
225293 apicd -> prev_cpu );
226294
227295 per_cpu (vector_irq , apicd -> cpu )[vector ] = VECTOR_UNUSED ;
228- irq_matrix_free (vector_matrix , apicd -> cpu , vector , false );
296+ irq_matrix_free (vector_matrix , apicd -> cpu , vector , managed );
229297 apicd -> vector = 0 ;
230298
231299 /* Clean up move in progress */
@@ -234,12 +302,86 @@ static void clear_irq_vector(struct irq_data *irqd)
234302 return ;
235303
236304 per_cpu (vector_irq , apicd -> prev_cpu )[vector ] = VECTOR_UNUSED ;
237- irq_matrix_free (vector_matrix , apicd -> prev_cpu , vector , false );
305+ irq_matrix_free (vector_matrix , apicd -> prev_cpu , vector , managed );
238306 apicd -> prev_vector = 0 ;
239307 apicd -> move_in_progress = 0 ;
240308 hlist_del_init (& apicd -> clist );
241309}
242310
311+ static void x86_vector_deactivate (struct irq_domain * dom , struct irq_data * irqd )
312+ {
313+ struct apic_chip_data * apicd = apic_chip_data (irqd );
314+ unsigned long flags ;
315+
316+ trace_vector_deactivate (irqd -> irq , apicd -> is_managed ,
317+ false, false);
318+
319+ if (apicd -> is_managed )
320+ return ;
321+
322+ raw_spin_lock_irqsave (& vector_lock , flags );
323+ clear_irq_vector (irqd );
324+ vector_assign_managed_shutdown (irqd );
325+ raw_spin_unlock_irqrestore (& vector_lock , flags );
326+ }
327+
328+ static int activate_managed (struct irq_data * irqd )
329+ {
330+ const struct cpumask * dest = irq_data_get_affinity_mask (irqd );
331+ int ret ;
332+
333+ cpumask_and (vector_searchmask , dest , cpu_online_mask );
334+ if (WARN_ON_ONCE (cpumask_empty (vector_searchmask ))) {
335+ /* Something in the core code broke! Survive gracefully */
336+ pr_err ("Managed startup for irq %u, but no CPU\n" , irqd -> irq );
337+ return EINVAL ;
338+ }
339+
340+ ret = assign_managed_vector (irqd , vector_searchmask );
341+ /*
342+ * This should not happen. The vector reservation got buggered. Handle
343+ * it gracefully.
344+ */
345+ if (WARN_ON_ONCE (ret < 0 )) {
346+ pr_err ("Managed startup irq %u, no vector available\n" ,
347+ irqd -> irq );
348+ }
349+ return ret ;
350+ }
351+
352+ static int x86_vector_activate (struct irq_domain * dom , struct irq_data * irqd ,
353+ bool early )
354+ {
355+ struct apic_chip_data * apicd = apic_chip_data (irqd );
356+ unsigned long flags ;
357+ int ret = 0 ;
358+
359+ trace_vector_activate (irqd -> irq , apicd -> is_managed ,
360+ false, early );
361+
362+ if (!apicd -> is_managed )
363+ return 0 ;
364+
365+ raw_spin_lock_irqsave (& vector_lock , flags );
366+ if (early || irqd_is_managed_and_shutdown (irqd ))
367+ vector_assign_managed_shutdown (irqd );
368+ else
369+ ret = activate_managed (irqd );
370+ raw_spin_unlock_irqrestore (& vector_lock , flags );
371+ return ret ;
372+ }
373+
374+ static void vector_free_reserved_and_managed (struct irq_data * irqd )
375+ {
376+ const struct cpumask * dest = irq_data_get_affinity_mask (irqd );
377+ struct apic_chip_data * apicd = apic_chip_data (irqd );
378+
379+ trace_vector_teardown (irqd -> irq , apicd -> is_managed , false);
380+
381+ if (apicd -> is_managed )
382+ irq_matrix_remove_managed (vector_matrix , dest );
383+ }
384+
243385static void x86_vector_free_irqs (struct irq_domain * domain ,
244386 unsigned int virq , unsigned int nr_irqs )
245387{
@@ -253,6 +395,7 @@ static void x86_vector_free_irqs(struct irq_domain *domain,
253395 if (irqd && irqd -> chip_data ) {
254396 raw_spin_lock_irqsave (& vector_lock , flags );
255397 clear_irq_vector (irqd );
398+ vector_free_reserved_and_managed (irqd );
256399 apicd = irqd -> chip_data ;
257400 irq_domain_reset_irq_data (irqd );
258401 raw_spin_unlock_irqrestore (& vector_lock , flags );
@@ -310,7 +453,7 @@ static int x86_vector_alloc_irqs(struct irq_domain *domain, unsigned int virq,
310453 continue ;
311454 }
312455
313- err = assign_irq_vector_policy (irqd , info , node );
456+ err = assign_irq_vector_policy (irqd , info );
314457 trace_vector_setup (virq + i , false, err );
315458 if (err )
316459 goto error ;
@@ -368,6 +511,8 @@ void x86_vector_debug_show(struct seq_file *m, struct irq_domain *d,
368511static const struct irq_domain_ops x86_vector_domain_ops = {
369512 .alloc = x86_vector_alloc_irqs ,
370513 .free = x86_vector_free_irqs ,
514+ .activate = x86_vector_activate ,
515+ .deactivate = x86_vector_deactivate ,
371516#ifdef CONFIG_GENERIC_IRQ_DEBUGFS
372517 .debug_show = x86_vector_debug_show ,
373518#endif
@@ -531,13 +676,13 @@ static int apic_set_affinity(struct irq_data *irqd,
531676{
532677 int err ;
533678
534- if (! IS_ENABLED ( CONFIG_SMP ))
535- return - EPERM ;
536-
537- if (! cpumask_intersects ( dest , cpu_online_mask ))
538- return - EINVAL ;
539-
540- err = assign_irq_vector ( irqd , dest );
679+ raw_spin_lock ( & vector_lock );
680+ cpumask_and ( vector_searchmask , dest , cpu_online_mask ) ;
681+ if ( irqd_affinity_is_managed ( irqd ))
682+ err = assign_managed_vector ( irqd , vector_searchmask );
683+ else
684+ err = assign_vector_locked ( irqd , vector_searchmask );
685+ raw_spin_unlock ( & vector_lock );
541686 return err ? err : IRQ_SET_MASK_OK ;
542687}
543688
@@ -577,9 +722,18 @@ static void free_moved_vector(struct apic_chip_data *apicd)
577722{
578723 unsigned int vector = apicd -> prev_vector ;
579724 unsigned int cpu = apicd -> prev_cpu ;
725+ bool managed = apicd -> is_managed ;
726+
727+ /*
728+ * This should never happen. Managed interrupts are not
729+ * migrated except on CPU down, which does not involve the
730+ * cleanup vector. But try to keep the accounting correct
731+ * nevertheless.
732+ */
733+ WARN_ON_ONCE (managed );
580734
581- trace_vector_free_moved (apicd -> irq , vector , false );
582- irq_matrix_free (vector_matrix , cpu , vector , false );
735+ trace_vector_free_moved (apicd -> irq , vector , managed );
736+ irq_matrix_free (vector_matrix , cpu , vector , managed );
583737 __this_cpu_write (vector_irq [vector ], VECTOR_UNUSED );
584738 hlist_del_init (& apicd -> clist );
585739 apicd -> prev_vector = 0 ;
0 commit comments