Skip to content

Commit bec0403

Browse files
douliyangKAGA-KOKO
authored andcommitted
genirq/core: Introduce struct irq_affinity_desc
The interrupt affinity management uses straight cpumask pointers to convey the automatically assigned affinity masks for managed interrupts. The core interrupt descriptor allocation also decides based on the pointer being non NULL whether an interrupt is managed or not. Devices which use managed interrupts usually have two classes of interrupts: - Interrupts for multiple device queues - Interrupts for general device management Currently both classes are treated the same way, i.e. as managed interrupts. The general interrupts get the default affinity mask assigned while the device queue interrupts are spread out over the possible CPUs. Treating the general interrupts as managed is both a limitation and under certain circumstances a bug. Assume the following situation: default_irq_affinity = 4..7 So if CPUs 4-7 are offlined, then the core code will shut down the device management interrupts because the last CPU in their affinity mask went offline. It's also a limitation because it's desired to allow manual placement of the general device interrupts for various reasons. If they are marked managed then the interrupt affinity setting from both user and kernel space is disabled. To remedy that situation it's required to convey more information than the cpumasks through various interfaces related to interrupt descriptor allocation. Instead of adding yet another argument, create a new data structure 'irq_affinity_desc' which for now just contains the cpumask. This struct can be expanded to convey auxilliary information in the next step. No functional change, just preparatory work. [ tglx: Simplified logic and clarified changelog ] Suggested-by: Thomas Gleixner <tglx@linutronix.de> Suggested-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Dou Liyang <douliyangs@gmail.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: linux-pci@vger.kernel.org Cc: kashyap.desai@broadcom.com Cc: shivasharan.srikanteshwara@broadcom.com Cc: sumit.saxena@broadcom.com Cc: ming.lei@redhat.com Cc: hch@lst.de Cc: douliyang1@huawei.com Link: https://lkml.kernel.org/r/20181204155122.6327-2-douliyangs@gmail.com
1 parent c2899c3 commit bec0403

File tree

10 files changed

+55
-39
lines changed

10 files changed

+55
-39
lines changed

drivers/pci/msi.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -534,14 +534,13 @@ static int populate_msi_sysfs(struct pci_dev *pdev)
534534
static struct msi_desc *
535535
msi_setup_entry(struct pci_dev *dev, int nvec, const struct irq_affinity *affd)
536536
{
537-
struct cpumask *masks = NULL;
537+
struct irq_affinity_desc *masks = NULL;
538538
struct msi_desc *entry;
539539
u16 control;
540540

541541
if (affd)
542542
masks = irq_create_affinity_masks(nvec, affd);
543543

544-
545544
/* MSI Entry Initialization */
546545
entry = alloc_msi_entry(&dev->dev, nvec, masks);
547546
if (!entry)
@@ -672,7 +671,7 @@ static int msix_setup_entries(struct pci_dev *dev, void __iomem *base,
672671
struct msix_entry *entries, int nvec,
673672
const struct irq_affinity *affd)
674673
{
675-
struct cpumask *curmsk, *masks = NULL;
674+
struct irq_affinity_desc *curmsk, *masks = NULL;
676675
struct msi_desc *entry;
677676
int ret, i;
678677

@@ -1264,7 +1263,7 @@ const struct cpumask *pci_irq_get_affinity(struct pci_dev *dev, int nr)
12641263

12651264
for_each_pci_msi_entry(entry, dev) {
12661265
if (i == nr)
1267-
return entry->affinity;
1266+
return &entry->affinity->mask;
12681267
i++;
12691268
}
12701269
WARN_ON_ONCE(1);
@@ -1276,7 +1275,7 @@ const struct cpumask *pci_irq_get_affinity(struct pci_dev *dev, int nr)
12761275
nr >= entry->nvec_used))
12771276
return NULL;
12781277

1279-
return &entry->affinity[nr];
1278+
return &entry->affinity[nr].mask;
12801279
} else {
12811280
return cpu_possible_mask;
12821281
}

include/linux/interrupt.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,14 @@ struct irq_affinity {
257257
int *sets;
258258
};
259259

260+
/**
261+
* struct irq_affinity_desc - Interrupt affinity descriptor
262+
* @mask: cpumask to hold the affinity assignment
263+
*/
264+
struct irq_affinity_desc {
265+
struct cpumask mask;
266+
};
267+
260268
#if defined(CONFIG_SMP)
261269

