1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * EDAC PCI component 4 * 5 * Author: Dave Jiang <djiang@mvista.com> 6 * 7 * 2007 (c) MontaVista Software, Inc. 8 */ 9 #include <asm/page.h> 10 #include <linux/uaccess.h> 11 #include <linux/ctype.h> 12 #include <linux/highmem.h> 13 #include <linux/init.h> 14 #include <linux/module.h> 15 #include <linux/slab.h> 16 #include <linux/smp.h> 17 #include <linux/spinlock.h> 18 #include <linux/sysctl.h> 19 #include <linux/timer.h> 20 21 #include "edac_pci.h" 22 #include "edac_module.h" 23 24 static DEFINE_MUTEX(edac_pci_ctls_mutex); 25 static LIST_HEAD(edac_pci_list); 26 static atomic_t pci_indexes = ATOMIC_INIT(0); 27 28 struct edac_pci_ctl_info *edac_pci_alloc_ctl_info(unsigned int sz_pvt, 29 const char *edac_pci_name) 30 { 31 struct edac_pci_ctl_info *pci; 32 33 edac_dbg(1, "\n"); 34 35 pci = kzalloc(sizeof(struct edac_pci_ctl_info), GFP_KERNEL); 36 if (!pci) 37 return NULL; 38 39 if (sz_pvt) { 40 pci->pvt_info = kzalloc(sz_pvt, GFP_KERNEL); 41 if (!pci->pvt_info) 42 goto free; 43 } 44 45 pci->op_state = OP_ALLOC; 46 47 snprintf(pci->name, strlen(edac_pci_name) + 1, "%s", edac_pci_name); 48 49 return pci; 50 51 free: 52 kfree(pci); 53 return NULL; 54 } 55 EXPORT_SYMBOL_GPL(edac_pci_alloc_ctl_info); 56 57 void edac_pci_free_ctl_info(struct edac_pci_ctl_info *pci) 58 { 59 edac_dbg(1, "\n"); 60 61 edac_pci_remove_sysfs(pci); 62 } 63 EXPORT_SYMBOL_GPL(edac_pci_free_ctl_info); 64 65 /* 66 * find_edac_pci_by_dev() 67 * scans the edac_pci list for a specific 'struct device *' 68 * 69 * return NULL if not found, or return control struct pointer 70 */ 71 static struct edac_pci_ctl_info *find_edac_pci_by_dev(struct device *dev) 72 { 73 struct edac_pci_ctl_info *pci; 74 struct list_head *item; 75 76 edac_dbg(1, "\n"); 77 78 list_for_each(item, &edac_pci_list) { 79 pci = list_entry(item, struct edac_pci_ctl_info, link); 80 81 if (pci->dev == dev) 82 return pci; 83 } 84 85 return NULL; 86 } 87 88 /* 89 * add_edac_pci_to_global_list 90 * Before calling this function, caller must assign a unique value to 91 * edac_dev->pci_idx. 92 * Return: 93 * 0 on success 94 * 1 on failure 95 */ 96 static int add_edac_pci_to_global_list(struct edac_pci_ctl_info *pci) 97 { 98 struct list_head *item, *insert_before; 99 struct edac_pci_ctl_info *rover; 100 101 edac_dbg(1, "\n"); 102 103 insert_before = &edac_pci_list; 104 105 /* Determine if already on the list */ 106 rover = find_edac_pci_by_dev(pci->dev); 107 if (unlikely(rover != NULL)) 108 goto fail0; 109 110 /* Insert in ascending order by 'pci_idx', so find position */ 111 list_for_each(item, &edac_pci_list) { 112 rover = list_entry(item, struct edac_pci_ctl_info, link); 113 114 if (rover->pci_idx >= pci->pci_idx) { 115 if (unlikely(rover->pci_idx == pci->pci_idx)) 116 goto fail1; 117 118 insert_before = item; 119 break; 120 } 121 } 122 123 list_add_tail_rcu(&pci->link, insert_before); 124 return 0; 125 126 fail0: 127 edac_printk(KERN_WARNING, EDAC_PCI, 128 "%s (%s) %s %s already assigned %d\n", 129 dev_name(rover->dev), edac_dev_name(rover), 130 rover->mod_name, rover->ctl_name, rover->pci_idx); 131 return 1; 132 133 fail1: 134 edac_printk(KERN_WARNING, EDAC_PCI, 135 "but in low-level driver: attempt to assign\n" 136 "\tduplicate pci_idx %d in %s()\n", rover->pci_idx, 137 __func__); 138 return 1; 139 } 140 141 /* 142 * del_edac_pci_from_global_list 143 * 144 * remove the PCI control struct from the global list 145 */ 146 static void del_edac_pci_from_global_list(struct edac_pci_ctl_info *pci) 147 { 148 list_del_rcu(&pci->link); 149 150 /* these are for safe removal of devices from global list while 151 * NMI handlers may be traversing list 152 */ 153 synchronize_rcu(); 154 INIT_LIST_HEAD(&pci->link); 155 } 156 157 /* 158 * edac_pci_workq_function() 159 * 160 * periodic function that performs the operation 161 * scheduled by a workq request, for a given PCI control struct 162 */ 163 static void edac_pci_workq_function(struct work_struct *work_req) 164 { 165 struct delayed_work *d_work = to_delayed_work(work_req); 166 struct edac_pci_ctl_info *pci = to_edac_pci_ctl_work(d_work); 167 int msec; 168 unsigned long delay; 169 170 edac_dbg(3, "checking\n"); 171 172 mutex_lock(&edac_pci_ctls_mutex); 173 174 if (pci->op_state != OP_RUNNING_POLL) { 175 mutex_unlock(&edac_pci_ctls_mutex); 176 return; 177 } 178 179 if (edac_pci_get_check_errors()) 180 pci->edac_check(pci); 181 182 /* if we are on a one second period, then use round */ 183 msec = edac_pci_get_poll_msec(); 184 if (msec == 1000) 185 delay = round_jiffies_relative(msecs_to_jiffies(msec)); 186 else 187 delay = msecs_to_jiffies(msec); 188 189 edac_queue_work(&pci->work, delay); 190 191 mutex_unlock(&edac_pci_ctls_mutex); 192 } 193 194 int edac_pci_alloc_index(void) 195 { 196 return atomic_inc_return(&pci_indexes) - 1; 197 } 198 EXPORT_SYMBOL_GPL(edac_pci_alloc_index); 199 200 int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx) 201 { 202 edac_dbg(0, "\n"); 203 204 pci->pci_idx = edac_idx; 205 pci->start_time = jiffies; 206 207 mutex_lock(&edac_pci_ctls_mutex); 208 209 if (add_edac_pci_to_global_list(pci)) 210 goto fail0; 211 212 if (edac_pci_create_sysfs(pci)) { 213 edac_pci_printk(pci, KERN_WARNING, 214 "failed to create sysfs pci\n"); 215 goto fail1; 216 } 217 218 if (pci->edac_check) { 219 pci->op_state = OP_RUNNING_POLL; 220 221 INIT_DELAYED_WORK(&pci->work, edac_pci_workq_function); 222 edac_queue_work(&pci->work, msecs_to_jiffies(edac_pci_get_poll_msec())); 223 224 } else { 225 pci->op_state = OP_RUNNING_INTERRUPT; 226 } 227 228 edac_pci_printk(pci, KERN_INFO, 229 "Giving out device to module %s controller %s: DEV %s (%s)\n", 230 pci->mod_name, pci->ctl_name, pci->dev_name, 231 edac_op_state_to_string(pci->op_state)); 232 233 mutex_unlock(&edac_pci_ctls_mutex); 234 return 0; 235 236 /* error unwind stack */ 237 fail1: 238 del_edac_pci_from_global_list(pci); 239 fail0: 240 mutex_unlock(&edac_pci_ctls_mutex); 241 return 1; 242 } 243 EXPORT_SYMBOL_GPL(edac_pci_add_device); 244 245 struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev) 246 { 247 struct edac_pci_ctl_info *pci; 248 249 edac_dbg(0, "\n"); 250 251 mutex_lock(&edac_pci_ctls_mutex); 252 253 /* ensure the control struct is on the global list 254 * if not, then leave 255 */ 256 pci = find_edac_pci_by_dev(dev); 257 if (pci == NULL) { 258 mutex_unlock(&edac_pci_ctls_mutex); 259 return NULL; 260 } 261 262 pci->op_state = OP_OFFLINE; 263 264 del_edac_pci_from_global_list(pci); 265 266 mutex_unlock(&edac_pci_ctls_mutex); 267 268 if (pci->edac_check) 269 edac_stop_work(&pci->work); 270 271 edac_printk(KERN_INFO, EDAC_PCI, 272 "Removed device %d for %s %s: DEV %s\n", 273 pci->pci_idx, pci->mod_name, pci->ctl_name, edac_dev_name(pci)); 274 275 return pci; 276 } 277 EXPORT_SYMBOL_GPL(edac_pci_del_device); 278 279 /* 280 * edac_pci_generic_check 281 * 282 * a Generic parity check API 283 */ 284 static void edac_pci_generic_check(struct edac_pci_ctl_info *pci) 285 { 286 edac_dbg(4, "\n"); 287 edac_pci_do_parity_check(); 288 } 289 290 /* free running instance index counter */ 291 static int edac_pci_idx; 292 #define EDAC_PCI_GENCTL_NAME "EDAC PCI controller" 293 294 struct edac_pci_gen_data { 295 int edac_idx; 296 }; 297 298 struct edac_pci_ctl_info *edac_pci_create_generic_ctl(struct device *dev, 299 const char *mod_name) 300 { 301 struct edac_pci_ctl_info *pci; 302 struct edac_pci_gen_data *pdata; 303 304 pci = edac_pci_alloc_ctl_info(sizeof(*pdata), EDAC_PCI_GENCTL_NAME); 305 if (!pci) 306 return NULL; 307 308 pdata = pci->pvt_info; 309 pci->dev = dev; 310 dev_set_drvdata(pci->dev, pci); 311 pci->dev_name = pci_name(to_pci_dev(dev)); 312 313 pci->mod_name = mod_name; 314 pci->ctl_name = EDAC_PCI_GENCTL_NAME; 315 if (edac_op_state == EDAC_OPSTATE_POLL) 316 pci->edac_check = edac_pci_generic_check; 317 318 pdata->edac_idx = edac_pci_idx++; 319 320 if (edac_pci_add_device(pci, pdata->edac_idx) > 0) { 321 edac_dbg(3, "failed edac_pci_add_device()\n"); 322 edac_pci_free_ctl_info(pci); 323 return NULL; 324 } 325 326 return pci; 327 } 328 EXPORT_SYMBOL_GPL(edac_pci_create_generic_ctl); 329 330 void edac_pci_release_generic_ctl(struct edac_pci_ctl_info *pci) 331 { 332 edac_dbg(0, "pci mod=%s\n", pci->mod_name); 333 334 edac_pci_del_device(pci->dev); 335 edac_pci_free_ctl_info(pci); 336 } 337 EXPORT_SYMBOL_GPL(edac_pci_release_generic_ctl); 338