diff options
author | Brian King <brking@us.ibm.com> | 2005-09-27 04:21:55 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-10-28 18:36:58 -0400 |
commit | e04b0ea2e0f9c1bb0d874db4493fc7f7a623116b (patch) | |
tree | 75937e50de883f69e906a4c8bc9f119d86c14411 /drivers/pci/proc.c | |
parent | 2cea752f683af1be58ee8f25717c0a8118e0ac5b (diff) |
[PATCH] PCI: Block config access during BIST
Some PCI adapters (eg. ipr scsi adapters) have an exposure today in that they
issue BIST to the adapter to reset the card. If, during the time it takes to
complete BIST, userspace attempts to access PCI config space, the host bus
bridge will master abort the access since the ipr adapter does not respond on
the PCI bus for a brief period of time when running BIST. On PPC64 hardware,
this master abort results in the host PCI bridge isolating that PCI device
from the rest of the system, making the device unusable until Linux is
rebooted. This patch is an attempt to close that exposure by introducing some
blocking code in the PCI code. When blocked, writes will be humored and reads
will return the cached value. Ben Herrenschmidt has also mentioned that he
plans to use this in PPC power management.
Signed-off-by: Brian King <brking@us.ibm.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/pci/access.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++
drivers/pci/pci-sysfs.c | 20 +++++-----
drivers/pci/pci.h | 7 +++
drivers/pci/proc.c | 28 +++++++--------
drivers/pci/syscall.c | 14 +++----
include/linux/pci.h | 7 +++
6 files changed, 134 insertions(+), 31 deletions(-)
Diffstat (limited to 'drivers/pci/proc.c')
-rw-r--r-- | drivers/pci/proc.c | 28 |
1 files changed, 14 insertions, 14 deletions
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c index 9613f666c110..9eb465727fce 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c | |||
@@ -80,7 +80,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp | |||
80 | 80 | ||
81 | if ((pos & 1) && cnt) { | 81 | if ((pos & 1) && cnt) { |
82 | unsigned char val; | 82 | unsigned char val; |
83 | pci_read_config_byte(dev, pos, &val); | 83 | pci_user_read_config_byte(dev, pos, &val); |
84 | __put_user(val, buf); | 84 | __put_user(val, buf); |
85 | buf++; | 85 | buf++; |
86 | pos++; | 86 | pos++; |
@@ -89,7 +89,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp | |||
89 | 89 | ||
90 | if ((pos & 3) && cnt > 2) { | 90 | if ((pos & 3) && cnt > 2) { |
91 | unsigned short val; | 91 | unsigned short val; |
92 | pci_read_config_word(dev, pos, &val); | 92 | pci_user_read_config_word(dev, pos, &val); |
93 | __put_user(cpu_to_le16(val), (unsigned short __user *) buf); | 93 | __put_user(cpu_to_le16(val), (unsigned short __user *) buf); |
94 | buf += 2; | 94 | buf += 2; |
95 | pos += 2; | 95 | pos += 2; |
@@ -98,7 +98,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp | |||
98 | 98 | ||
99 | while (cnt >= 4) { | 99 | while (cnt >= 4) { |
100 | unsigned int val; | 100 | unsigned int val; |
101 | pci_read_config_dword(dev, pos, &val); | 101 | pci_user_read_config_dword(dev, pos, &val); |
102 | __put_user(cpu_to_le32(val), (unsigned int __user *) buf); | 102 | __put_user(cpu_to_le32(val), (unsigned int __user *) buf); |
103 | buf += 4; | 103 | buf += 4; |
104 | pos += 4; | 104 | pos += 4; |
@@ -107,7 +107,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp | |||
107 | 107 | ||
108 | if (cnt >= 2) { | 108 | if (cnt >= 2) { |
109 | unsigned short val; | 109 | unsigned short val; |
110 | pci_read_config_word(dev, pos, &val); | 110 | pci_user_read_config_word(dev, pos, &val); |
111 | __put_user(cpu_to_le16(val), (unsigned short __user *) buf); | 111 | __put_user(cpu_to_le16(val), (unsigned short __user *) buf); |
112 | buf += 2; | 112 | buf += 2; |
113 | pos += 2; | 113 | pos += 2; |
@@ -116,7 +116,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp | |||
116 | 116 | ||
117 | if (cnt) { | 117 | if (cnt) { |
118 | unsigned char val; | 118 | unsigned char val; |
119 | pci_read_config_byte(dev, pos, &val); | 119 | pci_user_read_config_byte(dev, pos, &val); |
120 | __put_user(val, buf); | 120 | __put_user(val, buf); |
121 | buf++; | 121 | buf++; |
122 | pos++; | 122 | pos++; |
@@ -151,7 +151,7 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof | |||
151 | if ((pos & 1) && cnt) { | 151 | if ((pos & 1) && cnt) { |
152 | unsigned char val; | 152 | unsigned char val; |
153 | __get_user(val, buf); | 153 | __get_user(val, buf); |
154 | pci_write_config_byte(dev, pos, val); | 154 | pci_user_write_config_byte(dev, pos, val); |
155 | buf++; | 155 | buf++; |
156 | pos++; | 156 | pos++; |
157 | cnt--; | 157 | cnt--; |
@@ -160,7 +160,7 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof | |||
160 | if ((pos & 3) && cnt > 2) { | 160 | if ((pos & 3) && cnt > 2) { |
161 | unsigned short val; | 161 | unsigned short val; |
162 | __get_user(val, (unsigned short __user *) buf); | 162 | __get_user(val, (unsigned short __user *) buf); |
163 | pci_write_config_word(dev, pos, le16_to_cpu(val)); | 163 | pci_user_write_config_word(dev, pos, le16_to_cpu(val)); |
164 | buf += 2; | 164 | buf += 2; |
165 | pos += 2; | 165 | pos += 2; |
166 | cnt -= 2; | 166 | cnt -= 2; |
@@ -169,7 +169,7 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof | |||
169 | while (cnt >= 4) { | 169 | while (cnt >= 4) { |
170 | unsigned int val; | 170 | unsigned int val; |
171 | __get_user(val, (unsigned int __user *) buf); | 171 | __get_user(val, (unsigned int __user *) buf); |
172 | pci_write_config_dword(dev, pos, le32_to_cpu(val)); | 172 | pci_user_write_config_dword(dev, pos, le32_to_cpu(val)); |
173 | buf += 4; | 173 | buf += 4; |
174 | pos += 4; | 174 | pos += 4; |
175 | cnt -= 4; | 175 | cnt -= 4; |
@@ -178,7 +178,7 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof | |||
178 | if (cnt >= 2) { | 178 | if (cnt >= 2) { |
179 | unsigned short val; | 179 | unsigned short val; |
180 | __get_user(val, (unsigned short __user *) buf); | 180 | __get_user(val, (unsigned short __user *) buf); |
181 | pci_write_config_word(dev, pos, le16_to_cpu(val)); | 181 | pci_user_write_config_word(dev, pos, le16_to_cpu(val)); |
182 | buf += 2; | 182 | buf += 2; |
183 | pos += 2; | 183 | pos += 2; |
184 | cnt -= 2; | 184 | cnt -= 2; |
@@ -187,7 +187,7 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof | |||
187 | if (cnt) { | 187 | if (cnt) { |
188 | unsigned char val; | 188 | unsigned char val; |
189 | __get_user(val, buf); | 189 | __get_user(val, buf); |
190 | pci_write_config_byte(dev, pos, val); | 190 | pci_user_write_config_byte(dev, pos, val); |
191 | buf++; | 191 | buf++; |
192 | pos++; | 192 | pos++; |
193 | cnt--; | 193 | cnt--; |
@@ -484,10 +484,10 @@ static int show_dev_config(struct seq_file *m, void *v) | |||
484 | 484 | ||
485 | drv = pci_dev_driver(dev); | 485 | drv = pci_dev_driver(dev); |
486 | 486 | ||
487 | pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); | 487 | pci_user_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); |
488 | pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency); | 488 | pci_user_read_config_byte (dev, PCI_LATENCY_TIMER, &latency); |
489 | pci_read_config_byte (dev, PCI_MIN_GNT, &min_gnt); | 489 | pci_user_read_config_byte (dev, PCI_MIN_GNT, &min_gnt); |
490 | pci_read_config_byte (dev, PCI_MAX_LAT, &max_lat); | 490 | pci_user_read_config_byte (dev, PCI_MAX_LAT, &max_lat); |
491 | seq_printf(m, " Bus %2d, device %3d, function %2d:\n", | 491 | seq_printf(m, " Bus %2d, device %3d, function %2d:\n", |
492 | dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); | 492 | dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); |
493 | seq_printf(m, " Class %04x", class_rev >> 16); | 493 | seq_printf(m, " Class %04x", class_rev >> 16); |