262270
extern cpumask_var_t irq_default_affinity;
@@ -303,7 +311,9 @@ extern int irq_set_affinity_hint(unsigned int irq, const struct cpumask *m);
303311
extern int
304312
irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify);
305313

306-
struct cpumask *irq_create_affinity_masks(int nvec, const struct irq_affinity *affd);
314+
struct irq_affinity_desc *
315+
irq_create_affinity_masks(int nvec, const struct irq_affinity *affd);
316+
307317
int irq_calc_affinity_vectors(int minvec, int maxvec, const struct irq_affinity *affd);
308318

309319
#else /* CONFIG_SMP */
@@ -337,7 +347,7 @@ irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify)
337347
return 0;
338348
}
339349

340-
static inline struct cpumask *
350+
static inline struct irq_affinity_desc *
341351
irq_create_affinity_masks(int nvec, const struct irq_affinity *affd)
342352
{
343353
return NULL;

include/linux/irq.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
struct seq_file;
2828
struct module;
2929
struct msi_msg;
30+
struct irq_affinity_desc;
3031
enum irqchip_irq_state;
3132

3233
/*
@@ -834,11 +835,12 @@ struct cpumask *irq_data_get_effective_affinity_mask(struct irq_data *d)
834835
unsigned int arch_dynirq_lower_bound(unsigned int from);
835836

836837
int __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
837-
struct module *owner, const struct cpumask *affinity);
838+
struct module *owner,
839+
const struct irq_affinity_desc *affinity);
838840

839841
int __devm_irq_alloc_descs(struct device *dev, int irq, unsigned int from,
840842
unsigned int cnt, int node, struct module *owner,
841-
const struct cpumask *affinity);
843+
const struct irq_affinity_desc *affinity);
842844

843845
/* use macros to avoid needing export.h for THIS_MODULE */
844846
#define irq_alloc_descs(irq, from, cnt, node) \

include/linux/irqdomain.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ struct irq_chip;
4343
struct irq_data;
4444
struct cpumask;
4545
struct seq_file;
46+
struct irq_affinity_desc;
4647

4748
/* Number of irqs reserved for a legacy isa controller */
4849
#define NUM_ISA_INTERRUPTS 16
@@ -266,7 +267,7 @@ extern bool irq_domain_check_msi_remap(void);
266267
extern void irq_set_default_host(struct irq_domain *host);
267268
extern int irq_domain_alloc_descs(int virq, unsigned int nr_irqs,
268269
irq_hw_number_t hwirq, int node,
269-
const struct cpumask *affinity);
270+
const struct irq_affinity_desc *affinity);
270271

271272
static inline struct fwnode_handle *of_node_to_fwnode(struct device_node *node)
272273
{
@@ -449,7 +450,8 @@ static inline struct irq_domain *irq_domain_add_hierarchy(struct irq_domain *par
449450

450451
extern int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base,
451452
unsigned int nr_irqs, int node, void *arg,
452-
bool realloc, const struct cpumask *affinity);
453+
bool realloc,
454+
const struct irq_affinity_desc *affinity);
453455
extern void irq_domain_free_irqs(unsigned int virq, unsigned int nr_irqs);
454456
extern int irq_domain_activate_irq(struct irq_data *irq_data, bool early);
455457
extern void irq_domain_deactivate_irq(struct irq_data *irq_data);

