Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/edac/edac_device.c
26278 views
1
2
/*
3
* edac_device.c
4
* (C) 2007 www.douglaskthompson.com
5
*
6
* This file may be distributed under the terms of the
7
* GNU General Public License.
8
*
9
* Written by Doug Thompson <[email protected]>
10
*
11
* edac_device API implementation
12
* 19 Jan 2007
13
*/
14
15
#include <asm/page.h>
16
#include <linux/uaccess.h>
17
#include <linux/ctype.h>
18
#include <linux/highmem.h>
19
#include <linux/init.h>
20
#include <linux/jiffies.h>
21
#include <linux/module.h>
22
#include <linux/slab.h>
23
#include <linux/smp.h>
24
#include <linux/spinlock.h>
25
#include <linux/sysctl.h>
26
#include <linux/timer.h>
27
28
#include "edac_device.h"
29
#include "edac_module.h"
30
31
/* lock for the list: 'edac_device_list', manipulation of this list
32
* is protected by the 'device_ctls_mutex' lock
33
*/
34
static DEFINE_MUTEX(device_ctls_mutex);
35
static LIST_HEAD(edac_device_list);
36
37
/* Default workqueue processing interval on this instance, in msecs */
38
#define DEFAULT_POLL_INTERVAL 1000
39
40
#ifdef CONFIG_EDAC_DEBUG
41
static void edac_device_dump_device(struct edac_device_ctl_info *edac_dev)
42
{
43
edac_dbg(3, "\tedac_dev = %p dev_idx=%d\n",
44
edac_dev, edac_dev->dev_idx);
45
edac_dbg(4, "\tedac_dev->edac_check = %p\n", edac_dev->edac_check);
46
edac_dbg(3, "\tdev = %p\n", edac_dev->dev);
47
edac_dbg(3, "\tmod_name:ctl_name = %s:%s\n",
48
edac_dev->mod_name, edac_dev->ctl_name);
49
edac_dbg(3, "\tpvt_info = %p\n\n", edac_dev->pvt_info);
50
}
51
#endif /* CONFIG_EDAC_DEBUG */
52
53
/*
54
* @off_val: zero, 1, or other based offset
55
*/
56
struct edac_device_ctl_info *
57
edac_device_alloc_ctl_info(unsigned pvt_sz, char *dev_name, unsigned nr_instances,
58
char *blk_name, unsigned nr_blocks, unsigned off_val,
59
int device_index)
60
{
61
struct edac_device_block *dev_blk, *blk_p, *blk;
62
struct edac_device_instance *dev_inst, *inst;
63
struct edac_device_ctl_info *dev_ctl;
64
unsigned instance, block;
65
void *pvt;
66
int err;
67
68
edac_dbg(4, "instances=%d blocks=%d\n", nr_instances, nr_blocks);
69
70
dev_ctl = kzalloc(sizeof(struct edac_device_ctl_info), GFP_KERNEL);
71
if (!dev_ctl)
72
return NULL;
73
74
dev_inst = kcalloc(nr_instances, sizeof(struct edac_device_instance), GFP_KERNEL);
75
if (!dev_inst)
76
goto free;
77
78
dev_ctl->instances = dev_inst;
79
80
dev_blk = kcalloc(nr_instances * nr_blocks, sizeof(struct edac_device_block), GFP_KERNEL);
81
if (!dev_blk)
82
goto free;
83
84
dev_ctl->blocks = dev_blk;
85
86
if (pvt_sz) {
87
pvt = kzalloc(pvt_sz, GFP_KERNEL);
88
if (!pvt)
89
goto free;
90
91
dev_ctl->pvt_info = pvt;
92
}
93
94
dev_ctl->dev_idx = device_index;
95
dev_ctl->nr_instances = nr_instances;
96
97
/* Default logging of CEs and UEs */
98
dev_ctl->log_ce = 1;
99
dev_ctl->log_ue = 1;
100
101
/* Name of this edac device */
102
snprintf(dev_ctl->name, sizeof(dev_ctl->name),"%s", dev_name);
103
104
/* Initialize every Instance */
105
for (instance = 0; instance < nr_instances; instance++) {
106
inst = &dev_inst[instance];
107
inst->ctl = dev_ctl;
108
inst->nr_blocks = nr_blocks;
109
blk_p = &dev_blk[instance * nr_blocks];
110
inst->blocks = blk_p;
111
112
/* name of this instance */
113
snprintf(inst->name, sizeof(inst->name), "%s%u", dev_name, instance);
114
115
/* Initialize every block in each instance */
116
for (block = 0; block < nr_blocks; block++) {
117
blk = &blk_p[block];
118
blk->instance = inst;
119
snprintf(blk->name, sizeof(blk->name),
120
"%s%d", blk_name, block + off_val);
121
122
edac_dbg(4, "instance=%d inst_p=%p block=#%d block_p=%p name='%s'\n",
123
instance, inst, block, blk, blk->name);
124
}
125
}
126
127
/* Mark this instance as merely ALLOCATED */
128
dev_ctl->op_state = OP_ALLOC;
129
130
/*
131
* Initialize the 'root' kobj for the edac_device controller
132
*/
133
err = edac_device_register_sysfs_main_kobj(dev_ctl);
134
if (err)
135
goto free;
136
137
/* at this point, the root kobj is valid, and in order to
138
* 'free' the object, then the function:
139
* edac_device_unregister_sysfs_main_kobj() must be called
140
* which will perform kobj unregistration and the actual free
141
* will occur during the kobject callback operation
142
*/
143
144
return dev_ctl;
145
146
free:
147
__edac_device_free_ctl_info(dev_ctl);
148
149
return NULL;
150
}
151
EXPORT_SYMBOL_GPL(edac_device_alloc_ctl_info);
152
153
void edac_device_free_ctl_info(struct edac_device_ctl_info *ctl_info)
154
{
155
edac_device_unregister_sysfs_main_kobj(ctl_info);
156
}
157
EXPORT_SYMBOL_GPL(edac_device_free_ctl_info);
158
159
/*
160
* find_edac_device_by_dev
161
* scans the edac_device list for a specific 'struct device *'
162
*
163
* lock to be held prior to call: device_ctls_mutex
164
*
165
* Return:
166
* pointer to control structure managing 'dev'
167
* NULL if not found on list
168
*/
169
static struct edac_device_ctl_info *find_edac_device_by_dev(struct device *dev)
170
{
171
struct edac_device_ctl_info *edac_dev;
172
struct list_head *item;
173
174
edac_dbg(0, "\n");
175
176
list_for_each(item, &edac_device_list) {
177
edac_dev = list_entry(item, struct edac_device_ctl_info, link);
178
179
if (edac_dev->dev == dev)
180
return edac_dev;
181
}
182
183
return NULL;
184
}
185
186
/*
187
* add_edac_dev_to_global_list
188
* Before calling this function, caller must
189
* assign a unique value to edac_dev->dev_idx.
190
*
191
* lock to be held prior to call: device_ctls_mutex
192
*
193
* Return:
194
* 0 on success
195
* 1 on failure.
196
*/
197
static int add_edac_dev_to_global_list(struct edac_device_ctl_info *edac_dev)
198
{
199
struct list_head *item, *insert_before;
200
struct edac_device_ctl_info *rover;
201
202
insert_before = &edac_device_list;
203
204
/* Determine if already on the list */
205
rover = find_edac_device_by_dev(edac_dev->dev);
206
if (unlikely(rover != NULL))
207
goto fail0;
208
209
/* Insert in ascending order by 'dev_idx', so find position */
210
list_for_each(item, &edac_device_list) {
211
rover = list_entry(item, struct edac_device_ctl_info, link);
212
213
if (rover->dev_idx >= edac_dev->dev_idx) {
214
if (unlikely(rover->dev_idx == edac_dev->dev_idx))
215
goto fail1;
216
217
insert_before = item;
218
break;
219
}
220
}
221
222
list_add_tail_rcu(&edac_dev->link, insert_before);
223
return 0;
224
225
fail0:
226
edac_printk(KERN_WARNING, EDAC_MC,
227
"%s (%s) %s %s already assigned %d\n",
228
dev_name(rover->dev), edac_dev_name(rover),
229
rover->mod_name, rover->ctl_name, rover->dev_idx);
230
return 1;
231
232
fail1:
233
edac_printk(KERN_WARNING, EDAC_MC,
234
"bug in low-level driver: attempt to assign\n"
235
" duplicate dev_idx %d in %s()\n", rover->dev_idx,
236
__func__);
237
return 1;
238
}
239
240
/*
241
* del_edac_device_from_global_list
242
*/
243
static void del_edac_device_from_global_list(struct edac_device_ctl_info
244
*edac_device)
245
{
246
list_del_rcu(&edac_device->link);
247
248
/* these are for safe removal of devices from global list while
249
* NMI handlers may be traversing list
250
*/
251
synchronize_rcu();
252
INIT_LIST_HEAD(&edac_device->link);
253
}
254
255
/*
256
* edac_device_workq_function
257
* performs the operation scheduled by a workq request
258
*
259
* this workq is embedded within an edac_device_ctl_info
260
* structure, that needs to be polled for possible error events.
261
*
262
* This operation is to acquire the list mutex lock
263
* (thus preventing insertation or deletion)
264
* and then call the device's poll function IFF this device is
265
* running polled and there is a poll function defined.
266
*/
267
static void edac_device_workq_function(struct work_struct *work_req)
268
{
269
struct delayed_work *d_work = to_delayed_work(work_req);
270
struct edac_device_ctl_info *edac_dev = to_edac_device_ctl_work(d_work);
271
272
mutex_lock(&device_ctls_mutex);
273
274
/* If we are being removed, bail out immediately */
275
if (edac_dev->op_state == OP_OFFLINE) {
276
mutex_unlock(&device_ctls_mutex);
277
return;
278
}
279
280
/* Only poll controllers that are running polled and have a check */
281
if ((edac_dev->op_state == OP_RUNNING_POLL) &&
282
(edac_dev->edac_check != NULL)) {
283
edac_dev->edac_check(edac_dev);
284
}
285
286
mutex_unlock(&device_ctls_mutex);
287
288
/* Reschedule the workq for the next time period to start again
289
* if the number of msec is for 1 sec, then adjust to the next
290
* whole one second to save timers firing all over the period
291
* between integral seconds
292
*/
293
if (edac_dev->poll_msec == DEFAULT_POLL_INTERVAL)
294
edac_queue_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay));
295
else
296
edac_queue_work(&edac_dev->work, edac_dev->delay);
297
}
298
299
/*
300
* edac_device_workq_setup
301
* initialize a workq item for this edac_device instance
302
* passing in the new delay period in msec
303
*/
304
static void edac_device_workq_setup(struct edac_device_ctl_info *edac_dev,
305
unsigned msec)
306
{
307
edac_dbg(0, "\n");
308
309
/* take the arg 'msec' and set it into the control structure
310
* to used in the time period calculation
311
* then calc the number of jiffies that represents
312
*/
313
edac_dev->poll_msec = msec;
314
edac_dev->delay = msecs_to_jiffies(msec);
315
316
INIT_DELAYED_WORK(&edac_dev->work, edac_device_workq_function);
317
318
/* optimize here for the 1 second case, which will be normal value, to
319
* fire ON the 1 second time event. This helps reduce all sorts of
320
* timers firing on sub-second basis, while they are happy
321
* to fire together on the 1 second exactly
322
*/
323
if (edac_dev->poll_msec == DEFAULT_POLL_INTERVAL)
324
edac_queue_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay));
325
else
326
edac_queue_work(&edac_dev->work, edac_dev->delay);
327
}
328
329
/*
330
* edac_device_workq_teardown
331
* stop the workq processing on this edac_dev
332
*/
333
static void edac_device_workq_teardown(struct edac_device_ctl_info *edac_dev)
334
{
335
if (!edac_dev->edac_check)
336
return;
337
338
edac_dev->op_state = OP_OFFLINE;
339
340
edac_stop_work(&edac_dev->work);
341
}
342
343
/*
344
* edac_device_reset_delay_period
345
*
346
* need to stop any outstanding workq queued up at this time
347
* because we will be resetting the sleep time.
348
* Then restart the workq on the new delay
349
*/
350
void edac_device_reset_delay_period(struct edac_device_ctl_info *edac_dev,
351
unsigned long msec)
352
{
353
edac_dev->poll_msec = msec;
354
edac_dev->delay = msecs_to_jiffies(msec);
355
356
/* See comment in edac_device_workq_setup() above */
357
if (edac_dev->poll_msec == DEFAULT_POLL_INTERVAL)
358
edac_mod_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay));
359
else
360
edac_mod_work(&edac_dev->work, edac_dev->delay);
361
}
362
363
int edac_device_alloc_index(void)
364
{
365
static atomic_t device_indexes = ATOMIC_INIT(0);
366
367
return atomic_inc_return(&device_indexes) - 1;
368
}
369
EXPORT_SYMBOL_GPL(edac_device_alloc_index);
370
371
int edac_device_add_device(struct edac_device_ctl_info *edac_dev)
372
{
373
edac_dbg(0, "\n");
374
375
#ifdef CONFIG_EDAC_DEBUG
376
if (edac_debug_level >= 3)
377
edac_device_dump_device(edac_dev);
378
#endif
379
mutex_lock(&device_ctls_mutex);
380
381
if (add_edac_dev_to_global_list(edac_dev))
382
goto fail0;
383
384
/* set load time so that error rate can be tracked */
385
edac_dev->start_time = jiffies;
386
387
/* create this instance's sysfs entries */
388
if (edac_device_create_sysfs(edac_dev)) {
389
edac_device_printk(edac_dev, KERN_WARNING,
390
"failed to create sysfs device\n");
391
goto fail1;
392
}
393
394
/* If there IS a check routine, then we are running POLLED */
395
if (edac_dev->edac_check != NULL) {
396
/* This instance is NOW RUNNING */
397
edac_dev->op_state = OP_RUNNING_POLL;
398
399
edac_device_workq_setup(edac_dev, edac_dev->poll_msec ?: DEFAULT_POLL_INTERVAL);
400
} else {
401
edac_dev->op_state = OP_RUNNING_INTERRUPT;
402
}
403
404
/* Report action taken */
405
edac_device_printk(edac_dev, KERN_INFO,
406
"Giving out device to module %s controller %s: DEV %s (%s)\n",
407
edac_dev->mod_name, edac_dev->ctl_name, edac_dev->dev_name,
408
edac_op_state_to_string(edac_dev->op_state));
409
410
mutex_unlock(&device_ctls_mutex);
411
return 0;
412
413
fail1:
414
/* Some error, so remove the entry from the lsit */
415
del_edac_device_from_global_list(edac_dev);
416
417
fail0:
418
mutex_unlock(&device_ctls_mutex);
419
return 1;
420
}
421
EXPORT_SYMBOL_GPL(edac_device_add_device);
422
423
struct edac_device_ctl_info *edac_device_del_device(struct device *dev)
424
{
425
struct edac_device_ctl_info *edac_dev;
426
427
edac_dbg(0, "\n");
428
429
mutex_lock(&device_ctls_mutex);
430
431
/* Find the structure on the list, if not there, then leave */
432
edac_dev = find_edac_device_by_dev(dev);
433
if (edac_dev == NULL) {
434
mutex_unlock(&device_ctls_mutex);
435
return NULL;
436
}
437
438
/* mark this instance as OFFLINE */
439
edac_dev->op_state = OP_OFFLINE;
440
441
/* deregister from global list */
442
del_edac_device_from_global_list(edac_dev);
443
444
mutex_unlock(&device_ctls_mutex);
445
446
/* clear workq processing on this instance */
447
edac_device_workq_teardown(edac_dev);
448
449
/* Tear down the sysfs entries for this instance */
450
edac_device_remove_sysfs(edac_dev);
451
452
edac_printk(KERN_INFO, EDAC_MC,
453
"Removed device %d for %s %s: DEV %s\n",
454
edac_dev->dev_idx,
455
edac_dev->mod_name, edac_dev->ctl_name, edac_dev_name(edac_dev));
456
457
return edac_dev;
458
}
459
EXPORT_SYMBOL_GPL(edac_device_del_device);
460
461
static inline int edac_device_get_log_ce(struct edac_device_ctl_info *edac_dev)
462
{
463
return edac_dev->log_ce;
464
}
465
466
static inline int edac_device_get_log_ue(struct edac_device_ctl_info *edac_dev)
467
{
468
return edac_dev->log_ue;
469
}
470
471
static inline int edac_device_get_panic_on_ue(struct edac_device_ctl_info
472
*edac_dev)
473
{
474
return edac_dev->panic_on_ue;
475
}
476
477
void edac_device_handle_ce_count(struct edac_device_ctl_info *edac_dev,
478
unsigned int count, int inst_nr, int block_nr,
479
const char *msg)
480
{
481
struct edac_device_instance *instance;
482
struct edac_device_block *block = NULL;
483
484
if (!count)
485
return;
486
487
if ((inst_nr >= edac_dev->nr_instances) || (inst_nr < 0)) {
488
edac_device_printk(edac_dev, KERN_ERR,
489
"INTERNAL ERROR: 'instance' out of range "
490
"(%d >= %d)\n", inst_nr,
491
edac_dev->nr_instances);
492
return;
493
}
494
495
instance = edac_dev->instances + inst_nr;
496
497
if ((block_nr >= instance->nr_blocks) || (block_nr < 0)) {
498
edac_device_printk(edac_dev, KERN_ERR,
499
"INTERNAL ERROR: instance %d 'block' "
500
"out of range (%d >= %d)\n",
501
inst_nr, block_nr,
502
instance->nr_blocks);
503
return;
504
}
505
506
if (instance->nr_blocks > 0) {
507
block = instance->blocks + block_nr;
508
block->counters.ce_count += count;
509
}
510
511
/* Propagate the count up the 'totals' tree */
512
instance->counters.ce_count += count;
513
edac_dev->counters.ce_count += count;
514
515
if (edac_device_get_log_ce(edac_dev))
516
edac_device_printk(edac_dev, KERN_WARNING,
517
"CE: %s instance: %s block: %s count: %d '%s'\n",
518
edac_dev->ctl_name, instance->name,
519
block ? block->name : "N/A", count, msg);
520
}
521
EXPORT_SYMBOL_GPL(edac_device_handle_ce_count);
522
523
void edac_device_handle_ue_count(struct edac_device_ctl_info *edac_dev,
524
unsigned int count, int inst_nr, int block_nr,
525
const char *msg)
526
{
527
struct edac_device_instance *instance;
528
struct edac_device_block *block = NULL;
529
530
if (!count)
531
return;
532
533
if ((inst_nr >= edac_dev->nr_instances) || (inst_nr < 0)) {
534
edac_device_printk(edac_dev, KERN_ERR,
535
"INTERNAL ERROR: 'instance' out of range "
536
"(%d >= %d)\n", inst_nr,
537
edac_dev->nr_instances);
538
return;
539
}
540
541
instance = edac_dev->instances + inst_nr;
542
543
if ((block_nr >= instance->nr_blocks) || (block_nr < 0)) {
544
edac_device_printk(edac_dev, KERN_ERR,
545
"INTERNAL ERROR: instance %d 'block' "
546
"out of range (%d >= %d)\n",
547
inst_nr, block_nr,
548
instance->nr_blocks);
549
return;
550
}
551
552
if (instance->nr_blocks > 0) {
553
block = instance->blocks + block_nr;
554
block->counters.ue_count += count;
555
}
556
557
/* Propagate the count up the 'totals' tree */
558
instance->counters.ue_count += count;
559
edac_dev->counters.ue_count += count;
560
561
if (edac_device_get_log_ue(edac_dev))
562
edac_device_printk(edac_dev, KERN_EMERG,
563
"UE: %s instance: %s block: %s count: %d '%s'\n",
564
edac_dev->ctl_name, instance->name,
565
block ? block->name : "N/A", count, msg);
566
567
if (edac_device_get_panic_on_ue(edac_dev))
568
panic("EDAC %s: UE instance: %s block %s count: %d '%s'\n",
569
edac_dev->ctl_name, instance->name,
570
block ? block->name : "N/A", count, msg);
571
}
572
EXPORT_SYMBOL_GPL(edac_device_handle_ue_count);
573
574
static void edac_dev_release(struct device *dev)
575
{
576
struct edac_dev_feat_ctx *ctx = container_of(dev, struct edac_dev_feat_ctx, dev);
577
578
kfree(ctx->mem_repair);
579
kfree(ctx->scrub);
580
kfree(ctx->dev.groups);
581
kfree(ctx);
582
}
583
584
static const struct device_type edac_dev_type = {
585
.name = "edac_dev",
586
.release = edac_dev_release,
587
};
588
589
static void edac_dev_unreg(void *data)
590
{
591
device_unregister(data);
592
}
593
594
/**
595
* edac_dev_register - register device for RAS features with EDAC
596
* @parent: parent device.
597
* @name: name for the folder in the /sys/bus/edac/devices/,
598
* which is derived from the parent device.
599
* For e.g. /sys/bus/edac/devices/cxl_mem0/
600
* @private: parent driver's data to store in the context if any.
601
* @num_features: number of RAS features to register.
602
* @ras_features: list of RAS features to register.
603
*
604
* Return:
605
* * %0 - Success.
606
* * %-EINVAL - Invalid parameters passed.
607
* * %-ENOMEM - Dynamic memory allocation failed.
608
*
609
*/
610
int edac_dev_register(struct device *parent, char *name,
611
void *private, int num_features,
612
const struct edac_dev_feature *ras_features)
613
{
614
const struct attribute_group **ras_attr_groups;
615
struct edac_dev_data *dev_data;
616
struct edac_dev_feat_ctx *ctx;
617
int mem_repair_cnt = 0;
618
int attr_gcnt = 0;
619
int ret = -ENOMEM;
620
int scrub_cnt = 0;
621
int feat;
622
623
if (!parent || !name || !num_features || !ras_features)
624
return -EINVAL;
625
626
/* Double parse to make space for attributes */
627
for (feat = 0; feat < num_features; feat++) {
628
switch (ras_features[feat].ft_type) {
629
case RAS_FEAT_SCRUB:
630
attr_gcnt++;
631
scrub_cnt++;
632
break;
633
case RAS_FEAT_ECS:
634
attr_gcnt += ras_features[feat].ecs_info.num_media_frus;
635
break;
636
case RAS_FEAT_MEM_REPAIR:
637
attr_gcnt++;
638
mem_repair_cnt++;
639
break;
640
default:
641
return -EINVAL;
642
}
643
}
644
645
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
646
if (!ctx)
647
return -ENOMEM;
648
649
ras_attr_groups = kcalloc(attr_gcnt + 1, sizeof(*ras_attr_groups), GFP_KERNEL);
650
if (!ras_attr_groups)
651
goto ctx_free;
652
653
if (scrub_cnt) {
654
ctx->scrub = kcalloc(scrub_cnt, sizeof(*ctx->scrub), GFP_KERNEL);
655
if (!ctx->scrub)
656
goto groups_free;
657
}
658
659
if (mem_repair_cnt) {
660
ctx->mem_repair = kcalloc(mem_repair_cnt, sizeof(*ctx->mem_repair), GFP_KERNEL);
661
if (!ctx->mem_repair)
662
goto data_mem_free;
663
}
664
665
attr_gcnt = 0;
666
scrub_cnt = 0;
667
mem_repair_cnt = 0;
668
for (feat = 0; feat < num_features; feat++, ras_features++) {
669
switch (ras_features->ft_type) {
670
case RAS_FEAT_SCRUB:
671
if (!ras_features->scrub_ops || scrub_cnt != ras_features->instance) {
672
ret = -EINVAL;
673
goto data_mem_free;
674
}
675
676
dev_data = &ctx->scrub[scrub_cnt];
677
dev_data->instance = scrub_cnt;
678
dev_data->scrub_ops = ras_features->scrub_ops;
679
dev_data->private = ras_features->ctx;
680
ret = edac_scrub_get_desc(parent, &ras_attr_groups[attr_gcnt],
681
ras_features->instance);
682
if (ret)
683
goto data_mem_free;
684
685
scrub_cnt++;
686
attr_gcnt++;
687
break;
688
case RAS_FEAT_ECS:
689
if (!ras_features->ecs_ops) {
690
ret = -EINVAL;
691
goto data_mem_free;
692
}
693
694
dev_data = &ctx->ecs;
695
dev_data->ecs_ops = ras_features->ecs_ops;
696
dev_data->private = ras_features->ctx;
697
ret = edac_ecs_get_desc(parent, &ras_attr_groups[attr_gcnt],
698
ras_features->ecs_info.num_media_frus);
699
if (ret)
700
goto data_mem_free;
701
702
attr_gcnt += ras_features->ecs_info.num_media_frus;
703
break;
704
case RAS_FEAT_MEM_REPAIR:
705
if (!ras_features->mem_repair_ops ||
706
mem_repair_cnt != ras_features->instance) {
707
ret = -EINVAL;
708
goto data_mem_free;
709
}
710
711
dev_data = &ctx->mem_repair[mem_repair_cnt];
712
dev_data->instance = mem_repair_cnt;
713
dev_data->mem_repair_ops = ras_features->mem_repair_ops;
714
dev_data->private = ras_features->ctx;
715
ret = edac_mem_repair_get_desc(parent, &ras_attr_groups[attr_gcnt],
716
ras_features->instance);
717
if (ret)
718
goto data_mem_free;
719
720
mem_repair_cnt++;
721
attr_gcnt++;
722
break;
723
default:
724
ret = -EINVAL;
725
goto data_mem_free;
726
}
727
}
728
729
ctx->dev.parent = parent;
730
ctx->dev.bus = edac_get_sysfs_subsys();
731
ctx->dev.type = &edac_dev_type;
732
ctx->dev.groups = ras_attr_groups;
733
ctx->private = private;
734
dev_set_drvdata(&ctx->dev, ctx);
735
736
ret = dev_set_name(&ctx->dev, "%s", name);
737
if (ret)
738
goto data_mem_free;
739
740
ret = device_register(&ctx->dev);
741
if (ret) {
742
put_device(&ctx->dev);
743
return ret;
744
}
745
746
return devm_add_action_or_reset(parent, edac_dev_unreg, &ctx->dev);
747
748
data_mem_free:
749
kfree(ctx->mem_repair);
750
kfree(ctx->scrub);
751
groups_free:
752
kfree(ras_attr_groups);
753
ctx_free:
754
kfree(ctx);
755
return ret;
756
}
757
EXPORT_SYMBOL_GPL(edac_dev_register);
758
759