| .. | .. |
|---|
| 34 | 34 | static DEFINE_MUTEX(device_ctls_mutex); |
|---|
| 35 | 35 | static LIST_HEAD(edac_device_list); |
|---|
| 36 | 36 | |
|---|
| 37 | +/* Default workqueue processing interval on this instance, in msecs */ |
|---|
| 38 | +#define DEFAULT_POLL_INTERVAL 1000 |
|---|
| 39 | + |
|---|
| 37 | 40 | #ifdef CONFIG_EDAC_DEBUG |
|---|
| 38 | 41 | static void edac_device_dump_device(struct edac_device_ctl_info *edac_dev) |
|---|
| 39 | 42 | { |
|---|
| .. | .. |
|---|
| 366 | 369 | * whole one second to save timers firing all over the period |
|---|
| 367 | 370 | * between integral seconds |
|---|
| 368 | 371 | */ |
|---|
| 369 | | - if (edac_dev->poll_msec == 1000) |
|---|
| 372 | + if (edac_dev->poll_msec == DEFAULT_POLL_INTERVAL) |
|---|
| 370 | 373 | edac_queue_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay)); |
|---|
| 371 | 374 | else |
|---|
| 372 | 375 | edac_queue_work(&edac_dev->work, edac_dev->delay); |
|---|
| .. | .. |
|---|
| 396 | 399 | * timers firing on sub-second basis, while they are happy |
|---|
| 397 | 400 | * to fire together on the 1 second exactly |
|---|
| 398 | 401 | */ |
|---|
| 399 | | - if (edac_dev->poll_msec == 1000) |
|---|
| 402 | + if (edac_dev->poll_msec == DEFAULT_POLL_INTERVAL) |
|---|
| 400 | 403 | edac_queue_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay)); |
|---|
| 401 | 404 | else |
|---|
| 402 | 405 | edac_queue_work(&edac_dev->work, edac_dev->delay); |
|---|
| .. | .. |
|---|
| 424 | 427 | * Then restart the workq on the new delay |
|---|
| 425 | 428 | */ |
|---|
| 426 | 429 | void edac_device_reset_delay_period(struct edac_device_ctl_info *edac_dev, |
|---|
| 427 | | - unsigned long value) |
|---|
| 430 | + unsigned long msec) |
|---|
| 428 | 431 | { |
|---|
| 429 | | - unsigned long jiffs = msecs_to_jiffies(value); |
|---|
| 432 | + edac_dev->poll_msec = msec; |
|---|
| 433 | + edac_dev->delay = msecs_to_jiffies(msec); |
|---|
| 430 | 434 | |
|---|
| 431 | | - if (value == 1000) |
|---|
| 432 | | - jiffs = round_jiffies_relative(value); |
|---|
| 433 | | - |
|---|
| 434 | | - edac_dev->poll_msec = value; |
|---|
| 435 | | - edac_dev->delay = jiffs; |
|---|
| 436 | | - |
|---|
| 437 | | - edac_mod_work(&edac_dev->work, jiffs); |
|---|
| 435 | + /* See comment in edac_device_workq_setup() above */ |
|---|
| 436 | + if (edac_dev->poll_msec == DEFAULT_POLL_INTERVAL) |
|---|
| 437 | + edac_mod_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay)); |
|---|
| 438 | + else |
|---|
| 439 | + edac_mod_work(&edac_dev->work, edac_dev->delay); |
|---|
| 438 | 440 | } |
|---|
| 439 | 441 | |
|---|
| 440 | 442 | int edac_device_alloc_index(void) |
|---|
| .. | .. |
|---|
| 473 | 475 | /* This instance is NOW RUNNING */ |
|---|
| 474 | 476 | edac_dev->op_state = OP_RUNNING_POLL; |
|---|
| 475 | 477 | |
|---|
| 476 | | - /* |
|---|
| 477 | | - * enable workq processing on this instance, |
|---|
| 478 | | - * default = 1000 msec |
|---|
| 479 | | - */ |
|---|
| 480 | | - edac_device_workq_setup(edac_dev, 1000); |
|---|
| 478 | + edac_device_workq_setup(edac_dev, edac_dev->poll_msec ?: DEFAULT_POLL_INTERVAL); |
|---|
| 481 | 479 | } else { |
|---|
| 482 | 480 | edac_dev->op_state = OP_RUNNING_INTERRUPT; |
|---|
| 483 | 481 | } |
|---|
| .. | .. |
|---|
| 555 | 553 | return edac_dev->panic_on_ue; |
|---|
| 556 | 554 | } |
|---|
| 557 | 555 | |
|---|
| 558 | | -void edac_device_handle_ce(struct edac_device_ctl_info *edac_dev, |
|---|
| 559 | | - int inst_nr, int block_nr, const char *msg) |
|---|
| 556 | +void edac_device_handle_ce_count(struct edac_device_ctl_info *edac_dev, |
|---|
| 557 | + unsigned int count, int inst_nr, int block_nr, |
|---|
| 558 | + const char *msg) |
|---|
| 560 | 559 | { |
|---|
| 561 | 560 | struct edac_device_instance *instance; |
|---|
| 562 | 561 | struct edac_device_block *block = NULL; |
|---|
| 562 | + |
|---|
| 563 | + if (!count) |
|---|
| 564 | + return; |
|---|
| 563 | 565 | |
|---|
| 564 | 566 | if ((inst_nr >= edac_dev->nr_instances) || (inst_nr < 0)) { |
|---|
| 565 | 567 | edac_device_printk(edac_dev, KERN_ERR, |
|---|
| .. | .. |
|---|
| 582 | 584 | |
|---|
| 583 | 585 | if (instance->nr_blocks > 0) { |
|---|
| 584 | 586 | block = instance->blocks + block_nr; |
|---|
| 585 | | - block->counters.ce_count++; |
|---|
| 587 | + block->counters.ce_count += count; |
|---|
| 586 | 588 | } |
|---|
| 587 | 589 | |
|---|
| 588 | 590 | /* Propagate the count up the 'totals' tree */ |
|---|
| 589 | | - instance->counters.ce_count++; |
|---|
| 590 | | - edac_dev->counters.ce_count++; |
|---|
| 591 | + instance->counters.ce_count += count; |
|---|
| 592 | + edac_dev->counters.ce_count += count; |
|---|
| 591 | 593 | |
|---|
| 592 | 594 | if (edac_device_get_log_ce(edac_dev)) |
|---|
| 593 | 595 | edac_device_printk(edac_dev, KERN_WARNING, |
|---|
| 594 | | - "CE: %s instance: %s block: %s '%s'\n", |
|---|
| 595 | | - edac_dev->ctl_name, instance->name, |
|---|
| 596 | | - block ? block->name : "N/A", msg); |
|---|
| 596 | + "CE: %s instance: %s block: %s count: %d '%s'\n", |
|---|
| 597 | + edac_dev->ctl_name, instance->name, |
|---|
| 598 | + block ? block->name : "N/A", count, msg); |
|---|
| 597 | 599 | } |
|---|
| 598 | | -EXPORT_SYMBOL_GPL(edac_device_handle_ce); |
|---|
| 600 | +EXPORT_SYMBOL_GPL(edac_device_handle_ce_count); |
|---|
| 599 | 601 | |
|---|
| 600 | | -void edac_device_handle_ue(struct edac_device_ctl_info *edac_dev, |
|---|
| 601 | | - int inst_nr, int block_nr, const char *msg) |
|---|
| 602 | +void edac_device_handle_ue_count(struct edac_device_ctl_info *edac_dev, |
|---|
| 603 | + unsigned int count, int inst_nr, int block_nr, |
|---|
| 604 | + const char *msg) |
|---|
| 602 | 605 | { |
|---|
| 603 | 606 | struct edac_device_instance *instance; |
|---|
| 604 | 607 | struct edac_device_block *block = NULL; |
|---|
| 608 | + |
|---|
| 609 | + if (!count) |
|---|
| 610 | + return; |
|---|
| 605 | 611 | |
|---|
| 606 | 612 | if ((inst_nr >= edac_dev->nr_instances) || (inst_nr < 0)) { |
|---|
| 607 | 613 | edac_device_printk(edac_dev, KERN_ERR, |
|---|
| .. | .. |
|---|
| 624 | 630 | |
|---|
| 625 | 631 | if (instance->nr_blocks > 0) { |
|---|
| 626 | 632 | block = instance->blocks + block_nr; |
|---|
| 627 | | - block->counters.ue_count++; |
|---|
| 633 | + block->counters.ue_count += count; |
|---|
| 628 | 634 | } |
|---|
| 629 | 635 | |
|---|
| 630 | 636 | /* Propagate the count up the 'totals' tree */ |
|---|
| 631 | | - instance->counters.ue_count++; |
|---|
| 632 | | - edac_dev->counters.ue_count++; |
|---|
| 637 | + instance->counters.ue_count += count; |
|---|
| 638 | + edac_dev->counters.ue_count += count; |
|---|
| 633 | 639 | |
|---|
| 634 | 640 | if (edac_device_get_log_ue(edac_dev)) |
|---|
| 635 | 641 | edac_device_printk(edac_dev, KERN_EMERG, |
|---|
| 636 | | - "UE: %s instance: %s block: %s '%s'\n", |
|---|
| 637 | | - edac_dev->ctl_name, instance->name, |
|---|
| 638 | | - block ? block->name : "N/A", msg); |
|---|
| 642 | + "UE: %s instance: %s block: %s count: %d '%s'\n", |
|---|
| 643 | + edac_dev->ctl_name, instance->name, |
|---|
| 644 | + block ? block->name : "N/A", count, msg); |
|---|
| 639 | 645 | |
|---|
| 640 | 646 | if (edac_device_get_panic_on_ue(edac_dev)) |
|---|
| 641 | | - panic("EDAC %s: UE instance: %s block %s '%s'\n", |
|---|
| 642 | | - edac_dev->ctl_name, instance->name, |
|---|
| 643 | | - block ? block->name : "N/A", msg); |
|---|
| 647 | + panic("EDAC %s: UE instance: %s block %s count: %d '%s'\n", |
|---|
| 648 | + edac_dev->ctl_name, instance->name, |
|---|
| 649 | + block ? block->name : "N/A", count, msg); |
|---|
| 644 | 650 | } |
|---|
| 645 | | -EXPORT_SYMBOL_GPL(edac_device_handle_ue); |
|---|
| 651 | +EXPORT_SYMBOL_GPL(edac_device_handle_ue_count); |
|---|