0001
0002
0003
0004
0005
0006 #include <linux/interrupt.h>
0007 #include <linux/kernel.h>
0008 #include <linux/slab.h>
0009 #include <linux/cpu.h>
0010 #include <linux/sort.h>
0011
0012 static void irq_spread_init_one(struct cpumask *irqmsk, struct cpumask *nmsk,
0013 unsigned int cpus_per_vec)
0014 {
0015 const struct cpumask *siblmsk;
0016 int cpu, sibl;
0017
0018 for ( ; cpus_per_vec > 0; ) {
0019 cpu = cpumask_first(nmsk);
0020
0021
0022 if (cpu >= nr_cpu_ids)
0023 return;
0024
0025 cpumask_clear_cpu(cpu, nmsk);
0026 cpumask_set_cpu(cpu, irqmsk);
0027 cpus_per_vec--;
0028
0029
0030 siblmsk = topology_sibling_cpumask(cpu);
0031 for (sibl = -1; cpus_per_vec > 0; ) {
0032 sibl = cpumask_next(sibl, siblmsk);
0033 if (sibl >= nr_cpu_ids)
0034 break;
0035 if (!cpumask_test_and_clear_cpu(sibl, nmsk))
0036 continue;
0037 cpumask_set_cpu(sibl, irqmsk);
0038 cpus_per_vec--;
0039 }
0040 }
0041 }
0042
0043 static cpumask_var_t *alloc_node_to_cpumask(void)
0044 {
0045 cpumask_var_t *masks;
0046 int node;
0047
0048 masks = kcalloc(nr_node_ids, sizeof(cpumask_var_t), GFP_KERNEL);
0049 if (!masks)
0050 return NULL;
0051
0052 for (node = 0; node < nr_node_ids; node++) {
0053 if (!zalloc_cpumask_var(&masks[node], GFP_KERNEL))
0054 goto out_unwind;
0055 }
0056
0057 return masks;
0058
0059 out_unwind:
0060 while (--node >= 0)
0061 free_cpumask_var(masks[node]);
0062 kfree(masks);
0063 return NULL;
0064 }
0065
0066 static void free_node_to_cpumask(cpumask_var_t *masks)
0067 {
0068 int node;
0069
0070 for (node = 0; node < nr_node_ids; node++)
0071 free_cpumask_var(masks[node]);
0072 kfree(masks);
0073 }
0074
0075 static void build_node_to_cpumask(cpumask_var_t *masks)
0076 {
0077 int cpu;
0078
0079 for_each_possible_cpu(cpu)
0080 cpumask_set_cpu(cpu, masks[cpu_to_node(cpu)]);
0081 }
0082
0083 static int get_nodes_in_cpumask(cpumask_var_t *node_to_cpumask,
0084 const struct cpumask *mask, nodemask_t *nodemsk)
0085 {
0086 int n, nodes = 0;
0087
0088
0089 for_each_node(n) {
0090 if (cpumask_intersects(mask, node_to_cpumask[n])) {
0091 node_set(n, *nodemsk);
0092 nodes++;
0093 }
0094 }
0095 return nodes;
0096 }
0097
0098 struct node_vectors {
0099 unsigned id;
0100
0101 union {
0102 unsigned nvectors;
0103 unsigned ncpus;
0104 };
0105 };
0106
0107 static int ncpus_cmp_func(const void *l, const void *r)
0108 {
0109 const struct node_vectors *ln = l;
0110 const struct node_vectors *rn = r;
0111
0112 return ln->ncpus - rn->ncpus;
0113 }
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128 static void alloc_nodes_vectors(unsigned int numvecs,
0129 cpumask_var_t *node_to_cpumask,
0130 const struct cpumask *cpu_mask,
0131 const nodemask_t nodemsk,
0132 struct cpumask *nmsk,
0133 struct node_vectors *node_vectors)
0134 {
0135 unsigned n, remaining_ncpus = 0;
0136
0137 for (n = 0; n < nr_node_ids; n++) {
0138 node_vectors[n].id = n;
0139 node_vectors[n].ncpus = UINT_MAX;
0140 }
0141
0142 for_each_node_mask(n, nodemsk) {
0143 unsigned ncpus;
0144
0145 cpumask_and(nmsk, cpu_mask, node_to_cpumask[n]);
0146 ncpus = cpumask_weight(nmsk);
0147
0148 if (!ncpus)
0149 continue;
0150 remaining_ncpus += ncpus;
0151 node_vectors[n].ncpus = ncpus;
0152 }
0153
0154 numvecs = min_t(unsigned, remaining_ncpus, numvecs);
0155
0156 sort(node_vectors, nr_node_ids, sizeof(node_vectors[0]),
0157 ncpus_cmp_func, NULL);
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227 for (n = 0; n < nr_node_ids; n++) {
0228 unsigned nvectors, ncpus;
0229
0230 if (node_vectors[n].ncpus == UINT_MAX)
0231 continue;
0232
0233 WARN_ON_ONCE(numvecs == 0);
0234
0235 ncpus = node_vectors[n].ncpus;
0236 nvectors = max_t(unsigned, 1,
0237 numvecs * ncpus / remaining_ncpus);
0238 WARN_ON_ONCE(nvectors > ncpus);
0239
0240 node_vectors[n].nvectors = nvectors;
0241
0242 remaining_ncpus -= ncpus;
0243 numvecs -= nvectors;
0244 }
0245 }
0246
0247 static int __irq_build_affinity_masks(unsigned int startvec,
0248 unsigned int numvecs,
0249 unsigned int firstvec,
0250 cpumask_var_t *node_to_cpumask,
0251 const struct cpumask *cpu_mask,
0252 struct cpumask *nmsk,
0253 struct irq_affinity_desc *masks)
0254 {
0255 unsigned int i, n, nodes, cpus_per_vec, extra_vecs, done = 0;
0256 unsigned int last_affv = firstvec + numvecs;
0257 unsigned int curvec = startvec;
0258 nodemask_t nodemsk = NODE_MASK_NONE;
0259 struct node_vectors *node_vectors;
0260
0261 if (cpumask_empty(cpu_mask))
0262 return 0;
0263
0264 nodes = get_nodes_in_cpumask(node_to_cpumask, cpu_mask, &nodemsk);
0265
0266
0267
0268
0269
0270 if (numvecs <= nodes) {
0271 for_each_node_mask(n, nodemsk) {
0272
0273 cpumask_and(nmsk, cpu_mask, node_to_cpumask[n]);
0274 cpumask_or(&masks[curvec].mask, &masks[curvec].mask, nmsk);
0275 if (++curvec == last_affv)
0276 curvec = firstvec;
0277 }
0278 return numvecs;
0279 }
0280
0281 node_vectors = kcalloc(nr_node_ids,
0282 sizeof(struct node_vectors),
0283 GFP_KERNEL);
0284 if (!node_vectors)
0285 return -ENOMEM;
0286
0287
0288 alloc_nodes_vectors(numvecs, node_to_cpumask, cpu_mask,
0289 nodemsk, nmsk, node_vectors);
0290
0291 for (i = 0; i < nr_node_ids; i++) {
0292 unsigned int ncpus, v;
0293 struct node_vectors *nv = &node_vectors[i];
0294
0295 if (nv->nvectors == UINT_MAX)
0296 continue;
0297
0298
0299 cpumask_and(nmsk, cpu_mask, node_to_cpumask[nv->id]);
0300 ncpus = cpumask_weight(nmsk);
0301 if (!ncpus)
0302 continue;
0303
0304 WARN_ON_ONCE(nv->nvectors > ncpus);
0305
0306
0307 extra_vecs = ncpus - nv->nvectors * (ncpus / nv->nvectors);
0308
0309
0310 for (v = 0; v < nv->nvectors; v++, curvec++) {
0311 cpus_per_vec = ncpus / nv->nvectors;
0312
0313
0314 if (extra_vecs) {
0315 cpus_per_vec++;
0316 --extra_vecs;
0317 }
0318
0319
0320
0321
0322
0323 if (curvec >= last_affv)
0324 curvec = firstvec;
0325 irq_spread_init_one(&masks[curvec].mask, nmsk,
0326 cpus_per_vec);
0327 }
0328 done += nv->nvectors;
0329 }
0330 kfree(node_vectors);
0331 return done;
0332 }
0333
0334
0335
0336
0337
0338
0339 static int irq_build_affinity_masks(unsigned int startvec, unsigned int numvecs,
0340 unsigned int firstvec,
0341 struct irq_affinity_desc *masks)
0342 {
0343 unsigned int curvec = startvec, nr_present = 0, nr_others = 0;
0344 cpumask_var_t *node_to_cpumask;
0345 cpumask_var_t nmsk, npresmsk;
0346 int ret = -ENOMEM;
0347
0348 if (!zalloc_cpumask_var(&nmsk, GFP_KERNEL))
0349 return ret;
0350
0351 if (!zalloc_cpumask_var(&npresmsk, GFP_KERNEL))
0352 goto fail_nmsk;
0353
0354 node_to_cpumask = alloc_node_to_cpumask();
0355 if (!node_to_cpumask)
0356 goto fail_npresmsk;
0357
0358
0359 cpus_read_lock();
0360 build_node_to_cpumask(node_to_cpumask);
0361
0362
0363 ret = __irq_build_affinity_masks(curvec, numvecs, firstvec,
0364 node_to_cpumask, cpu_present_mask,
0365 nmsk, masks);
0366 if (ret < 0)
0367 goto fail_build_affinity;
0368 nr_present = ret;
0369
0370
0371
0372
0373
0374
0375
0376 if (nr_present >= numvecs)
0377 curvec = firstvec;
0378 else
0379 curvec = firstvec + nr_present;
0380 cpumask_andnot(npresmsk, cpu_possible_mask, cpu_present_mask);
0381 ret = __irq_build_affinity_masks(curvec, numvecs, firstvec,
0382 node_to_cpumask, npresmsk, nmsk,
0383 masks);
0384 if (ret >= 0)
0385 nr_others = ret;
0386
0387 fail_build_affinity:
0388 cpus_read_unlock();
0389
0390 if (ret >= 0)
0391 WARN_ON(nr_present + nr_others < numvecs);
0392
0393 free_node_to_cpumask(node_to_cpumask);
0394
0395 fail_npresmsk:
0396 free_cpumask_var(npresmsk);
0397
0398 fail_nmsk:
0399 free_cpumask_var(nmsk);
0400 return ret < 0 ? ret : 0;
0401 }
0402
0403 static void default_calc_sets(struct irq_affinity *affd, unsigned int affvecs)
0404 {
0405 affd->nr_sets = 1;
0406 affd->set_size[0] = affvecs;
0407 }
0408
0409
0410
0411
0412
0413
0414
0415
0416 struct irq_affinity_desc *
0417 irq_create_affinity_masks(unsigned int nvecs, struct irq_affinity *affd)
0418 {
0419 unsigned int affvecs, curvec, usedvecs, i;
0420 struct irq_affinity_desc *masks = NULL;
0421
0422
0423
0424
0425
0426
0427
0428 if (nvecs > affd->pre_vectors + affd->post_vectors)
0429 affvecs = nvecs - affd->pre_vectors - affd->post_vectors;
0430 else
0431 affvecs = 0;
0432
0433
0434
0435
0436
0437 if (!affd->calc_sets)
0438 affd->calc_sets = default_calc_sets;
0439
0440
0441 affd->calc_sets(affd, affvecs);
0442
0443 if (WARN_ON_ONCE(affd->nr_sets > IRQ_AFFINITY_MAX_SETS))
0444 return NULL;
0445
0446
0447 if (!affvecs)
0448 return NULL;
0449
0450 masks = kcalloc(nvecs, sizeof(*masks), GFP_KERNEL);
0451 if (!masks)
0452 return NULL;
0453
0454
0455 for (curvec = 0; curvec < affd->pre_vectors; curvec++)
0456 cpumask_copy(&masks[curvec].mask, irq_default_affinity);
0457
0458
0459
0460
0461
0462 for (i = 0, usedvecs = 0; i < affd->nr_sets; i++) {
0463 unsigned int this_vecs = affd->set_size[i];
0464 int ret;
0465
0466 ret = irq_build_affinity_masks(curvec, this_vecs,
0467 curvec, masks);
0468 if (ret) {
0469 kfree(masks);
0470 return NULL;
0471 }
0472 curvec += this_vecs;
0473 usedvecs += this_vecs;
0474 }
0475
0476
0477 if (usedvecs >= affvecs)
0478 curvec = affd->pre_vectors + affvecs;
0479 else
0480 curvec = affd->pre_vectors + usedvecs;
0481 for (; curvec < nvecs; curvec++)
0482 cpumask_copy(&masks[curvec].mask, irq_default_affinity);
0483
0484
0485 for (i = affd->pre_vectors; i < nvecs - affd->post_vectors; i++)
0486 masks[i].is_managed = 1;
0487
0488 return masks;
0489 }
0490
0491
0492
0493
0494
0495
0496
0497 unsigned int irq_calc_affinity_vectors(unsigned int minvec, unsigned int maxvec,
0498 const struct irq_affinity *affd)
0499 {
0500 unsigned int resv = affd->pre_vectors + affd->post_vectors;
0501 unsigned int set_vecs;
0502
0503 if (resv > minvec)
0504 return 0;
0505
0506 if (affd->calc_sets) {
0507 set_vecs = maxvec - resv;
0508 } else {
0509 cpus_read_lock();
0510 set_vecs = cpumask_weight(cpu_possible_mask);
0511 cpus_read_unlock();
0512 }
0513
0514 return resv + min(set_vecs, maxvec - resv);
0515 }