diff options
| -rw-r--r-- | drivers/dma/dmaengine.c | 55 |
1 files changed, 27 insertions, 28 deletions
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 9e56745f87bf..e428cf2a458b 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c | |||
| @@ -376,20 +376,30 @@ void dma_issue_pending_all(void) | |||
| 376 | EXPORT_SYMBOL(dma_issue_pending_all); | 376 | EXPORT_SYMBOL(dma_issue_pending_all); |
| 377 | 377 | ||
| 378 | /** | 378 | /** |
| 379 | * nth_chan - returns the nth channel of the given capability | 379 | * dma_chan_is_local - returns true if the channel is in the same numa-node as the cpu |
| 380 | */ | ||
| 381 | static bool dma_chan_is_local(struct dma_chan *chan, int cpu) | ||
| 382 | { | ||
| 383 | int node = dev_to_node(chan->device->dev); | ||
| 384 | return node == -1 || cpumask_test_cpu(cpu, cpumask_of_node(node)); | ||
| 385 | } | ||
| 386 | |||
| 387 | /** | ||
| 388 | * min_chan - returns the channel with min count and in the same numa-node as the cpu | ||
| 380 | * @cap: capability to match | 389 | * @cap: capability to match |
| 381 | * @n: nth channel desired | 390 | * @cpu: cpu index which the channel should be close to |
| 382 | * | 391 | * |
| 383 | * Defaults to returning the channel with the desired capability and the | 392 | * If some channels are close to the given cpu, the one with the lowest |
| 384 | * lowest reference count when 'n' cannot be satisfied. Must be called | 393 | * reference count is returned. Otherwise, cpu is ignored and only the |
| 385 | * under dma_list_mutex. | 394 | * reference count is taken into account. |
| 395 | * Must be called under dma_list_mutex. | ||
| 386 | */ | 396 | */ |
| 387 | static struct dma_chan *nth_chan(enum dma_transaction_type cap, int n) | 397 | static struct dma_chan *min_chan(enum dma_transaction_type cap, int cpu) |
| 388 | { | 398 | { |
| 389 | struct dma_device *device; | 399 | struct dma_device *device; |
| 390 | struct dma_chan *chan; | 400 | struct dma_chan *chan; |
| 391 | struct dma_chan *ret = NULL; | ||
| 392 | struct dma_chan *min = NULL; | 401 | struct dma_chan *min = NULL; |
| 402 | struct dma_chan *localmin = NULL; | ||
| 393 | 403 | ||
| 394 | list_for_each_entry(device, &dma_device_list, global_node) { | 404 | list_for_each_entry(device, &dma_device_list, global_node) { |
| 395 | if (!dma_has_cap(cap, device->cap_mask) || | 405 | if (!dma_has_cap(cap, device->cap_mask) || |
| @@ -398,27 +408,22 @@ static struct dma_chan *nth_chan(enum dma_transaction_type cap, int n) | |||
| 398 | list_for_each_entry(chan, &device->channels, device_node) { | 408 | list_for_each_entry(chan, &device->channels, device_node) { |
| 399 | if (!chan->client_count) | 409 | if (!chan->client_count) |
| 400 | continue; | 410 | continue; |
| 401 | if (!min) | 411 | if (!min || chan->table_count < min->table_count) |
| 402 | min = chan; | ||
| 403 | else if (chan->table_count < min->table_count) | ||
| 404 | min = chan; | 412 | min = chan; |
| 405 | 413 | ||
| 406 | if (n-- == 0) { | 414 | if (dma_chan_is_local(chan, cpu)) |
| 407 | ret = chan; | 415 | if (!localmin || |
| 408 | break; /* done */ | 416 | chan->table_count < localmin->table_count) |
| 409 | } | 417 | localmin = chan; |
| 410 | } | 418 | } |
| 411 | if (ret) | ||
| 412 | break; /* done */ | ||
| 413 | } | 419 | } |
| 414 | 420 | ||
| 415 | if (!ret) | 421 | chan = localmin ? localmin : min; |
| 416 | ret = min; | ||
| 417 | 422 | ||
| 418 | if (ret) | 423 | if (chan) |
| 419 | ret->table_count++; | 424 | chan->table_count++; |
| 420 | 425 | ||
| 421 | return ret; | 426 | return chan; |
| 422 | } | 427 | } |
| 423 | 428 | ||
| 424 | /** | 429 | /** |
| @@ -435,7 +440,6 @@ static void dma_channel_rebalance(void) | |||
| 435 | struct dma_device *device; | 440 | struct dma_device *device; |
| 436 | int cpu; | 441 | int cpu; |
| 437 | int cap; | 442 | int cap; |
| 438 | int n; | ||
| 439 | 443 | ||
| 440 | /* undo the last distribution */ | 444 | /* undo the last distribution */ |
| 441 | for_each_dma_cap_mask(cap, dma_cap_mask_all) | 445 | for_each_dma_cap_mask(cap, dma_cap_mask_all) |
| @@ -454,14 +458,9 @@ static void dma_channel_rebalance(void) | |||
| 454 | return; | 458 | return; |
| 455 | 459 | ||
| 456 | /* redistribute available channels */ | 460 | /* redistribute available channels */ |
| 457 | n = 0; | ||
| 458 | for_each_dma_cap_mask(cap, dma_cap_mask_all) | 461 | for_each_dma_cap_mask(cap, dma_cap_mask_all) |
| 459 | for_each_online_cpu(cpu) { | 462 | for_each_online_cpu(cpu) { |
| 460 | if (num_possible_cpus() > 1) | 463 | chan = min_chan(cap, cpu); |
| 461 | chan = nth_chan(cap, n++); | ||
| 462 | else | ||
| 463 | chan = nth_chan(cap, -1); | ||
| 464 | |||
| 465 | per_cpu_ptr(channel_table[cap], cpu)->chan = chan; | 464 | per_cpu_ptr(channel_table[cap], cpu)->chan = chan; |
| 466 | } | 465 | } |
| 467 | } | 466 | } |
