ecrc.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /*
  2. * Enables/disables PCIe ECRC checking.
  3. *
  4. * (C) Copyright 2009 Hewlett-Packard Development Company, L.P.
  5. * Andrew Patterson <andrew.patterson@hp.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; version 2 of the License.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  19. * 02111-1307, USA.
  20. *
  21. */
  22. #include <linux/kernel.h>
  23. #include <linux/module.h>
  24. #include <linux/moduleparam.h>
  25. #include <linux/pci.h>
  26. #include <linux/pci_regs.h>
  27. #include <linux/errno.h>
  28. #include "../../pci.h"
  29. #define ECRC_POLICY_DEFAULT 0 /* ECRC set by BIOS */
  30. #define ECRC_POLICY_OFF 1 /* ECRC off for performance */
  31. #define ECRC_POLICY_ON 2 /* ECRC on for data integrity */
  32. static int ecrc_policy = ECRC_POLICY_DEFAULT;
  33. static const char *ecrc_policy_str[] = {
  34. [ECRC_POLICY_DEFAULT] = "bios",
  35. [ECRC_POLICY_OFF] = "off",
  36. [ECRC_POLICY_ON] = "on"
  37. };
  38. /**
  39. * enable_ercr_checking - enable PCIe ECRC checking for a device
  40. * @dev: the PCI device
  41. *
  42. * Returns 0 on success, or negative on failure.
  43. */
  44. static int enable_ecrc_checking(struct pci_dev *dev)
  45. {
  46. int pos;
  47. u32 reg32;
  48. if (!pci_is_pcie(dev))
  49. return -ENODEV;
  50. pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
  51. if (!pos)
  52. return -ENODEV;
  53. pci_read_config_dword(dev, pos + PCI_ERR_CAP, &reg32);
  54. if (reg32 & PCI_ERR_CAP_ECRC_GENC)
  55. reg32 |= PCI_ERR_CAP_ECRC_GENE;
  56. if (reg32 & PCI_ERR_CAP_ECRC_CHKC)
  57. reg32 |= PCI_ERR_CAP_ECRC_CHKE;
  58. pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32);
  59. return 0;
  60. }
  61. /**
  62. * disable_ercr_checking - disables PCIe ECRC checking for a device
  63. * @dev: the PCI device
  64. *
  65. * Returns 0 on success, or negative on failure.
  66. */
  67. static int disable_ecrc_checking(struct pci_dev *dev)
  68. {
  69. int pos;
  70. u32 reg32;
  71. if (!pci_is_pcie(dev))
  72. return -ENODEV;
  73. pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
  74. if (!pos)
  75. return -ENODEV;
  76. pci_read_config_dword(dev, pos + PCI_ERR_CAP, &reg32);
  77. reg32 &= ~(PCI_ERR_CAP_ECRC_GENE | PCI_ERR_CAP_ECRC_CHKE);
  78. pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32);
  79. return 0;
  80. }
  81. /**
  82. * pcie_set_ecrc_checking - set/unset PCIe ECRC checking for a device based on global policy
  83. * @dev: the PCI device
  84. */
  85. void pcie_set_ecrc_checking(struct pci_dev *dev)
  86. {
  87. switch (ecrc_policy) {
  88. case ECRC_POLICY_DEFAULT:
  89. return;
  90. case ECRC_POLICY_OFF:
  91. disable_ecrc_checking(dev);
  92. break;
  93. case ECRC_POLICY_ON:
  94. enable_ecrc_checking(dev);
  95. break;
  96. default:
  97. return;
  98. }
  99. }
  100. /**
  101. * pcie_ecrc_get_policy - parse kernel command-line ecrc option
  102. */
  103. void pcie_ecrc_get_policy(char *str)
  104. {
  105. int i;
  106. for (i = 0; i < ARRAY_SIZE(ecrc_policy_str); i++)
  107. if (!strncmp(str, ecrc_policy_str[i],
  108. strlen(ecrc_policy_str[i])))
  109. break;
  110. if (i >= ARRAY_SIZE(ecrc_policy_str))
  111. return;
  112. ecrc_policy = i;
  113. }