]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/xen/xen-pciback/conf_space.c
xen/pciback: xen pci backend driver.
[mv-sheeva.git] / drivers / xen / xen-pciback / conf_space.c
1 /*
2  * PCI Backend - Functions for creating a virtual configuration space for
3  *               exported PCI Devices.
4  *               It's dangerous to allow PCI Driver Domains to change their
5  *               device's resources (memory, i/o ports, interrupts). We need to
6  *               restrict changes to certain PCI Configuration registers:
7  *               BARs, INTERRUPT_PIN, most registers in the header...
8  *
9  * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
10  */
11
12 #include <linux/kernel.h>
13 #include <linux/pci.h>
14 #include "pciback.h"
15 #include "conf_space.h"
16 #include "conf_space_quirks.h"
17
18 static int permissive;
19 module_param(permissive, bool, 0644);
20
21 #define DEFINE_PCI_CONFIG(op, size, type)                       \
22 int pciback_##op##_config_##size                                \
23 (struct pci_dev *dev, int offset, type value, void *data)       \
24 {                                                               \
25         return pci_##op##_config_##size(dev, offset, value);    \
26 }
27
28 DEFINE_PCI_CONFIG(read, byte, u8 *)
29 DEFINE_PCI_CONFIG(read, word, u16 *)
30 DEFINE_PCI_CONFIG(read, dword, u32 *)
31
32 DEFINE_PCI_CONFIG(write, byte, u8)
33 DEFINE_PCI_CONFIG(write, word, u16)
34 DEFINE_PCI_CONFIG(write, dword, u32)
35
36 static int conf_space_read(struct pci_dev *dev,
37                            const struct config_field_entry *entry,
38                            int offset, u32 *value)
39 {
40         int ret = 0;
41         const struct config_field *field = entry->field;
42
43         *value = 0;
44
45         switch (field->size) {
46         case 1:
47                 if (field->u.b.read)
48                         ret = field->u.b.read(dev, offset, (u8 *) value,
49                                               entry->data);
50                 break;
51         case 2:
52                 if (field->u.w.read)
53                         ret = field->u.w.read(dev, offset, (u16 *) value,
54                                               entry->data);
55                 break;
56         case 4:
57                 if (field->u.dw.read)
58                         ret = field->u.dw.read(dev, offset, value, entry->data);
59                 break;
60         }
61         return ret;
62 }
63
64 static int conf_space_write(struct pci_dev *dev,
65                             const struct config_field_entry *entry,
66                             int offset, u32 value)
67 {
68         int ret = 0;
69         const struct config_field *field = entry->field;
70
71         switch (field->size) {
72         case 1:
73                 if (field->u.b.write)
74                         ret = field->u.b.write(dev, offset, (u8) value,
75                                                entry->data);
76                 break;
77         case 2:
78                 if (field->u.w.write)
79                         ret = field->u.w.write(dev, offset, (u16) value,
80                                                entry->data);
81                 break;
82         case 4:
83                 if (field->u.dw.write)
84                         ret = field->u.dw.write(dev, offset, value,
85                                                 entry->data);
86                 break;
87         }
88         return ret;
89 }
90
91 static inline u32 get_mask(int size)
92 {
93         if (size == 1)
94                 return 0xff;
95         else if (size == 2)
96                 return 0xffff;
97         else
98                 return 0xffffffff;
99 }
100
101 static inline int valid_request(int offset, int size)
102 {
103         /* Validate request (no un-aligned requests) */
104         if ((size == 1 || size == 2 || size == 4) && (offset % size) == 0)
105                 return 1;
106         return 0;
107 }
108
109 static inline u32 merge_value(u32 val, u32 new_val, u32 new_val_mask,
110                               int offset)
111 {
112         if (offset >= 0) {
113                 new_val_mask <<= (offset * 8);
114                 new_val <<= (offset * 8);
115         } else {
116                 new_val_mask >>= (offset * -8);
117                 new_val >>= (offset * -8);
118         }
119         val = (val & ~new_val_mask) | (new_val & new_val_mask);
120
121         return val;
122 }
123
124 static int pcibios_err_to_errno(int err)
125 {
126         switch (err) {
127         case PCIBIOS_SUCCESSFUL:
128                 return XEN_PCI_ERR_success;
129         case PCIBIOS_DEVICE_NOT_FOUND:
130                 return XEN_PCI_ERR_dev_not_found;
131         case PCIBIOS_BAD_REGISTER_NUMBER:
132                 return XEN_PCI_ERR_invalid_offset;
133         case PCIBIOS_FUNC_NOT_SUPPORTED:
134                 return XEN_PCI_ERR_not_implemented;
135         case PCIBIOS_SET_FAILED:
136                 return XEN_PCI_ERR_access_denied;
137         }
138         return err;
139 }
140
141 int pciback_config_read(struct pci_dev *dev, int offset, int size,
142                         u32 *ret_val)
143 {
144         int err = 0;
145         struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
146         const struct config_field_entry *cfg_entry;
147         const struct config_field *field;
148         int req_start, req_end, field_start, field_end;
149         /* if read fails for any reason, return 0
150          * (as if device didn't respond) */
151         u32 value = 0, tmp_val;
152
153         if (unlikely(verbose_request))
154                 printk(KERN_DEBUG "pciback: %s: read %d bytes at 0x%x\n",
155                        pci_name(dev), size, offset);
156
157         if (!valid_request(offset, size)) {
158                 err = XEN_PCI_ERR_invalid_offset;
159                 goto out;
160         }
161
162         /* Get the real value first, then modify as appropriate */
163         switch (size) {
164         case 1:
165                 err = pci_read_config_byte(dev, offset, (u8 *) &value);
166                 break;
167         case 2:
168                 err = pci_read_config_word(dev, offset, (u16 *) &value);
169                 break;
170         case 4:
171                 err = pci_read_config_dword(dev, offset, &value);
172                 break;
173         }
174
175         list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
176                 field = cfg_entry->field;
177
178                 req_start = offset;
179                 req_end = offset + size;
180                 field_start = OFFSET(cfg_entry);
181                 field_end = OFFSET(cfg_entry) + field->size;
182
183                 if ((req_start >= field_start && req_start < field_end)
184                     || (req_end > field_start && req_end <= field_end)) {
185                         err = conf_space_read(dev, cfg_entry, field_start,
186                                               &tmp_val);
187                         if (err)
188                                 goto out;
189
190                         value = merge_value(value, tmp_val,
191                                             get_mask(field->size),
192                                             field_start - req_start);
193                 }
194         }
195
196 out:
197         if (unlikely(verbose_request))
198                 printk(KERN_DEBUG "pciback: %s: read %d bytes at 0x%x = %x\n",
199                        pci_name(dev), size, offset, value);
200
201         *ret_val = value;
202         return pcibios_err_to_errno(err);
203 }
204
205 int pciback_config_write(struct pci_dev *dev, int offset, int size, u32 value)
206 {
207         int err = 0, handled = 0;
208         struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
209         const struct config_field_entry *cfg_entry;
210         const struct config_field *field;
211         u32 tmp_val;
212         int req_start, req_end, field_start, field_end;
213
214         if (unlikely(verbose_request))
215                 printk(KERN_DEBUG
216                        "pciback: %s: write request %d bytes at 0x%x = %x\n",
217                        pci_name(dev), size, offset, value);
218
219         if (!valid_request(offset, size))
220                 return XEN_PCI_ERR_invalid_offset;
221
222         list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
223                 field = cfg_entry->field;
224
225                 req_start = offset;
226                 req_end = offset + size;
227                 field_start = OFFSET(cfg_entry);
228                 field_end = OFFSET(cfg_entry) + field->size;
229
230                 if ((req_start >= field_start && req_start < field_end)
231                     || (req_end > field_start && req_end <= field_end)) {
232                         tmp_val = 0;
233
234                         err = pciback_config_read(dev, field_start,
235                                                   field->size, &tmp_val);
236                         if (err)
237                                 break;
238
239                         tmp_val = merge_value(tmp_val, value, get_mask(size),
240                                               req_start - field_start);
241
242                         err = conf_space_write(dev, cfg_entry, field_start,
243                                                tmp_val);
244
245                         /* handled is set true here, but not every byte
246                          * may have been written! Properly detecting if
247                          * every byte is handled is unnecessary as the
248                          * flag is used to detect devices that need
249                          * special helpers to work correctly.
250                          */
251                         handled = 1;
252                 }
253         }
254
255         if (!handled && !err) {
256                 /* By default, anything not specificially handled above is
257                  * read-only. The permissive flag changes this behavior so
258                  * that anything not specifically handled above is writable.
259                  * This means that some fields may still be read-only because
260                  * they have entries in the config_field list that intercept
261                  * the write and do nothing. */
262                 if (dev_data->permissive || permissive) {
263                         switch (size) {
264                         case 1:
265                                 err = pci_write_config_byte(dev, offset,
266                                                             (u8) value);
267                                 break;
268                         case 2:
269                                 err = pci_write_config_word(dev, offset,
270                                                             (u16) value);
271                                 break;
272                         case 4:
273                                 err = pci_write_config_dword(dev, offset,
274                                                              (u32) value);
275                                 break;
276                         }
277                 } else if (!dev_data->warned_on_write) {
278                         dev_data->warned_on_write = 1;
279                         dev_warn(&dev->dev, "Driver tried to write to a "
280                                  "read-only configuration space field at offset"
281                                  " 0x%x, size %d. This may be harmless, but if "
282                                  "you have problems with your device:\n"
283                                  "1) see permissive attribute in sysfs\n"
284                                  "2) report problems to the xen-devel "
285                                  "mailing list along with details of your "
286                                  "device obtained from lspci.\n", offset, size);
287                 }
288         }
289
290         return pcibios_err_to_errno(err);
291 }
292
293 void pciback_config_free_dyn_fields(struct pci_dev *dev)
294 {
295         struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
296         struct config_field_entry *cfg_entry, *t;
297         const struct config_field *field;
298
299         dev_dbg(&dev->dev, "free-ing dynamically allocated virtual "
300                            "configuration space fields\n");
301         if (!dev_data)
302                 return;
303
304         list_for_each_entry_safe(cfg_entry, t, &dev_data->config_fields, list) {
305                 field = cfg_entry->field;
306
307                 if (field->clean) {
308                         field->clean((struct config_field *)field);
309
310                         kfree(cfg_entry->data);
311
312                         list_del(&cfg_entry->list);
313                         kfree(cfg_entry);
314                 }
315
316         }
317 }
318
319 void pciback_config_reset_dev(struct pci_dev *dev)
320 {
321         struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
322         const struct config_field_entry *cfg_entry;
323         const struct config_field *field;
324
325         dev_dbg(&dev->dev, "resetting virtual configuration space\n");
326         if (!dev_data)
327                 return;
328
329         list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
330                 field = cfg_entry->field;
331
332                 if (field->reset)
333                         field->reset(dev, OFFSET(cfg_entry), cfg_entry->data);
334         }
335 }
336
337 void pciback_config_free_dev(struct pci_dev *dev)
338 {
339         struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
340         struct config_field_entry *cfg_entry, *t;
341         const struct config_field *field;
342
343         dev_dbg(&dev->dev, "free-ing virtual configuration space fields\n");
344         if (!dev_data)
345                 return;
346
347         list_for_each_entry_safe(cfg_entry, t, &dev_data->config_fields, list) {
348                 list_del(&cfg_entry->list);
349
350                 field = cfg_entry->field;
351
352                 if (field->release)
353                         field->release(dev, OFFSET(cfg_entry), cfg_entry->data);
354
355                 kfree(cfg_entry);
356         }
357 }
358
359 int pciback_config_add_field_offset(struct pci_dev *dev,
360                                     const struct config_field *field,
361                                     unsigned int base_offset)
362 {
363         int err = 0;
364         struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
365         struct config_field_entry *cfg_entry;
366         void *tmp;
367
368         cfg_entry = kmalloc(sizeof(*cfg_entry), GFP_KERNEL);
369         if (!cfg_entry) {
370                 err = -ENOMEM;
371                 goto out;
372         }
373
374         cfg_entry->data = NULL;
375         cfg_entry->field = field;
376         cfg_entry->base_offset = base_offset;
377
378         /* silently ignore duplicate fields */
379         err = pciback_field_is_dup(dev, OFFSET(cfg_entry));
380         if (err)
381                 goto out;
382
383         if (field->init) {
384                 tmp = field->init(dev, OFFSET(cfg_entry));
385
386                 if (IS_ERR(tmp)) {
387                         err = PTR_ERR(tmp);
388                         goto out;
389                 }
390
391                 cfg_entry->data = tmp;
392         }
393
394         dev_dbg(&dev->dev, "added config field at offset 0x%02x\n",
395                 OFFSET(cfg_entry));
396         list_add_tail(&cfg_entry->list, &dev_data->config_fields);
397
398 out:
399         if (err)
400                 kfree(cfg_entry);
401
402         return err;
403 }
404
405 /* This sets up the device's virtual configuration space to keep track of
406  * certain registers (like the base address registers (BARs) so that we can
407  * keep the client from manipulating them directly.
408  */
409 int pciback_config_init_dev(struct pci_dev *dev)
410 {
411         int err = 0;
412         struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
413
414         dev_dbg(&dev->dev, "initializing virtual configuration space\n");
415
416         INIT_LIST_HEAD(&dev_data->config_fields);
417
418         err = pciback_config_header_add_fields(dev);
419         if (err)
420                 goto out;
421
422         err = pciback_config_capability_add_fields(dev);
423         if (err)
424                 goto out;
425
426         err = pciback_config_quirks_init(dev);
427
428 out:
429         return err;
430 }
431
432 int pciback_config_init(void)
433 {
434         return pciback_config_capability_init();
435 }