aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pcie/aer
diff options
context:
space:
mode:
authorHidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>2010-04-15 00:16:16 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2010-05-11 15:01:33 -0400
commit88da13bfabbffb8f89574eb168b9da9a0abc693f (patch)
tree0d618bd5c2ddab8ba03d9b0c21b3998f2928d282 /drivers/pci/pcie/aer
parent7c4ec94f72cefec1c1b42219469794a34864a1ee (diff)
PCI: aerdrv: rework get_e_source()
Current get_e_source() returns pointer to an element of array. However since it also progress consume counter, it is possible that the element is overwritten by newly produced data before the element is really consumed. This patch changes get_e_source() to copy contents of the element to address pointed by its caller. Once copied the element in array can be consumed. And relocate this function to more innocuous place. Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> Reviewed-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/pcie/aer')
-rw-r--r--drivers/pci/pcie/aer/aerdrv_core.c63
1 files changed, 31 insertions, 32 deletions
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index ca140580199c..210e53c2fdc1 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -555,32 +555,6 @@ static void handle_error_source(struct pcie_device *aerdev,
555} 555}
556 556
557/** 557/**
558 * get_e_source - retrieve an error source
559 * @rpc: pointer to the root port which holds an error
560 *
561 * Invoked by DPC handler to consume an error.
562 */
563static struct aer_err_source *get_e_source(struct aer_rpc *rpc)
564{
565 struct aer_err_source *e_source;
566 unsigned long flags;
567
568 /* Lock access to Root error producer/consumer index */
569 spin_lock_irqsave(&rpc->e_lock, flags);
570 if (rpc->prod_idx == rpc->cons_idx) {
571 spin_unlock_irqrestore(&rpc->e_lock, flags);
572 return NULL;
573 }
574 e_source = &rpc->e_sources[rpc->cons_idx];
575 rpc->cons_idx++;
576 if (rpc->cons_idx == AER_ERROR_SOURCES_MAX)
577 rpc->cons_idx = 0;
578 spin_unlock_irqrestore(&rpc->e_lock, flags);
579
580 return e_source;
581}
582
583/**
584 * get_device_error_info - read error status from dev and store it to info 558 * get_device_error_info - read error status from dev and store it to info
585 * @dev: pointer to the device expected to have a error record 559 * @dev: pointer to the device expected to have a error record
586 * @info: pointer to structure to store the error record 560 * @info: pointer to structure to store the error record
@@ -717,6 +691,34 @@ static void aer_isr_one_error(struct pcie_device *p_device,
717} 691}
718 692
719/** 693/**
694 * get_e_source - retrieve an error source
695 * @rpc: pointer to the root port which holds an error
696 * @e_src: pointer to store retrieved error source
697 *
698 * Return 1 if an error source is retrieved, otherwise 0.
699 *
700 * Invoked by DPC handler to consume an error.
701 */
702static int get_e_source(struct aer_rpc *rpc, struct aer_err_source *e_src)
703{
704 unsigned long flags;
705 int ret = 0;
706
707 /* Lock access to Root error producer/consumer index */
708 spin_lock_irqsave(&rpc->e_lock, flags);
709 if (rpc->prod_idx != rpc->cons_idx) {
710 *e_src = rpc->e_sources[rpc->cons_idx];
711 rpc->cons_idx++;
712 if (rpc->cons_idx == AER_ERROR_SOURCES_MAX)
713 rpc->cons_idx = 0;
714 ret = 1;
715 }
716 spin_unlock_irqrestore(&rpc->e_lock, flags);
717
718 return ret;
719}
720
721/**
720 * aer_isr - consume errors detected by root port 722 * aer_isr - consume errors detected by root port
721 * @work: definition of this work item 723 * @work: definition of this work item
722 * 724 *
@@ -726,14 +728,11 @@ void aer_isr(struct work_struct *work)
726{ 728{
727 struct aer_rpc *rpc = container_of(work, struct aer_rpc, dpc_handler); 729 struct aer_rpc *rpc = container_of(work, struct aer_rpc, dpc_handler);
728 struct pcie_device *p_device = rpc->rpd; 730 struct pcie_device *p_device = rpc->rpd;
729 struct aer_err_source *e_src; 731 struct aer_err_source e_src;
730 732
731 mutex_lock(&rpc->rpc_mutex); 733 mutex_lock(&rpc->rpc_mutex);
732 e_src = get_e_source(rpc); 734 while (get_e_source(rpc, &e_src))
733 while (e_src) { 735 aer_isr_one_error(p_device, &e_src);
734 aer_isr_one_error(p_device, e_src);
735 e_src = get_e_source(rpc);
736 }
737 mutex_unlock(&rpc->rpc_mutex); 736 mutex_unlock(&rpc->rpc_mutex);
738 737
739 wake_up(&rpc->wait_release); 738 wake_up(&rpc->wait_release);