include/linux/msi.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ struct msi_desc {
7676
unsigned int nvec_used;
7777
struct device *dev;
7878
struct msi_msg msg;
79-
struct cpumask *affinity;
79+
struct irq_affinity_desc *affinity;
8080

8181
union {
8282
/* PCI MSI/X specific data */
@@ -138,7 +138,7 @@ static inline void pci_write_msi_msg(unsigned int irq, struct msi_msg *msg)
138138
#endif /* CONFIG_PCI_MSI */
139139

140140
struct msi_desc *alloc_msi_entry(struct device *dev, int nvec,
141-
const struct cpumask *affinity);
141+
const struct irq_affinity_desc *affinity);
142142
void free_msi_entry(struct msi_desc *entry);
143143
void __pci_read_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
144144
void __pci_write_msi_msg(struct msi_desc *entry, struct msi_msg *msg);

kernel/irq/affinity.c

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ static int __irq_build_affinity_masks(const struct irq_affinity *affd,
9999
cpumask_var_t *node_to_cpumask,
100100
const struct cpumask *cpu_mask,
101101
struct cpumask *nmsk,
102-
struct cpumask *masks)
102+
struct irq_affinity_desc *masks)
103103
{
104104
int n, nodes, cpus_per_vec, extra_vecs, done = 0;
105105
int last_affv = firstvec + numvecs;
@@ -117,7 +117,9 @@ static int __irq_build_affinity_masks(const struct irq_affinity *affd,
117117
*/
118118
if (numvecs <= nodes) {
119119
for_each_node_mask(n, nodemsk) {
120-
cpumask_or(masks + curvec, masks + curvec, node_to_cpumask[n]);
120+
cpumask_or(&masks[curvec].mask,
121+
&masks[curvec].mask,
122+
node_to_cpumask[n]);
121123
if (++curvec == last_affv)
122124
curvec = firstvec;
123125
}
@@ -150,7 +152,8 @@ static int __irq_build_affinity_masks(const struct irq_affinity *affd,
150152
cpus_per_vec++;
151153
--extra_vecs;
152154
}
153-
irq_spread_init_one(masks + curvec, nmsk, cpus_per_vec);
155+
irq_spread_init_one(&masks[curvec].mask, nmsk,
156+
cpus_per_vec);
154157
}
155158

156159
done += v;
@@ -173,7 +176,7 @@ static int __irq_build_affinity_masks(const struct irq_affinity *affd,
173176
static int irq_build_affinity_masks(const struct irq_affinity *affd,
174177
int startvec, int numvecs, int firstvec,
175178
cpumask_var_t *node_to_cpumask,
176-
struct cpumask *masks)
179+
struct irq_affinity_desc *masks)
177180
{
178181
int curvec = startvec, nr_present, nr_others;
179182
int ret = -ENOMEM;
@@ -226,15 +229,15 @@ static int irq_build_affinity_masks(const struct irq_affinity *affd,
226229
* @nvecs: The total number of vectors
227230
* @affd: Description of the affinity requirements
228231
*
229-
* Returns the masks pointer or NULL if allocation failed.
232+
* Returns the irq_affinity_desc pointer or NULL if allocation failed.
230233
*/
231-
struct cpumask *
234+
struct irq_affinity_desc *
232235
irq_create_affinity_masks(int nvecs, const struct irq_affinity *affd)
233236
{
234237
int affvecs = nvecs - affd->pre_vectors - affd->post_vectors;
235238
int curvec, usedvecs;
236239
cpumask_var_t *node_to_cpumask;
237-
struct cpumask *masks = NULL;
240+
struct irq_affinity_desc *masks = NULL;
238241
int i, nr_sets;
239242

240243
/*
@@ -254,8 +257,7 @@ irq_create_affinity_masks(int nvecs, const struct irq_affinity *affd)
254257

255258
/* Fill out vectors at the beginning that don't need affinity */
256259
for (curvec = 0; curvec < affd->pre_vectors; curvec++)
257-
cpumask_copy(masks + curvec, irq_default_affinity);
258-
260+
cpumask_copy(&masks[curvec].mask, irq_default_affinity);
259261
/*
260262
* Spread on present CPUs starting from affd->pre_vectors. If we
261263
* have multiple sets, build each sets affinity mask separately.
@@ -285,7 +287,7 @@ irq_create_affinity_masks(int nvecs, const struct irq_affinity *affd)
285287
else
286288
curvec = affd->pre_vectors + usedvecs;
287289
for (; curvec < nvecs; curvec++)
288-
cpumask_copy(masks + curvec, irq_default_affinity);
290+
cpumask_copy(&masks[curvec].mask, irq_default_affinity);
289291

290292
outnodemsk:
291293
free_node_to_cpumask(node_to_cpumask);

kernel/irq/devres.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ static void devm_irq_desc_release(struct device *dev, void *res)
169169
* @cnt: Number of consecutive irqs to allocate
170170
* @node: Preferred node on which the irq descriptor should be allocated
171171
* @owner: Owning module (can be NULL)
172-
* @affinity: Optional pointer to an affinity mask array of size @cnt
172+
* @affinity: Optional pointer to an irq_affinity_desc array of size @cnt
173173
* which hints where the irq descriptors should be allocated
174174
* and which default affinities to use
175175
*
@@ -179,7 +179,7 @@ static void devm_irq_desc_release(struct device *dev, void *res)
179179
*/
180180
int __devm_irq_alloc_descs(struct device *dev, int irq, unsigned int from,
181181
unsigned int cnt, int node, struct module *owner,
182-
const struct cpumask *affinity)
182+
const struct irq_affinity_desc *affinity)
183183
{
184184
struct irq_desc_devres *dr;
185185
int base;

kernel/irq/irqdesc.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -449,28 +449,29 @@ static void free_desc(unsigned int irq)
449449
}
450450

451451
static int alloc_descs(unsigned int start, unsigned int cnt, int node,
452-
const struct cpumask *affinity, struct module *owner)
452+
const struct irq_affinity_desc *affinity,
453+
struct module *owner)
453454
{
454-
const struct cpumask *mask = NULL;
455455
struct irq_desc *desc;
456456
unsigned int flags;
457457
int i;
458458

459459
/* Validate affinity mask(s) */
460460
if (affinity) {
461-
for (i = 0, mask = affinity; i < cnt; i++, mask++) {
462-
if (cpumask_empty(mask))
461+
for (i = 0; i < cnt; i++) {
462+
if (cpumask_empty(&affinity[i].mask))
463463
return -EINVAL;
464464
}
465465
}
466466

467467
flags = affinity ? IRQD_AFFINITY_MANAGED | IRQD_MANAGED_SHUTDOWN : 0;
468-
mask = NULL;
469468

470469
for (i = 0; i < cnt; i++) {
470+
const struct cpumask *mask = NULL;
471+
471472
if (affinity) {
472473
node = cpu_to_node(cpumask_first(affinity));
473-
mask = affinity;
474+
mask = &affinity->mask;
474475
affinity++;
475476
}
476477
desc = alloc_desc(start + i, node, flags, mask, owner);
@@ -575,7 +576,7 @@ static void free_desc(unsigned int irq)
575576
}
576577

577578
static inline int alloc_descs(unsigned int start, unsigned int cnt, int node,
578-
const struct cpumask *affinity,
579+
const struct irq_affinity_desc *affinity,
579580
struct module *owner)
580581
{
581582
u32 i;
@@ -705,7 +706,7 @@ EXPORT_SYMBOL_GPL(irq_free_descs);
705706
*/
706707
int __ref
707708
__irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
708-
struct module *owner, const struct cpumask *affinity)
709+
struct module *owner, const struct irq_affinity_desc *affinity)
709710
{
710711
int start, ret;
711712

kernel/irq/irqdomain.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -969,7 +969,7 @@ const struct irq_domain_ops irq_domain_simple_ops = {
969969
EXPORT_SYMBOL_GPL(irq_domain_simple_ops);
970970

971971
int irq_domain_alloc_descs(int virq, unsigned int cnt, irq_hw_number_t hwirq,
972-
int node, const struct cpumask *affinity)
972+
int node, const struct irq_affinity_desc *affinity)
973973
{
974974
unsigned int hint;
975975

@@ -1281,7 +1281,7 @@ int irq_domain_alloc_irqs_hierarchy(struct irq_domain *domain,
12811281
*/
12821282
int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base,
12831283
unsigned int nr_irqs, int node, void *arg,
1284-
bool realloc, const struct cpumask *affinity)
1284+
bool realloc, const struct irq_affinity_desc *affinity)
12851285
{
12861286
int i, ret, virq;
12871287

kernel/irq/msi.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@
2323
* @nvec: The number of vectors used in this entry
2424
* @affinity: Optional pointer to an affinity mask array size of @nvec
2525
*
26-
* If @affinity is not NULL then a an affinity array[@nvec] is allocated
27-
* and the affinity masks from @affinity are copied.
26+
* If @affinity is not NULL then an affinity array[@nvec] is allocated
27+
* and the affinity masks and flags from @affinity are copied.
2828
*/
29-
struct msi_desc *
30-
alloc_msi_entry(struct device *dev, int nvec, const struct cpumask *affinity)
29+
struct msi_desc *alloc_msi_entry(struct device *dev, int nvec,
30+
const struct irq_affinity_desc *affinity)
3131
{
3232
struct msi_desc *desc;
3333

0 commit comments

Comments
 (0)