diff options
-rw-r--r-- | drivers/pci/access.c | 89 | ||||
-rw-r--r-- | drivers/pci/pci-sysfs.c | 20 | ||||
-rw-r--r-- | drivers/pci/pci.h | 7 | ||||
-rw-r--r-- | drivers/pci/proc.c | 28 | ||||
-rw-r--r-- | drivers/pci/syscall.c | 14 | ||||
-rw-r--r-- | include/linux/pci.h | 7 |
6 files changed, 134 insertions, 31 deletions
diff --git a/drivers/pci/access.c b/drivers/pci/access.c index 24a76de49f41..2a42add7f563 100644 --- a/drivers/pci/access.c +++ b/drivers/pci/access.c | |||
@@ -60,3 +60,92 @@ EXPORT_SYMBOL(pci_bus_read_config_dword); | |||
60 | EXPORT_SYMBOL(pci_bus_write_config_byte); | 60 | EXPORT_SYMBOL(pci_bus_write_config_byte); |
61 | EXPORT_SYMBOL(pci_bus_write_config_word); | 61 | EXPORT_SYMBOL(pci_bus_write_config_word); |
62 | EXPORT_SYMBOL(pci_bus_write_config_dword); | 62 | EXPORT_SYMBOL(pci_bus_write_config_dword); |
63 | |||
64 | static u32 pci_user_cached_config(struct pci_dev *dev, int pos) | ||
65 | { | ||
66 | u32 data; | ||
67 | |||
68 | data = dev->saved_config_space[pos/sizeof(dev->saved_config_space[0])]; | ||
69 | data >>= (pos % sizeof(dev->saved_config_space[0])) * 8; | ||
70 | return data; | ||
71 | } | ||
72 | |||
73 | #define PCI_USER_READ_CONFIG(size,type) \ | ||
74 | int pci_user_read_config_##size \ | ||
75 | (struct pci_dev *dev, int pos, type *val) \ | ||
76 | { \ | ||
77 | unsigned long flags; \ | ||
78 | int ret = 0; \ | ||
79 | u32 data = -1; \ | ||
80 | if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \ | ||
81 | spin_lock_irqsave(&pci_lock, flags); \ | ||
82 | if (likely(!dev->block_ucfg_access)) \ | ||
83 | ret = dev->bus->ops->read(dev->bus, dev->devfn, \ | ||
84 | pos, sizeof(type), &data); \ | ||
85 | else if (pos < sizeof(dev->saved_config_space)) \ | ||
86 | data = pci_user_cached_config(dev, pos); \ | ||
87 | spin_unlock_irqrestore(&pci_lock, flags); \ | ||
88 | *val = (type)data; \ | ||
89 | return ret; \ | ||
90 | } | ||
91 | |||
92 | #define PCI_USER_WRITE_CONFIG(size,type) \ | ||
93 | int pci_user_write_config_##size \ | ||
94 | (struct pci_dev *dev, int pos, type val) \ | ||
95 | { \ | ||
96 | unsigned long flags; \ | ||
97 | int ret = -EIO; \ | ||
98 | if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \ | ||
99 | spin_lock_irqsave(&pci_lock, flags); \ | ||
100 | if (likely(!dev->block_ucfg_access)) \ | ||
101 | ret = dev->bus->ops->write(dev->bus, dev->devfn, \ | ||
102 | pos, sizeof(type), val); \ | ||
103 | spin_unlock_irqrestore(&pci_lock, flags); \ | ||
104 | return ret; \ | ||
105 | } | ||
106 | |||
107 | PCI_USER_READ_CONFIG(byte, u8) | ||
108 | PCI_USER_READ_CONFIG(word, u16) | ||
109 | PCI_USER_READ_CONFIG(dword, u32) | ||
110 | PCI_USER_WRITE_CONFIG(byte, u8) | ||
111 | PCI_USER_WRITE_CONFIG(word, u16) | ||
112 | PCI_USER_WRITE_CONFIG(dword, u32) | ||
113 | |||
114 | /** | ||
115 | * pci_block_user_cfg_access - Block userspace PCI config reads/writes | ||
116 | * @dev: pci device struct | ||
117 | * | ||
118 | * This function blocks any userspace PCI config accesses from occurring. | ||
119 | * When blocked, any writes will be bit bucketed and reads will return the | ||
120 | * data saved using pci_save_state for the first 64 bytes of config | ||
121 | * space and return 0xff for all other config reads. | ||
122 | **/ | ||
123 | void pci_block_user_cfg_access(struct pci_dev *dev) | ||
124 | { | ||
125 | unsigned long flags; | ||
126 | |||
127 | pci_save_state(dev); | ||
128 | |||
129 | /* spinlock to synchronize with anyone reading config space now */ | ||
130 | spin_lock_irqsave(&pci_lock, flags); | ||
131 | dev->block_ucfg_access = 1; | ||
132 | spin_unlock_irqrestore(&pci_lock, flags); | ||
133 | } | ||
134 | EXPORT_SYMBOL_GPL(pci_block_user_cfg_access); | ||
135 | |||
136 | /** | ||
137 | * pci_unblock_user_cfg_access - Unblock userspace PCI config reads/writes | ||
138 | * @dev: pci device struct | ||
139 | * | ||
140 | * This function allows userspace PCI config accesses to resume. | ||
141 | **/ | ||
142 | void pci_unblock_user_cfg_access(struct pci_dev *dev) | ||
143 | { | ||
144 | unsigned long flags; | ||
145 | |||
146 | /* spinlock to synchronize with anyone reading saved config space */ | ||
147 | spin_lock_irqsave(&pci_lock, flags); | ||
148 | dev->block_ucfg_access = 0; | ||
149 | spin_unlock_irqrestore(&pci_lock, flags); | ||
150 | } | ||
151 | EXPORT_SYMBOL_GPL(pci_unblock_user_cfg_access); | ||
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 2898830c496f..965a5934623a 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
@@ -130,7 +130,7 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count) | |||
130 | 130 | ||
131 | if ((off & 1) && size) { | 131 | if ((off & 1) && size) { |
132 | u8 val; | 132 | u8 val; |
133 | pci_read_config_byte(dev, off, &val); | 133 | pci_user_read_config_byte(dev, off, &val); |
134 | data[off - init_off] = val; | 134 | data[off - init_off] = val; |
135 | off++; | 135 | off++; |
136 | size--; | 136 | size--; |
@@ -138,7 +138,7 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count) | |||
138 | 138 | ||
139 | if ((off & 3) && size > 2) { | 139 | if ((off & 3) && size > 2) { |
140 | u16 val; | 140 | u16 val; |
141 | pci_read_config_word(dev, off, &val); | 141 | pci_user_read_config_word(dev, off, &val); |
142 | data[off - init_off] = val & 0xff; | 142 | data[off - init_off] = val & 0xff; |
143 | data[off - init_off + 1] = (val >> 8) & 0xff; | 143 | data[off - init_off + 1] = (val >> 8) & 0xff; |
144 | off += 2; | 144 | off += 2; |
@@ -147,7 +147,7 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count) | |||
147 | 147 | ||
148 | while (size > 3) { | 148 | while (size > 3) { |
149 | u32 val; | 149 | u32 val; |
150 | pci_read_config_dword(dev, off, &val); | 150 | pci_user_read_config_dword(dev, off, &val); |
151 | data[off - init_off] = val & 0xff; | 151 | data[off - init_off] = val & 0xff; |
152 | data[off - init_off + 1] = (val >> 8) & 0xff; | 152 | data[off - init_off + 1] = (val >> 8) & 0xff; |
153 | data[off - init_off + 2] = (val >> 16) & 0xff; | 153 | data[off - init_off + 2] = (val >> 16) & 0xff; |
@@ -158,7 +158,7 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count) | |||
158 | 158 | ||
159 | if (size >= 2) { | 159 | if (size >= 2) { |
160 | u16 val; | 160 | u16 val; |
161 | pci_read_config_word(dev, off, &val); | 161 | pci_user_read_config_word(dev, off, &val); |
162 | data[off - init_off] = val & 0xff; | 162 | data[off - init_off] = val & 0xff; |
163 | data[off - init_off + 1] = (val >> 8) & 0xff; | 163 | data[off - init_off + 1] = (val >> 8) & 0xff; |
164 | off += 2; | 164 | off += 2; |
@@ -167,7 +167,7 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count) | |||
167 | 167 | ||
168 | if (size > 0) { | 168 | if (size > 0) { |
169 | u8 val; | 169 | u8 val; |
170 | pci_read_config_byte(dev, off, &val); | 170 | pci_user_read_config_byte(dev, off, &val); |
171 | data[off - init_off] = val; | 171 | data[off - init_off] = val; |
172 | off++; | 172 | off++; |
173 | --size; | 173 | --size; |
@@ -192,7 +192,7 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count) | |||
192 | } | 192 | } |
193 | 193 | ||
194 | if ((off & 1) && size) { | 194 | if ((off & 1) && size) { |
195 | pci_write_config_byte(dev, off, data[off - init_off]); | 195 | pci_user_write_config_byte(dev, off, data[off - init_off]); |
196 | off++; | 196 | off++; |
197 | size--; | 197 | size--; |
198 | } | 198 | } |
@@ -200,7 +200,7 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count) | |||
200 | if ((off & 3) && size > 2) { | 200 | if ((off & 3) && size > 2) { |
201 | u16 val = data[off - init_off]; | 201 | u16 val = data[off - init_off]; |
202 | val |= (u16) data[off - init_off + 1] << 8; | 202 | val |= (u16) data[off - init_off + 1] << 8; |
203 | pci_write_config_word(dev, off, val); | 203 | pci_user_write_config_word(dev, off, val); |
204 | off += 2; | 204 | off += 2; |
205 | size -= 2; | 205 | size -= 2; |
206 | } | 206 | } |
@@ -210,7 +210,7 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count) | |||
210 | val |= (u32) data[off - init_off + 1] << 8; | 210 | val |= (u32) data[off - init_off + 1] << 8; |
211 | val |= (u32) data[off - init_off + 2] << 16; | 211 | val |= (u32) data[off - init_off + 2] << 16; |
212 | val |= (u32) data[off - init_off + 3] << 24; | 212 | val |= (u32) data[off - init_off + 3] << 24; |
213 | pci_write_config_dword(dev, off, val); | 213 | pci_user_write_config_dword(dev, off, val); |
214 | off += 4; | 214 | off += 4; |
215 | size -= 4; | 215 | size -= 4; |
216 | } | 216 | } |
@@ -218,13 +218,13 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count) | |||
218 | if (size >= 2) { | 218 | if (size >= 2) { |
219 | u16 val = data[off - init_off]; | 219 | u16 val = data[off - init_off]; |
220 | val |= (u16) data[off - init_off + 1] << 8; | 220 | val |= (u16) data[off - init_off + 1] << 8; |
221 | pci_write_config_word(dev, off, val); | 221 | pci_user_write_config_word(dev, off, val); |
222 | off += 2; | 222 | off += 2; |
223 | size -= 2; | 223 | size -= 2; |
224 | } | 224 | } |
225 | 225 | ||
226 | if (size) { | 226 | if (size) { |
227 | pci_write_config_byte(dev, off, data[off - init_off]); | 227 | pci_user_write_config_byte(dev, off, data[off - init_off]); |
228 | off++; | 228 | off++; |
229 | --size; | 229 | --size; |
230 | } | 230 | } |
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index d3f3dd42240d..6527b36c9a61 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -15,6 +15,13 @@ extern int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, | |||
15 | extern int (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state); | 15 | extern int (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state); |
16 | extern int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t state); | 16 | extern int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t state); |
17 | 17 | ||
18 | extern int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val); | ||
19 | extern int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val); | ||
20 | extern int pci_user_read_config_dword(struct pci_dev *dev, int where, u32 *val); | ||
21 | extern int pci_user_write_config_byte(struct pci_dev *dev, int where, u8 val); | ||
22 | extern int pci_user_write_config_word(struct pci_dev *dev, int where, u16 val); | ||
23 | extern int pci_user_write_config_dword(struct pci_dev *dev, int where, u32 val); | ||
24 | |||
18 | /* PCI /proc functions */ | 25 | /* PCI /proc functions */ |
19 | #ifdef CONFIG_PROC_FS | 26 | #ifdef CONFIG_PROC_FS |
20 | extern int pci_proc_attach_device(struct pci_dev *dev); | 27 | extern int pci_proc_attach_device(struct pci_dev *dev); |
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); |
diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c index c071790cc983..87fafc08cb9d 100644 --- a/drivers/pci/syscall.c +++ b/drivers/pci/syscall.c | |||
@@ -13,7 +13,7 @@ | |||
13 | #include <linux/smp_lock.h> | 13 | #include <linux/smp_lock.h> |
14 | #include <linux/syscalls.h> | 14 | #include <linux/syscalls.h> |
15 | #include <asm/uaccess.h> | 15 | #include <asm/uaccess.h> |
16 | 16 | #include "pci.h" | |
17 | 17 | ||
18 | asmlinkage long | 18 | asmlinkage long |
19 | sys_pciconfig_read(unsigned long bus, unsigned long dfn, | 19 | sys_pciconfig_read(unsigned long bus, unsigned long dfn, |
@@ -38,13 +38,13 @@ sys_pciconfig_read(unsigned long bus, unsigned long dfn, | |||
38 | lock_kernel(); | 38 | lock_kernel(); |
39 | switch (len) { | 39 | switch (len) { |
40 | case 1: | 40 | case 1: |
41 | cfg_ret = pci_read_config_byte(dev, off, &byte); | 41 | cfg_ret = pci_user_read_config_byte(dev, off, &byte); |
42 | break; | 42 | break; |
43 | case 2: | 43 | case 2: |
44 | cfg_ret = pci_read_config_word(dev, off, &word); | 44 | cfg_ret = pci_user_read_config_word(dev, off, &word); |
45 | break; | 45 | break; |
46 | case 4: | 46 | case 4: |
47 | cfg_ret = pci_read_config_dword(dev, off, &dword); | 47 | cfg_ret = pci_user_read_config_dword(dev, off, &dword); |
48 | break; | 48 | break; |
49 | default: | 49 | default: |
50 | err = -EINVAL; | 50 | err = -EINVAL; |
@@ -112,7 +112,7 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn, | |||
112 | err = get_user(byte, (u8 __user *)buf); | 112 | err = get_user(byte, (u8 __user *)buf); |
113 | if (err) | 113 | if (err) |
114 | break; | 114 | break; |
115 | err = pci_write_config_byte(dev, off, byte); | 115 | err = pci_user_write_config_byte(dev, off, byte); |
116 | if (err != PCIBIOS_SUCCESSFUL) | 116 | if (err != PCIBIOS_SUCCESSFUL) |
117 | err = -EIO; | 117 | err = -EIO; |
118 | break; | 118 | break; |
@@ -121,7 +121,7 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn, | |||
121 | err = get_user(word, (u16 __user *)buf); | 121 | err = get_user(word, (u16 __user *)buf); |
122 | if (err) | 122 | if (err) |
123 | break; | 123 | break; |
124 | err = pci_write_config_word(dev, off, word); | 124 | err = pci_user_write_config_word(dev, off, word); |
125 | if (err != PCIBIOS_SUCCESSFUL) | 125 | if (err != PCIBIOS_SUCCESSFUL) |
126 | err = -EIO; | 126 | err = -EIO; |
127 | break; | 127 | break; |
@@ -130,7 +130,7 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn, | |||
130 | err = get_user(dword, (u32 __user *)buf); | 130 | err = get_user(dword, (u32 __user *)buf); |
131 | if (err) | 131 | if (err) |
132 | break; | 132 | break; |
133 | err = pci_write_config_dword(dev, off, dword); | 133 | err = pci_user_write_config_dword(dev, off, dword); |
134 | if (err != PCIBIOS_SUCCESSFUL) | 134 | if (err != PCIBIOS_SUCCESSFUL) |
135 | err = -EIO; | 135 | err = -EIO; |
136 | break; | 136 | break; |
diff --git a/include/linux/pci.h b/include/linux/pci.h index 7349058ed778..3596ac94ecff 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -132,6 +132,7 @@ struct pci_dev { | |||
132 | unsigned int is_enabled:1; /* pci_enable_device has been called */ | 132 | unsigned int is_enabled:1; /* pci_enable_device has been called */ |
133 | unsigned int is_busmaster:1; /* device is busmaster */ | 133 | unsigned int is_busmaster:1; /* device is busmaster */ |
134 | unsigned int no_msi:1; /* device may not use msi */ | 134 | unsigned int no_msi:1; /* device may not use msi */ |
135 | unsigned int block_ucfg_access:1; /* userspace config space access is blocked */ | ||
135 | 136 | ||
136 | u32 saved_config_space[16]; /* config space saved at suspend time */ | 137 | u32 saved_config_space[16]; /* config space saved at suspend time */ |
137 | struct bin_attribute *rom_attr; /* attribute descriptor for sysfs ROM entry */ | 138 | struct bin_attribute *rom_attr; /* attribute descriptor for sysfs ROM entry */ |
@@ -490,6 +491,9 @@ extern void pci_disable_msix(struct pci_dev *dev); | |||
490 | extern void msi_remove_pci_irq_vectors(struct pci_dev *dev); | 491 | extern void msi_remove_pci_irq_vectors(struct pci_dev *dev); |
491 | #endif | 492 | #endif |
492 | 493 | ||
494 | extern void pci_block_user_cfg_access(struct pci_dev *dev); | ||
495 | extern void pci_unblock_user_cfg_access(struct pci_dev *dev); | ||
496 | |||
493 | /* | 497 | /* |
494 | * PCI domain support. Sometimes called PCI segment (eg by ACPI), | 498 | * PCI domain support. Sometimes called PCI segment (eg by ACPI), |
495 | * a PCI domain is defined to be a set of PCI busses which share | 499 | * a PCI domain is defined to be a set of PCI busses which share |
@@ -560,6 +564,9 @@ static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int en | |||
560 | 564 | ||
561 | #define pci_dma_burst_advice(pdev, strat, strategy_parameter) do { } while (0) | 565 | #define pci_dma_burst_advice(pdev, strat, strategy_parameter) do { } while (0) |
562 | 566 | ||
567 | static inline void pci_block_user_cfg_access(struct pci_dev *dev) { } | ||
568 | static inline void pci_unblock_user_cfg_access(struct pci_dev *dev) { } | ||
569 | |||
563 | #endif /* CONFIG_PCI */ | 570 | #endif /* CONFIG_PCI */ |
564 | 571 | ||
565 | /* Include architecture-dependent settings and functions */ | 572 | /* Include architecture-dependent settings and functions */ |