aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/access.c89
-rw-r--r--drivers/pci/pci-sysfs.c20
-rw-r--r--drivers/pci/pci.h7
-rw-r--r--drivers/pci/proc.c28
-rw-r--r--drivers/pci/syscall.c14
5 files changed, 127 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);
60EXPORT_SYMBOL(pci_bus_write_config_byte); 60EXPORT_SYMBOL(pci_bus_write_config_byte);
61EXPORT_SYMBOL(pci_bus_write_config_word); 61EXPORT_SYMBOL(pci_bus_write_config_word);
62EXPORT_SYMBOL(pci_bus_write_config_dword); 62EXPORT_SYMBOL(pci_bus_write_config_dword);
63
64static 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) \
74int 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) \
93int 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
107PCI_USER_READ_CONFIG(byte, u8)
108PCI_USER_READ_CONFIG(word, u16)
109PCI_USER_READ_CONFIG(dword, u32)
110PCI_USER_WRITE_CONFIG(byte, u8)
111PCI_USER_WRITE_CONFIG(word, u16)
112PCI_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 **/
123void 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}
134EXPORT_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 **/
142void 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}
151EXPORT_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,
15extern int (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state); 15extern int (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state);
16extern int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t state); 16extern int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t state);
17 17
18extern int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val);
19extern int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val);
20extern int pci_user_read_config_dword(struct pci_dev *dev, int where, u32 *val);
21extern int pci_user_write_config_byte(struct pci_dev *dev, int where, u8 val);
22extern int pci_user_write_config_word(struct pci_dev *dev, int where, u16 val);
23extern 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
20extern int pci_proc_attach_device(struct pci_dev *dev); 27extern 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
18asmlinkage long 18asmlinkage long
19sys_pciconfig_read(unsigned long bus, unsigned long dfn, 19sys_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;