diff options
Diffstat (limited to 'drivers/edac/edac_pci.c')
| -rw-r--r-- | drivers/edac/edac_pci.c | 95 |
1 files changed, 50 insertions, 45 deletions
diff --git a/drivers/edac/edac_pci.c b/drivers/edac/edac_pci.c index 32be43576a8..2cf44b4db80 100644 --- a/drivers/edac/edac_pci.c +++ b/drivers/edac/edac_pci.c @@ -19,7 +19,6 @@ #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/list.h> -#include <linux/sysdev.h> #include <linux/ctype.h> #include <linux/workqueue.h> #include <asm/uaccess.h> @@ -29,7 +28,8 @@ #include "edac_module.h" static DEFINE_MUTEX(edac_pci_ctls_mutex); -static struct list_head edac_pci_list = LIST_HEAD_INIT(edac_pci_list); +static LIST_HEAD(edac_pci_list); +static atomic_t pci_indexes = ATOMIC_INIT(0); /* * edac_pci_alloc_ctl_info @@ -42,13 +42,13 @@ struct edac_pci_ctl_info *edac_pci_alloc_ctl_info(unsigned int sz_pvt, const char *edac_pci_name) { struct edac_pci_ctl_info *pci; - void *pvt; + void *p = NULL, *pvt; unsigned int size; - debugf1("%s()\n", __func__); + edac_dbg(1, "\n"); - pci = (struct edac_pci_ctl_info *)0; - pvt = edac_align_ptr(&pci[1], sz_pvt); + pci = edac_align_ptr(&p, sizeof(*pci), 1); + pvt = edac_align_ptr(&p, 1, sz_pvt); size = ((unsigned long)pvt) + sz_pvt; /* Alloc the needed control struct memory */ @@ -80,7 +80,7 @@ EXPORT_SYMBOL_GPL(edac_pci_alloc_ctl_info); */ void edac_pci_free_ctl_info(struct edac_pci_ctl_info *pci) { - debugf1("%s()\n", __func__); + edac_dbg(1, "\n"); edac_pci_remove_sysfs(pci); } @@ -97,7 +97,7 @@ static struct edac_pci_ctl_info *find_edac_pci_by_dev(struct device *dev) struct edac_pci_ctl_info *pci; struct list_head *item; - debugf1("%s()\n", __func__); + edac_dbg(1, "\n"); list_for_each(item, &edac_pci_list) { pci = list_entry(item, struct edac_pci_ctl_info, link); @@ -122,7 +122,7 @@ static int add_edac_pci_to_global_list(struct edac_pci_ctl_info *pci) struct list_head *item, *insert_before; struct edac_pci_ctl_info *rover; - debugf1("%s()\n", __func__); + edac_dbg(1, "\n"); insert_before = &edac_pci_list; @@ -150,7 +150,7 @@ static int add_edac_pci_to_global_list(struct edac_pci_ctl_info *pci) fail0: edac_printk(KERN_WARNING, EDAC_PCI, "%s (%s) %s %s already assigned %d\n", - rover->dev->bus_id, dev_name(rover), + dev_name(rover->dev), edac_dev_name(rover), rover->mod_name, rover->ctl_name, rover->pci_idx); return 1; @@ -163,20 +163,6 @@ fail1: } /* - * complete_edac_pci_list_del - * - * RCU completion callback to indicate item is deleted - */ -static void complete_edac_pci_list_del(struct rcu_head *head) -{ - struct edac_pci_ctl_info *pci; - - pci = container_of(head, struct edac_pci_ctl_info, rcu); - INIT_LIST_HEAD(&pci->link); - complete(&pci->complete); -} - -/* * del_edac_pci_from_global_list * * remove the PCI control struct from the global list @@ -184,11 +170,17 @@ static void complete_edac_pci_list_del(struct rcu_head *head) static void del_edac_pci_from_global_list(struct edac_pci_ctl_info *pci) { list_del_rcu(&pci->link); - init_completion(&pci->complete); - call_rcu(&pci->rcu, complete_edac_pci_list_del); - wait_for_completion(&pci->complete); + + /* these are for safe removal of devices from global list while + * NMI handlers may be traversing list + */ + synchronize_rcu(); + INIT_LIST_HEAD(&pci->link); } +#if 0 +/* Older code, but might use in the future */ + /* * edac_pci_find() * Search for an edac_pci_ctl_info structure whose index is 'idx' @@ -219,6 +211,7 @@ struct edac_pci_ctl_info *edac_pci_find(int idx) return NULL; } EXPORT_SYMBOL_GPL(edac_pci_find); +#endif /* * edac_pci_workq_function() @@ -228,12 +221,12 @@ EXPORT_SYMBOL_GPL(edac_pci_find); */ static void edac_pci_workq_function(struct work_struct *work_req) { - struct delayed_work *d_work = (struct delayed_work *)work_req; + struct delayed_work *d_work = to_delayed_work(work_req); struct edac_pci_ctl_info *pci = to_edac_pci_ctl_work(d_work); int msec; unsigned long delay; - debugf3("%s() checking\n", __func__); + edac_dbg(3, "checking\n"); mutex_lock(&edac_pci_ctls_mutex); @@ -268,7 +261,7 @@ static void edac_pci_workq_function(struct work_struct *work_req) static void edac_pci_workq_setup(struct edac_pci_ctl_info *pci, unsigned int msec) { - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); INIT_DELAYED_WORK(&pci->work, edac_pci_workq_function); queue_delayed_work(edac_workqueue, &pci->work, @@ -283,7 +276,7 @@ static void edac_pci_workq_teardown(struct edac_pci_ctl_info *pci) { int status; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); status = cancel_delayed_work(&pci->work); if (status == 0) @@ -300,7 +293,7 @@ static void edac_pci_workq_teardown(struct edac_pci_ctl_info *pci) void edac_pci_reset_delay_period(struct edac_pci_ctl_info *pci, unsigned long value) { - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); edac_pci_workq_teardown(pci); @@ -314,6 +307,19 @@ void edac_pci_reset_delay_period(struct edac_pci_ctl_info *pci, EXPORT_SYMBOL_GPL(edac_pci_reset_delay_period); /* + * edac_pci_alloc_index: Allocate a unique PCI index number + * + * Return: + * allocated index number + * + */ +int edac_pci_alloc_index(void) +{ + return atomic_inc_return(&pci_indexes) - 1; +} +EXPORT_SYMBOL_GPL(edac_pci_alloc_index); + +/* * edac_pci_add_device: Insert the 'edac_dev' structure into the * edac_pci global list and create sysfs entries associated with * edac_pci structure. @@ -327,7 +333,7 @@ EXPORT_SYMBOL_GPL(edac_pci_reset_delay_period); */ int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx) { - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); pci->pci_idx = edac_idx; pci->start_time = jiffies; @@ -352,11 +358,9 @@ int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx) } edac_pci_printk(pci, KERN_INFO, - "Giving out device to module '%s' controller '%s':" - " DEV '%s' (%s)\n", - pci->mod_name, - pci->ctl_name, - dev_name(pci), edac_op_state_to_string(pci->op_state)); + "Giving out device to module %s controller %s: DEV %s (%s)\n", + pci->mod_name, pci->ctl_name, pci->dev_name, + edac_op_state_to_string(pci->op_state)); mutex_unlock(&edac_pci_ctls_mutex); return 0; @@ -387,7 +391,7 @@ struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev) { struct edac_pci_ctl_info *pci; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); mutex_lock(&edac_pci_ctls_mutex); @@ -411,7 +415,7 @@ struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev) edac_printk(KERN_INFO, EDAC_PCI, "Removed device %d for %s %s: DEV %s\n", - pci->pci_idx, pci->mod_name, pci->ctl_name, dev_name(pci)); + pci->pci_idx, pci->mod_name, pci->ctl_name, edac_dev_name(pci)); return pci; } @@ -422,9 +426,9 @@ EXPORT_SYMBOL_GPL(edac_pci_del_device); * * a Generic parity check API */ -void edac_pci_generic_check(struct edac_pci_ctl_info *pci) +static void edac_pci_generic_check(struct edac_pci_ctl_info *pci) { - debugf4("%s()\n", __func__); + edac_dbg(4, "\n"); edac_pci_do_parity_check(); } @@ -464,12 +468,13 @@ struct edac_pci_ctl_info *edac_pci_create_generic_ctl(struct device *dev, pci->mod_name = mod_name; pci->ctl_name = EDAC_PCI_GENCTL_NAME; - pci->edac_check = edac_pci_generic_check; + if (edac_op_state == EDAC_OPSTATE_POLL) + pci->edac_check = edac_pci_generic_check; pdata->edac_idx = edac_pci_idx++; if (edac_pci_add_device(pci, pdata->edac_idx) > 0) { - debugf3("%s(): failed edac_pci_add_device()\n", __func__); + edac_dbg(3, "failed edac_pci_add_device()\n"); edac_pci_free_ctl_info(pci); return NULL; } @@ -485,7 +490,7 @@ EXPORT_SYMBOL_GPL(edac_pci_create_generic_ctl); */ void edac_pci_release_generic_ctl(struct edac_pci_ctl_info *pci) { - debugf0("%s() pci mod=%s\n", __func__, pci->mod_name); + edac_dbg(0, "pci mod=%s\n", pci->mod_name); edac_pci_del_device(pci->dev); edac_pci_free_ctl_info(pci); |
