1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include <linux/export.h>
26#include <linux/gfp.h>
27#include <linux/init.h>
28#include <linux/kernel.h>
29#include <linux/pci.h>
30#include <linux/string.h>
31
32#include <asm/pci-bridge.h>
33#include <asm/ppc-pci.h>
34
35static LIST_HEAD(eeh_phb_pe);
36
37
38
39
40
41
42
43
44static struct eeh_pe *eeh_pe_alloc(struct pci_controller *phb, int type)
45{
46 struct eeh_pe *pe;
47
48
49 pe = kzalloc(sizeof(struct eeh_pe), GFP_KERNEL);
50 if (!pe) return NULL;
51
52
53 pe->type = type;
54 pe->phb = phb;
55 INIT_LIST_HEAD(&pe->child_list);
56 INIT_LIST_HEAD(&pe->child);
57 INIT_LIST_HEAD(&pe->edevs);
58
59 return pe;
60}
61
62
63
64
65
66
67
68
69int eeh_phb_pe_create(struct pci_controller *phb)
70{
71 struct eeh_pe *pe;
72
73
74 pe = eeh_pe_alloc(phb, EEH_PE_PHB);
75 if (!pe) {
76 pr_err("%s: out of memory!\n", __func__);
77 return -ENOMEM;
78 }
79
80
81 eeh_lock();
82 list_add_tail(&pe->child, &eeh_phb_pe);
83 eeh_unlock();
84
85 pr_debug("EEH: Add PE for PHB#%d\n", phb->global_number);
86
87 return 0;
88}
89
90
91
92
93
94
95
96
97
98static struct eeh_pe *eeh_phb_pe_get(struct pci_controller *phb)
99{
100 struct eeh_pe *pe;
101
102 list_for_each_entry(pe, &eeh_phb_pe, child) {
103
104
105
106
107
108 if ((pe->type & EEH_PE_PHB) && pe->phb == phb)
109 return pe;
110 }
111
112 return NULL;
113}
114
115
116
117
118
119
120
121
122
123static struct eeh_pe *eeh_pe_next(struct eeh_pe *pe,
124 struct eeh_pe *root)
125{
126 struct list_head *next = pe->child_list.next;
127
128 if (next == &pe->child_list) {
129 while (1) {
130 if (pe == root)
131 return NULL;
132 next = pe->child.next;
133 if (next != &pe->parent->child_list)
134 break;
135 pe = pe->parent;
136 }
137 }
138
139 return list_entry(next, struct eeh_pe, child);
140}
141
142
143
144
145
146
147
148
149
150
151
152
153static void *eeh_pe_traverse(struct eeh_pe *root,
154 eeh_traverse_func fn, void *flag)
155{
156 struct eeh_pe *pe;
157 void *ret;
158
159 for (pe = root; pe; pe = eeh_pe_next(pe, root)) {
160 ret = fn(pe, flag);
161 if (ret) return ret;
162 }
163
164 return NULL;
165}
166
167
168
169
170
171
172
173
174
175
176void *eeh_pe_dev_traverse(struct eeh_pe *root,
177 eeh_traverse_func fn, void *flag)
178{
179 struct eeh_pe *pe;
180 struct eeh_dev *edev;
181 void *ret;
182
183 if (!root) {
184 pr_warning("%s: Invalid PE %p\n", __func__, root);
185 return NULL;
186 }
187
188 eeh_lock();
189
190
191 for (pe = root; pe; pe = eeh_pe_next(pe, root)) {
192 eeh_pe_for_each_dev(pe, edev) {
193 ret = fn(edev, flag);
194 if (ret) {
195 eeh_unlock();
196 return ret;
197 }
198 }
199 }
200
201 eeh_unlock();
202
203 return NULL;
204}
205
206
207
208
209
210
211
212
213
214
215
216static void *__eeh_pe_get(void *data, void *flag)
217{
218 struct eeh_pe *pe = (struct eeh_pe *)data;
219 struct eeh_dev *edev = (struct eeh_dev *)flag;
220
221
222 if (pe->type & EEH_PE_PHB)
223 return NULL;
224
225
226 if (edev->pe_config_addr &&
227 (edev->pe_config_addr == pe->addr))
228 return pe;
229
230
231 if (edev->pe_config_addr &&
232 (edev->config_addr == pe->config_addr))
233 return pe;
234
235 return NULL;
236}
237
238
239
240
241
242
243
244
245
246
247
248
249static struct eeh_pe *eeh_pe_get(struct eeh_dev *edev)
250{
251 struct eeh_pe *root = eeh_phb_pe_get(edev->phb);
252 struct eeh_pe *pe;
253
254 pe = eeh_pe_traverse(root, __eeh_pe_get, edev);
255
256 return pe;
257}
258
259
260
261
262
263
264
265
266
267static struct eeh_pe *eeh_pe_get_parent(struct eeh_dev *edev)
268{
269 struct device_node *dn;
270 struct eeh_dev *parent;
271
272
273
274
275
276
277 dn = edev->dn->parent;
278 while (dn) {
279
280 if (!PCI_DN(dn)) return NULL;
281
282 parent = of_node_to_eeh_dev(dn);
283
284 if (!parent) return NULL;
285
286 if (parent->pe)
287 return parent->pe;
288
289 dn = dn->parent;
290 }
291
292 return NULL;
293}
294
295
296
297
298
299
300
301
302
303
304int eeh_add_to_parent_pe(struct eeh_dev *edev)
305{
306 struct eeh_pe *pe, *parent;
307
308 eeh_lock();
309
310
311
312
313
314
315
316 pe = eeh_pe_get(edev);
317 if (pe && !(pe->type & EEH_PE_INVALID)) {
318 if (!edev->pe_config_addr) {
319 eeh_unlock();
320 pr_err("%s: PE with addr 0x%x already exists\n",
321 __func__, edev->config_addr);
322 return -EEXIST;
323 }
324
325
326 pe->type = EEH_PE_BUS;
327 edev->pe = pe;
328
329
330 list_add_tail(&edev->list, &pe->edevs);
331 eeh_unlock();
332 pr_debug("EEH: Add %s to Bus PE#%x\n",
333 edev->dn->full_name, pe->addr);
334
335 return 0;
336 } else if (pe && (pe->type & EEH_PE_INVALID)) {
337 list_add_tail(&edev->list, &pe->edevs);
338 edev->pe = pe;
339
340
341
342
343 parent = pe;
344 while (parent) {
345 if (!(parent->type & EEH_PE_INVALID))
346 break;
347 parent->type &= ~EEH_PE_INVALID;
348 parent = parent->parent;
349 }
350 eeh_unlock();
351 pr_debug("EEH: Add %s to Device PE#%x, Parent PE#%x\n",
352 edev->dn->full_name, pe->addr, pe->parent->addr);
353
354 return 0;
355 }
356
357
358 pe = eeh_pe_alloc(edev->phb, EEH_PE_DEVICE);
359 if (!pe) {
360 eeh_unlock();
361 pr_err("%s: out of memory!\n", __func__);
362 return -ENOMEM;
363 }
364 pe->addr = edev->pe_config_addr;
365 pe->config_addr = edev->config_addr;
366
367
368
369
370
371
372
373 parent = eeh_pe_get_parent(edev);
374 if (!parent) {
375 parent = eeh_phb_pe_get(edev->phb);
376 if (!parent) {
377 eeh_unlock();
378 pr_err("%s: No PHB PE is found (PHB Domain=%d)\n",
379 __func__, edev->phb->global_number);
380 edev->pe = NULL;
381 kfree(pe);
382 return -EEXIST;
383 }
384 }
385 pe->parent = parent;
386
387
388
389
390
391 list_add_tail(&pe->child, &parent->child_list);
392 list_add_tail(&edev->list, &pe->edevs);
393 edev->pe = pe;
394 eeh_unlock();
395 pr_debug("EEH: Add %s to Device PE#%x, Parent PE#%x\n",
396 edev->dn->full_name, pe->addr, pe->parent->addr);
397
398 return 0;
399}
400
401
402
403
404
405
406
407
408
409
410
411int eeh_rmv_from_parent_pe(struct eeh_dev *edev, int purge_pe)
412{
413 struct eeh_pe *pe, *parent, *child;
414 int cnt;
415
416 if (!edev->pe) {
417 pr_warning("%s: No PE found for EEH device %s\n",
418 __func__, edev->dn->full_name);
419 return -EEXIST;
420 }
421
422 eeh_lock();
423
424
425 pe = edev->pe;
426 edev->pe = NULL;
427 list_del(&edev->list);
428
429
430
431
432
433
434
435 while (1) {
436 parent = pe->parent;
437 if (pe->type & EEH_PE_PHB)
438 break;
439
440 if (purge_pe) {
441 if (list_empty(&pe->edevs) &&
442 list_empty(&pe->child_list)) {
443 list_del(&pe->child);
444 kfree(pe);
445 } else {
446 break;
447 }
448 } else {
449 if (list_empty(&pe->edevs)) {
450 cnt = 0;
451 list_for_each_entry(child, &pe->child_list, child) {
452 if (!(child->type & EEH_PE_INVALID)) {
453 cnt++;
454 break;
455 }
456 }
457
458 if (!cnt)
459 pe->type |= EEH_PE_INVALID;
460 else
461 break;
462 }
463 }
464
465 pe = parent;
466 }
467
468 eeh_unlock();
469
470 return 0;
471}
472
473
474
475
476
477
478
479
480
481
482static void *__eeh_pe_state_mark(void *data, void *flag)
483{
484 struct eeh_pe *pe = (struct eeh_pe *)data;
485 int state = *((int *)flag);
486 struct eeh_dev *tmp;
487 struct pci_dev *pdev;
488
489
490
491
492
493
494
495 pe->state |= state;
496 eeh_pe_for_each_dev(pe, tmp) {
497 pdev = eeh_dev_to_pci_dev(tmp);
498 if (pdev)
499 pdev->error_state = pci_channel_io_frozen;
500 }
501
502 return NULL;
503}
504
505
506
507
508
509
510
511
512
513void eeh_pe_state_mark(struct eeh_pe *pe, int state)
514{
515 eeh_lock();
516 eeh_pe_traverse(pe, __eeh_pe_state_mark, &state);
517 eeh_unlock();
518}
519
520
521
522
523
524
525
526
527
528
529static void *__eeh_pe_state_clear(void *data, void *flag)
530{
531 struct eeh_pe *pe = (struct eeh_pe *)data;
532 int state = *((int *)flag);
533
534 pe->state &= ~state;
535 pe->check_count = 0;
536
537 return NULL;
538}
539
540
541
542
543
544
545
546
547
548
549void eeh_pe_state_clear(struct eeh_pe *pe, int state)
550{
551 eeh_lock();
552 eeh_pe_traverse(pe, __eeh_pe_state_clear, &state);
553 eeh_unlock();
554}
555
556
557
558
559
560
561
562
563
564
565static void *eeh_restore_one_device_bars(void *data, void *flag)
566{
567 int i;
568 u32 cmd;
569 struct eeh_dev *edev = (struct eeh_dev *)data;
570 struct device_node *dn = eeh_dev_to_of_node(edev);
571
572 for (i = 4; i < 10; i++)
573 eeh_ops->write_config(dn, i*4, 4, edev->config_space[i]);
574
575 eeh_ops->write_config(dn, 12*4, 4, edev->config_space[12]);
576
577#define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF))
578#define SAVED_BYTE(OFF) (((u8 *)(edev->config_space))[BYTE_SWAP(OFF)])
579
580 eeh_ops->write_config(dn, PCI_CACHE_LINE_SIZE, 1,
581 SAVED_BYTE(PCI_CACHE_LINE_SIZE));
582 eeh_ops->write_config(dn, PCI_LATENCY_TIMER, 1,
583 SAVED_BYTE(PCI_LATENCY_TIMER));
584
585
586 eeh_ops->write_config(dn, 15*4, 4, edev->config_space[15]);
587
588
589
590
591
592 eeh_ops->read_config(dn, PCI_COMMAND, 4, &cmd);
593 if (edev->config_space[1] & PCI_COMMAND_PARITY)
594 cmd |= PCI_COMMAND_PARITY;
595 else
596 cmd &= ~PCI_COMMAND_PARITY;
597 if (edev->config_space[1] & PCI_COMMAND_SERR)
598 cmd |= PCI_COMMAND_SERR;
599 else
600 cmd &= ~PCI_COMMAND_SERR;
601 eeh_ops->write_config(dn, PCI_COMMAND, 4, cmd);
602
603 return NULL;
604}
605
606
607
608
609
610
611
612
613void eeh_pe_restore_bars(struct eeh_pe *pe)
614{
615
616
617
618
619 eeh_pe_dev_traverse(pe, eeh_restore_one_device_bars, NULL);
620}
621
622
623
624
625
626
627
628
629
630
631
632struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe)
633{
634 struct pci_bus *bus = NULL;
635 struct eeh_dev *edev;
636 struct pci_dev *pdev;
637
638 eeh_lock();
639
640 if (pe->type & EEH_PE_PHB) {
641 bus = pe->phb->bus;
642 } else if (pe->type & EEH_PE_BUS ||
643 pe->type & EEH_PE_DEVICE) {
644 edev = list_first_entry(&pe->edevs, struct eeh_dev, list);
645 pdev = eeh_dev_to_pci_dev(edev);
646 if (pdev)
647 bus = pdev->bus;
648 }
649
650 eeh_unlock();
651
652 return bus;
653}
654