• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/drivers/pci/pcie/aer/
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
23#include <linux/kernel.h>
24#include <linux/module.h>
25#include <linux/moduleparam.h>
26#include <linux/pci.h>
27#include <linux/pci_regs.h>
28#include <linux/errno.h>
29#include "../../pci.h"
30
31#define ECRC_POLICY_DEFAULT 0		/* ECRC set by BIOS */
32#define ECRC_POLICY_OFF     1		/* ECRC off for performance */
33#define ECRC_POLICY_ON      2		/* ECRC on for data integrity */
34
35static int ecrc_policy = ECRC_POLICY_DEFAULT;
36
37static const char *ecrc_policy_str[] = {
38	[ECRC_POLICY_DEFAULT] = "bios",
39	[ECRC_POLICY_OFF] = "off",
40	[ECRC_POLICY_ON] = "on"
41};
42
43/**
44 * enable_ercr_checking - enable PCIe ECRC checking for a device
45 * @dev: the PCI device
46 *
47 * Returns 0 on success, or negative on failure.
48 */
49static int enable_ecrc_checking(struct pci_dev *dev)
50{
51	int pos;
52	u32 reg32;
53
54	if (!pci_is_pcie(dev))
55		return -ENODEV;
56
57	pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
58	if (!pos)
59		return -ENODEV;
60
61	pci_read_config_dword(dev, pos + PCI_ERR_CAP, &reg32);
62	if (reg32 & PCI_ERR_CAP_ECRC_GENC)
63		reg32 |= PCI_ERR_CAP_ECRC_GENE;
64	if (reg32 & PCI_ERR_CAP_ECRC_CHKC)
65		reg32 |= PCI_ERR_CAP_ECRC_CHKE;
66	pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32);
67
68	return 0;
69}
70
71/**
72 * disable_ercr_checking - disables PCIe ECRC checking for a device
73 * @dev: the PCI device
74 *
75 * Returns 0 on success, or negative on failure.
76 */
77static int disable_ecrc_checking(struct pci_dev *dev)
78{
79	int pos;
80	u32 reg32;
81
82	if (!pci_is_pcie(dev))
83		return -ENODEV;
84
85	pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
86	if (!pos)
87		return -ENODEV;
88
89	pci_read_config_dword(dev, pos + PCI_ERR_CAP, &reg32);
90	reg32 &= ~(PCI_ERR_CAP_ECRC_GENE | PCI_ERR_CAP_ECRC_CHKE);
91	pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32);
92
93	return 0;
94}
95
96/**
97 * pcie_set_ecrc_checking - set/unset PCIe ECRC checking for a device based on global policy
98 * @dev: the PCI device
99 */
100void pcie_set_ecrc_checking(struct pci_dev *dev)
101{
102	switch (ecrc_policy) {
103	case ECRC_POLICY_DEFAULT:
104		return;
105	case ECRC_POLICY_OFF:
106		disable_ecrc_checking(dev);
107		break;
108	case ECRC_POLICY_ON:
109		enable_ecrc_checking(dev);
110		break;
111	default:
112		return;
113	}
114}
115
116/**
117 * pcie_ecrc_get_policy - parse kernel command-line ecrc option
118 */
119void pcie_ecrc_get_policy(char *str)
120{
121	int i;
122
123	for (i = 0; i < ARRAY_SIZE(ecrc_policy_str); i++)
124		if (!strncmp(str, ecrc_policy_str[i],
125			     strlen(ecrc_policy_str[i])))
126			break;
127	if (i >= ARRAY_SIZE(ecrc_policy_str))
128		return;
129
130	ecrc_policy = i;
131}
132