aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/eeh_driver.c
diff options
context:
space:
mode:
authorGavin Shan <gwshan@linux.vnet.ibm.com>2014-09-29 22:39:07 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2014-09-30 03:15:18 -0400
commit5cfb20b96f624e9852c4f3f1c4397e81ca28d5aa (patch)
treeacf784a0da023e6ef83e60514e3ee3fa1fe30a53 /arch/powerpc/kernel/eeh_driver.c
parent93e8b36d7bf5c54f1c52d8b78e34f88e52a3dfa2 (diff)
powerpc/eeh: Emulate EEH recovery for VFIO devices
When enabling EEH functionality on passed through devices (PE) with VFIO, the devices in the PE would be removed permanently from guest side. In that case, the PE remains frozen state. When returning PE to host, or restarting the guest again, we had mechanism unfreezing the PE by clearing PESTA/B frozen bits. However, that's not enough for some adapters, which are indicated as following "lspci" shows. Those adapters require hot reset on the parent bus to bring their firmware back to workable state. Otherwise, those adaptrs won't be operative and the host (for returning case) or the guest will fail to load the drivers for those adapters without exception. 0000:01:00.0 Ethernet controller: Emulex Corporation OneConnect \ 10Gb NIC (be3) (rev 02) 0000:01:00.0 0200: 19a2:0710 (rev 02) 0001:03:00.0 Ethernet controller: Emulex Corporation OneConnect \ NIC (Lancer) (rev 10) 0001:03:00.0 0200: 10df:e220 (rev 10) The patch adds mechanism to emulate EEH recovery (for hot reset on parent PCI bus) on 3 gates to fix the issue: open/release one adapter of the PE, enable EEH functionality on one adapter of the PE. Reported-by: Murilo Fossa Vicentini <muvic@br.ibm.com> Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc/kernel/eeh_driver.c')
-rw-r--r--arch/powerpc/kernel/eeh_driver.c90
1 files changed, 86 insertions, 4 deletions
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c
index 948e6f99089f..3fd514f8e4b2 100644
--- a/arch/powerpc/kernel/eeh_driver.c
+++ b/arch/powerpc/kernel/eeh_driver.c
@@ -180,6 +180,22 @@ static bool eeh_dev_removed(struct eeh_dev *edev)
180 return false; 180 return false;
181} 181}
182 182
183static void *eeh_dev_save_state(void *data, void *userdata)
184{
185 struct eeh_dev *edev = data;
186 struct pci_dev *pdev;
187
188 if (!edev)
189 return NULL;
190
191 pdev = eeh_dev_to_pci_dev(edev);
192 if (!pdev)
193 return NULL;
194
195 pci_save_state(pdev);
196 return NULL;
197}
198
183/** 199/**
184 * eeh_report_error - Report pci error to each device driver 200 * eeh_report_error - Report pci error to each device driver
185 * @data: eeh device 201 * @data: eeh device
@@ -303,6 +319,22 @@ static void *eeh_report_reset(void *data, void *userdata)
303 return NULL; 319 return NULL;
304} 320}
305 321
322static void *eeh_dev_restore_state(void *data, void *userdata)
323{
324 struct eeh_dev *edev = data;
325 struct pci_dev *pdev;
326
327 if (!edev)
328 return NULL;
329
330 pdev = eeh_dev_to_pci_dev(edev);
331 if (!pdev)
332 return NULL;
333
334 pci_restore_state(pdev);
335 return NULL;
336}
337
306/** 338/**
307 * eeh_report_resume - Tell device to resume normal operations 339 * eeh_report_resume - Tell device to resume normal operations
308 * @data: eeh device 340 * @data: eeh device
@@ -450,10 +482,11 @@ static void *eeh_pe_detach_dev(void *data, void *userdata)
450static void *__eeh_clear_pe_frozen_state(void *data, void *flag) 482static void *__eeh_clear_pe_frozen_state(void *data, void *flag)
451{ 483{
452 struct eeh_pe *pe = (struct eeh_pe *)data; 484 struct eeh_pe *pe = (struct eeh_pe *)data;
485 bool *clear_sw_state = flag;
453 int i, rc = 1; 486 int i, rc = 1;
454 487
455 for (i = 0; rc && i < 3; i++) 488 for (i = 0; rc && i < 3; i++)
456 rc = eeh_unfreeze_pe(pe, false); 489 rc = eeh_unfreeze_pe(pe, clear_sw_state);
457 490
458 /* Stop immediately on any errors */ 491 /* Stop immediately on any errors */
459 if (rc) { 492 if (rc) {
@@ -465,17 +498,66 @@ static void *__eeh_clear_pe_frozen_state(void *data, void *flag)
465 return NULL; 498 return NULL;
466} 499}
467 500
468static int eeh_clear_pe_frozen_state(struct eeh_pe *pe) 501static int eeh_clear_pe_frozen_state(struct eeh_pe *pe,
502 bool clear_sw_state)
469{ 503{
470 void *rc; 504 void *rc;
471 505
472 rc = eeh_pe_traverse(pe, __eeh_clear_pe_frozen_state, NULL); 506 rc = eeh_pe_traverse(pe, __eeh_clear_pe_frozen_state, &clear_sw_state);
473 if (!rc) 507 if (!rc)
474 eeh_pe_state_clear(pe, EEH_PE_ISOLATED); 508 eeh_pe_state_clear(pe, EEH_PE_ISOLATED);
475 509
476 return rc ? -EIO : 0; 510 return rc ? -EIO : 0;
477} 511}
478 512
513int eeh_pe_reset_and_recover(struct eeh_pe *pe)
514{
515 int result, ret;
516
517 /* Bail if the PE is being recovered */
518 if (pe->state & EEH_PE_RECOVERING)
519 return 0;
520
521 /* Put the PE into recovery mode */
522 eeh_pe_state_mark(pe, EEH_PE_RECOVERING);
523
524 /* Save states */
525 eeh_pe_dev_traverse(pe, eeh_dev_save_state, NULL);
526
527 /* Report error */
528 eeh_pe_dev_traverse(pe, eeh_report_error, &result);
529
530 /* Issue reset */
531 eeh_pe_state_mark(pe, EEH_PE_RESET);
532 ret = eeh_reset_pe(pe);
533 if (ret) {
534 eeh_pe_state_clear(pe, EEH_PE_RECOVERING | EEH_PE_RESET);
535 return ret;
536 }
537 eeh_pe_state_clear(pe, EEH_PE_RESET);
538
539 /* Unfreeze the PE */
540 ret = eeh_clear_pe_frozen_state(pe, true);
541 if (ret) {
542 eeh_pe_state_clear(pe, EEH_PE_RECOVERING);
543 return ret;
544 }
545
546 /* Notify completion of reset */
547 eeh_pe_dev_traverse(pe, eeh_report_reset, &result);
548
549 /* Restore device state */
550 eeh_pe_dev_traverse(pe, eeh_dev_restore_state, NULL);
551
552 /* Resume */
553 eeh_pe_dev_traverse(pe, eeh_report_resume, NULL);
554
555 /* Clear recovery mode */
556 eeh_pe_state_clear(pe, EEH_PE_RECOVERING);
557
558 return 0;
559}
560
479/** 561/**
480 * eeh_reset_device - Perform actual reset of a pci slot 562 * eeh_reset_device - Perform actual reset of a pci slot
481 * @pe: EEH PE 563 * @pe: EEH PE
@@ -534,7 +616,7 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
534 eeh_pe_state_clear(pe, EEH_PE_RESET); 616 eeh_pe_state_clear(pe, EEH_PE_RESET);
535 617
536 /* Clear frozen state */ 618 /* Clear frozen state */
537 rc = eeh_clear_pe_frozen_state(pe); 619 rc = eeh_clear_pe_frozen_state(pe, false);
538 if (rc) 620 if (rc)
539 return rc; 621 return rc;
540 622