diff options
-rw-r--r-- | drivers/net/ethernet/intel/fm10k/fm10k_iov.c | 48 |
1 files changed, 28 insertions, 20 deletions
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_iov.c b/drivers/net/ethernet/intel/fm10k/fm10k_iov.c index 74160c2095ee..5d4f1761dc0c 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_iov.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_iov.c | |||
@@ -303,6 +303,28 @@ void fm10k_iov_suspend(struct pci_dev *pdev) | |||
303 | } | 303 | } |
304 | } | 304 | } |
305 | 305 | ||
306 | static void fm10k_mask_aer_comp_abort(struct pci_dev *pdev) | ||
307 | { | ||
308 | u32 err_mask; | ||
309 | int pos; | ||
310 | |||
311 | pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); | ||
312 | if (!pos) | ||
313 | return; | ||
314 | |||
315 | /* Mask the completion abort bit in the ERR_UNCOR_MASK register, | ||
316 | * preventing the device from reporting these errors to the upstream | ||
317 | * PCIe root device. This avoids bringing down platforms which upgrade | ||
318 | * non-fatal completer aborts into machine check exceptions. Completer | ||
319 | * aborts can occur whenever a VF reads a queue it doesn't own. | ||
320 | */ | ||
321 | pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_MASK, &err_mask); | ||
322 | err_mask |= PCI_ERR_UNC_COMP_ABORT; | ||
323 | pci_write_config_dword(pdev, pos + PCI_ERR_UNCOR_MASK, err_mask); | ||
324 | |||
325 | mmiowb(); | ||
326 | } | ||
327 | |||
306 | int fm10k_iov_resume(struct pci_dev *pdev) | 328 | int fm10k_iov_resume(struct pci_dev *pdev) |
307 | { | 329 | { |
308 | struct fm10k_intfc *interface = pci_get_drvdata(pdev); | 330 | struct fm10k_intfc *interface = pci_get_drvdata(pdev); |
@@ -318,6 +340,12 @@ int fm10k_iov_resume(struct pci_dev *pdev) | |||
318 | if (!iov_data) | 340 | if (!iov_data) |
319 | return -ENOMEM; | 341 | return -ENOMEM; |
320 | 342 | ||
343 | /* Lower severity of completer abort error reporting as | ||
344 | * the VFs can trigger this any time they read a queue | ||
345 | * that they don't own. | ||
346 | */ | ||
347 | fm10k_mask_aer_comp_abort(pdev); | ||
348 | |||
321 | /* allocate hardware resources for the VFs */ | 349 | /* allocate hardware resources for the VFs */ |
322 | hw->iov.ops.assign_resources(hw, num_vfs, num_vfs); | 350 | hw->iov.ops.assign_resources(hw, num_vfs, num_vfs); |
323 | 351 | ||
@@ -461,20 +489,6 @@ void fm10k_iov_disable(struct pci_dev *pdev) | |||
461 | fm10k_iov_free_data(pdev); | 489 | fm10k_iov_free_data(pdev); |
462 | } | 490 | } |
463 | 491 | ||
464 | static void fm10k_disable_aer_comp_abort(struct pci_dev *pdev) | ||
465 | { | ||
466 | u32 err_sev; | ||
467 | int pos; | ||
468 | |||
469 | pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); | ||
470 | if (!pos) | ||
471 | return; | ||
472 | |||
473 | pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, &err_sev); | ||
474 | err_sev &= ~PCI_ERR_UNC_COMP_ABORT; | ||
475 | pci_write_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, err_sev); | ||
476 | } | ||
477 | |||
478 | int fm10k_iov_configure(struct pci_dev *pdev, int num_vfs) | 492 | int fm10k_iov_configure(struct pci_dev *pdev, int num_vfs) |
479 | { | 493 | { |
480 | int current_vfs = pci_num_vf(pdev); | 494 | int current_vfs = pci_num_vf(pdev); |
@@ -496,12 +510,6 @@ int fm10k_iov_configure(struct pci_dev *pdev, int num_vfs) | |||
496 | 510 | ||
497 | /* allocate VFs if not already allocated */ | 511 | /* allocate VFs if not already allocated */ |
498 | if (num_vfs && num_vfs != current_vfs) { | 512 | if (num_vfs && num_vfs != current_vfs) { |
499 | /* Disable completer abort error reporting as | ||
500 | * the VFs can trigger this any time they read a queue | ||
501 | * that they don't own. | ||
502 | */ | ||
503 | fm10k_disable_aer_comp_abort(pdev); | ||
504 | |||
505 | err = pci_enable_sriov(pdev, num_vfs); | 513 | err = pci_enable_sriov(pdev, num_vfs); |
506 | if (err) { | 514 | if (err) { |
507 | dev_err(&pdev->dev, | 515 | dev_err(&pdev->dev, |