diff options
Diffstat (limited to 'drivers/net/ethernet/intel/fm10k/fm10k_iov.c')
| -rw-r--r-- | drivers/net/ethernet/intel/fm10k/fm10k_iov.c | 71 |
1 files changed, 31 insertions, 40 deletions
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_iov.c b/drivers/net/ethernet/intel/fm10k/fm10k_iov.c index 30395f5e5e87..5d4f1761dc0c 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_iov.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_iov.c | |||
| @@ -1,23 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | /* Intel(R) Ethernet Switch Host Interface Driver | 2 | /* Copyright(c) 2013 - 2018 Intel Corporation. */ |
| 3 | * Copyright(c) 2013 - 2017 Intel Corporation. | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms and conditions of the GNU General Public License, | ||
| 7 | * version 2, as published by the Free Software Foundation. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 12 | * more details. | ||
| 13 | * | ||
| 14 | * The full GNU General Public License is included in this distribution in | ||
| 15 | * the file called "COPYING". | ||
| 16 | * | ||
| 17 | * Contact Information: | ||
| 18 | * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> | ||
| 19 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
| 20 | */ | ||
| 21 | 3 | ||
| 22 | #include "fm10k.h" | 4 | #include "fm10k.h" |
| 23 | #include "fm10k_vf.h" | 5 | #include "fm10k_vf.h" |
| @@ -262,7 +244,8 @@ process_mbx: | |||
| 262 | } | 244 | } |
| 263 | 245 | ||
| 264 | /* guarantee we have free space in the SM mailbox */ | 246 | /* guarantee we have free space in the SM mailbox */ |
| 265 | if (!hw->mbx.ops.tx_ready(&hw->mbx, FM10K_VFMBX_MSG_MTU)) { | 247 | if (hw->mbx.state == FM10K_STATE_OPEN && |
| 248 | !hw->mbx.ops.tx_ready(&hw->mbx, FM10K_VFMBX_MSG_MTU)) { | ||
| 266 | /* keep track of how many times this occurs */ | 249 | /* keep track of how many times this occurs */ |
| 267 | interface->hw_sm_mbx_full++; | 250 | interface->hw_sm_mbx_full++; |
| 268 | 251 | ||
| @@ -320,6 +303,28 @@ void fm10k_iov_suspend(struct pci_dev *pdev) | |||
| 320 | } | 303 | } |
| 321 | } | 304 | } |
| 322 | 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 | |||
| 323 | int fm10k_iov_resume(struct pci_dev *pdev) | 328 | int fm10k_iov_resume(struct pci_dev *pdev) |
| 324 | { | 329 | { |
| 325 | struct fm10k_intfc *interface = pci_get_drvdata(pdev); | 330 | struct fm10k_intfc *interface = pci_get_drvdata(pdev); |
| @@ -335,6 +340,12 @@ int fm10k_iov_resume(struct pci_dev *pdev) | |||
| 335 | if (!iov_data) | 340 | if (!iov_data) |
| 336 | return -ENOMEM; | 341 | return -ENOMEM; |
| 337 | 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 | |||
| 338 | /* allocate hardware resources for the VFs */ | 349 | /* allocate hardware resources for the VFs */ |
| 339 | hw->iov.ops.assign_resources(hw, num_vfs, num_vfs); | 350 | hw->iov.ops.assign_resources(hw, num_vfs, num_vfs); |
| 340 | 351 | ||
| @@ -478,20 +489,6 @@ void fm10k_iov_disable(struct pci_dev *pdev) | |||
| 478 | fm10k_iov_free_data(pdev); | 489 | fm10k_iov_free_data(pdev); |
| 479 | } | 490 | } |
| 480 | 491 | ||
| 481 | static void fm10k_disable_aer_comp_abort(struct pci_dev *pdev) | ||
| 482 | { | ||
| 483 | u32 err_sev; | ||
| 484 | int pos; | ||
| 485 | |||
| 486 | pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); | ||
| 487 | if (!pos) | ||
| 488 | return; | ||
| 489 | |||
| 490 | pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, &err_sev); | ||
| 491 | err_sev &= ~PCI_ERR_UNC_COMP_ABORT; | ||
| 492 | pci_write_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, err_sev); | ||
| 493 | } | ||
| 494 | |||
| 495 | int fm10k_iov_configure(struct pci_dev *pdev, int num_vfs) | 492 | int fm10k_iov_configure(struct pci_dev *pdev, int num_vfs) |
| 496 | { | 493 | { |
| 497 | int current_vfs = pci_num_vf(pdev); | 494 | int current_vfs = pci_num_vf(pdev); |
| @@ -513,12 +510,6 @@ int fm10k_iov_configure(struct pci_dev *pdev, int num_vfs) | |||
| 513 | 510 | ||
| 514 | /* allocate VFs if not already allocated */ | 511 | /* allocate VFs if not already allocated */ |
| 515 | if (num_vfs && num_vfs != current_vfs) { | 512 | if (num_vfs && num_vfs != current_vfs) { |
| 516 | /* Disable completer abort error reporting as | ||
| 517 | * the VFs can trigger this any time they read a queue | ||
| 518 | * that they don't own. | ||
| 519 | */ | ||
| 520 | fm10k_disable_aer_comp_abort(pdev); | ||
| 521 | |||
| 522 | err = pci_enable_sriov(pdev, num_vfs); | 513 | err = pci_enable_sriov(pdev, num_vfs); |
| 523 | if (err) { | 514 | if (err) { |
| 524 | dev_err(&pdev->dev, | 515 | dev_err(&pdev->dev, |
