GNU Linux-libre 4.9.333-gnu1
[releases.git] / drivers / xen / xen-pciback / conf_space_header.c
1 /*
2  * PCI Backend - Handles the virtual fields in the configuration space headers.
3  *
4  * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
5  */
6
7 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
8
9 #include <linux/kernel.h>
10 #include <linux/pci.h>
11 #include "pciback.h"
12 #include "conf_space.h"
13
14 struct pci_cmd_info {
15         u16 val;
16 };
17
18 struct pci_bar_info {
19         u32 val;
20         u32 len_val;
21         int which;
22 };
23
24 #define is_enable_cmd(value) ((value)&(PCI_COMMAND_MEMORY|PCI_COMMAND_IO))
25 #define is_master_cmd(value) ((value)&PCI_COMMAND_MASTER)
26
27 /* Bits guests are allowed to control in permissive mode. */
28 #define PCI_COMMAND_GUEST (PCI_COMMAND_MASTER|PCI_COMMAND_SPECIAL| \
29                            PCI_COMMAND_INVALIDATE|PCI_COMMAND_VGA_PALETTE| \
30                            PCI_COMMAND_WAIT|PCI_COMMAND_FAST_BACK)
31
32 static void *command_init(struct pci_dev *dev, int offset)
33 {
34         struct pci_cmd_info *cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
35         int err;
36
37         if (!cmd)
38                 return ERR_PTR(-ENOMEM);
39
40         err = pci_read_config_word(dev, PCI_COMMAND, &cmd->val);
41         if (err) {
42                 kfree(cmd);
43                 return ERR_PTR(err);
44         }
45
46         return cmd;
47 }
48
49 static int command_read(struct pci_dev *dev, int offset, u16 *value, void *data)
50 {
51         int ret = pci_read_config_word(dev, offset, value);
52         const struct pci_cmd_info *cmd = data;
53
54         *value &= PCI_COMMAND_GUEST;
55         *value |= cmd->val & ~PCI_COMMAND_GUEST;
56
57         return ret;
58 }
59
60 static int command_write(struct pci_dev *dev, int offset, u16 value, void *data)
61 {
62         struct xen_pcibk_dev_data *dev_data;
63         int err;
64         u16 val;
65         struct pci_cmd_info *cmd = data;
66
67         dev_data = pci_get_drvdata(dev);
68         if (!pci_is_enabled(dev) && is_enable_cmd(value)) {
69                 if (unlikely(verbose_request))
70                         printk(KERN_DEBUG DRV_NAME ": %s: enable\n",
71                                pci_name(dev));
72                 err = pci_enable_device(dev);
73                 if (err)
74                         return err;
75                 if (dev_data)
76                         dev_data->enable_intx = 1;
77         } else if (pci_is_enabled(dev) && !is_enable_cmd(value)) {
78                 if (unlikely(verbose_request))
79                         printk(KERN_DEBUG DRV_NAME ": %s: disable\n",
80                                pci_name(dev));
81                 pci_disable_device(dev);
82                 if (dev_data)
83                         dev_data->enable_intx = 0;
84         }
85
86         if (!dev->is_busmaster && is_master_cmd(value)) {
87                 if (unlikely(verbose_request))
88                         printk(KERN_DEBUG DRV_NAME ": %s: set bus master\n",
89                                pci_name(dev));
90                 pci_set_master(dev);
91         } else if (dev->is_busmaster && !is_master_cmd(value)) {
92                 if (unlikely(verbose_request))
93                         printk(KERN_DEBUG DRV_NAME ": %s: clear bus master\n",
94                                pci_name(dev));
95                 pci_clear_master(dev);
96         }
97
98         if (!(cmd->val & PCI_COMMAND_INVALIDATE) &&
99             (value & PCI_COMMAND_INVALIDATE)) {
100                 if (unlikely(verbose_request))
101                         printk(KERN_DEBUG
102                                DRV_NAME ": %s: enable memory-write-invalidate\n",
103                                pci_name(dev));
104                 err = pci_set_mwi(dev);
105                 if (err) {
106                         pr_warn("%s: cannot enable memory-write-invalidate (%d)\n",
107                                 pci_name(dev), err);
108                         value &= ~PCI_COMMAND_INVALIDATE;
109                 }
110         } else if ((cmd->val & PCI_COMMAND_INVALIDATE) &&
111                    !(value & PCI_COMMAND_INVALIDATE)) {
112                 if (unlikely(verbose_request))
113                         printk(KERN_DEBUG
114                                DRV_NAME ": %s: disable memory-write-invalidate\n",
115                                pci_name(dev));
116                 pci_clear_mwi(dev);
117         }
118
119         cmd->val = value;
120
121         if (!xen_pcibk_permissive && (!dev_data || !dev_data->permissive))
122                 return 0;
123
124         /* Only allow the guest to control certain bits. */
125         err = pci_read_config_word(dev, offset, &val);
126         if (err || val == value)
127                 return err;
128
129         value &= PCI_COMMAND_GUEST;
130         value |= val & ~PCI_COMMAND_GUEST;
131
132         return pci_write_config_word(dev, offset, value);
133 }
134
135 static int rom_write(struct pci_dev *dev, int offset, u32 value, void *data)
136 {
137         struct pci_bar_info *bar = data;
138
139         if (unlikely(!bar)) {
140                 pr_warn(DRV_NAME ": driver data not found for %s\n",
141                        pci_name(dev));
142                 return XEN_PCI_ERR_op_failed;
143         }
144
145         /* A write to obtain the length must happen as a 32-bit write.
146          * This does not (yet) support writing individual bytes
147          */
148         if ((value | ~PCI_ROM_ADDRESS_MASK) == ~0U)
149                 bar->which = 1;
150         else {
151                 u32 tmpval;
152                 pci_read_config_dword(dev, offset, &tmpval);
153                 if (tmpval != bar->val && value == bar->val) {
154                         /* Allow restoration of bar value. */
155                         pci_write_config_dword(dev, offset, bar->val);
156                 }
157                 bar->which = 0;
158         }
159
160         /* Do we need to support enabling/disabling the rom address here? */
161
162         return 0;
163 }
164
165 /* For the BARs, only allow writes which write ~0 or
166  * the correct resource information
167  * (Needed for when the driver probes the resource usage)
168  */
169 static int bar_write(struct pci_dev *dev, int offset, u32 value, void *data)
170 {
171         struct pci_bar_info *bar = data;
172
173         if (unlikely(!bar)) {
174                 pr_warn(DRV_NAME ": driver data not found for %s\n",
175                        pci_name(dev));
176                 return XEN_PCI_ERR_op_failed;
177         }
178
179         /* A write to obtain the length must happen as a 32-bit write.
180          * This does not (yet) support writing individual bytes
181          */
182         if (value == ~0)
183                 bar->which = 1;
184         else {
185                 u32 tmpval;
186                 pci_read_config_dword(dev, offset, &tmpval);
187                 if (tmpval != bar->val && value == bar->val) {
188                         /* Allow restoration of bar value. */
189                         pci_write_config_dword(dev, offset, bar->val);
190                 }
191                 bar->which = 0;
192         }
193
194         return 0;
195 }
196
197 static int bar_read(struct pci_dev *dev, int offset, u32 * value, void *data)
198 {
199         struct pci_bar_info *bar = data;
200
201         if (unlikely(!bar)) {
202                 pr_warn(DRV_NAME ": driver data not found for %s\n",
203                        pci_name(dev));
204                 return XEN_PCI_ERR_op_failed;
205         }
206
207         *value = bar->which ? bar->len_val : bar->val;
208
209         return 0;
210 }
211
212 static void *bar_init(struct pci_dev *dev, int offset)
213 {
214         unsigned int pos;
215         const struct resource *res = dev->resource;
216         struct pci_bar_info *bar = kzalloc(sizeof(*bar), GFP_KERNEL);
217
218         if (!bar)
219                 return ERR_PTR(-ENOMEM);
220
221         if (offset == PCI_ROM_ADDRESS || offset == PCI_ROM_ADDRESS1)
222                 pos = PCI_ROM_RESOURCE;
223         else {
224                 pos = (offset - PCI_BASE_ADDRESS_0) / 4;
225                 if (pos && (res[pos - 1].flags & IORESOURCE_MEM_64)) {
226                         bar->val = res[pos - 1].start >> 32;
227                         bar->len_val = -resource_size(&res[pos - 1]) >> 32;
228                         return bar;
229                 }
230         }
231
232         if (!res[pos].flags ||
233             (res[pos].flags & (IORESOURCE_DISABLED | IORESOURCE_UNSET |
234                                IORESOURCE_BUSY)))
235                 return bar;
236
237         bar->val = res[pos].start |
238                    (res[pos].flags & PCI_REGION_FLAG_MASK);
239         bar->len_val = -resource_size(&res[pos]) |
240                        (res[pos].flags & PCI_REGION_FLAG_MASK);
241
242         return bar;
243 }
244
245 static void bar_reset(struct pci_dev *dev, int offset, void *data)
246 {
247         struct pci_bar_info *bar = data;
248
249         bar->which = 0;
250 }
251
252 static void bar_release(struct pci_dev *dev, int offset, void *data)
253 {
254         kfree(data);
255 }
256
257 static int xen_pcibk_read_vendor(struct pci_dev *dev, int offset,
258                                u16 *value, void *data)
259 {
260         *value = dev->vendor;
261
262         return 0;
263 }
264
265 static int xen_pcibk_read_device(struct pci_dev *dev, int offset,
266                                u16 *value, void *data)
267 {
268         *value = dev->device;
269
270         return 0;
271 }
272
273 static int interrupt_read(struct pci_dev *dev, int offset, u8 * value,
274                           void *data)
275 {
276         *value = (u8) dev->irq;
277
278         return 0;
279 }
280
281 static int bist_write(struct pci_dev *dev, int offset, u8 value, void *data)
282 {
283         u8 cur_value;
284         int err;
285
286         err = pci_read_config_byte(dev, offset, &cur_value);
287         if (err)
288                 goto out;
289
290         if ((cur_value & ~PCI_BIST_START) == (value & ~PCI_BIST_START)
291             || value == PCI_BIST_START)
292                 err = pci_write_config_byte(dev, offset, value);
293
294 out:
295         return err;
296 }
297
298 static const struct config_field header_common[] = {
299         {
300          .offset    = PCI_VENDOR_ID,
301          .size      = 2,
302          .u.w.read  = xen_pcibk_read_vendor,
303         },
304         {
305          .offset    = PCI_DEVICE_ID,
306          .size      = 2,
307          .u.w.read  = xen_pcibk_read_device,
308         },
309         {
310          .offset    = PCI_COMMAND,
311          .size      = 2,
312          .init      = command_init,
313          .release   = bar_release,
314          .u.w.read  = command_read,
315          .u.w.write = command_write,
316         },
317         {
318          .offset    = PCI_INTERRUPT_LINE,
319          .size      = 1,
320          .u.b.read  = interrupt_read,
321         },
322         {
323          .offset    = PCI_INTERRUPT_PIN,
324          .size      = 1,
325          .u.b.read  = xen_pcibk_read_config_byte,
326         },
327         {
328          /* Any side effects of letting driver domain control cache line? */
329          .offset    = PCI_CACHE_LINE_SIZE,
330          .size      = 1,
331          .u.b.read  = xen_pcibk_read_config_byte,
332          .u.b.write = xen_pcibk_write_config_byte,
333         },
334         {
335          .offset    = PCI_LATENCY_TIMER,
336          .size      = 1,
337          .u.b.read  = xen_pcibk_read_config_byte,
338         },
339         {
340          .offset    = PCI_BIST,
341          .size      = 1,
342          .u.b.read  = xen_pcibk_read_config_byte,
343          .u.b.write = bist_write,
344         },
345         {}
346 };
347
348 #define CFG_FIELD_BAR(reg_offset)                       \
349         {                                               \
350         .offset     = reg_offset,                       \
351         .size       = 4,                                \
352         .init       = bar_init,                         \
353         .reset      = bar_reset,                        \
354         .release    = bar_release,                      \
355         .u.dw.read  = bar_read,                         \
356         .u.dw.write = bar_write,                        \
357         }
358
359 #define CFG_FIELD_ROM(reg_offset)                       \
360         {                                               \
361         .offset     = reg_offset,                       \
362         .size       = 4,                                \
363         .init       = bar_init,                         \
364         .reset      = bar_reset,                        \
365         .release    = bar_release,                      \
366         .u.dw.read  = bar_read,                         \
367         .u.dw.write = rom_write,                        \
368         }
369
370 static const struct config_field header_0[] = {
371         CFG_FIELD_BAR(PCI_BASE_ADDRESS_0),
372         CFG_FIELD_BAR(PCI_BASE_ADDRESS_1),
373         CFG_FIELD_BAR(PCI_BASE_ADDRESS_2),
374         CFG_FIELD_BAR(PCI_BASE_ADDRESS_3),
375         CFG_FIELD_BAR(PCI_BASE_ADDRESS_4),
376         CFG_FIELD_BAR(PCI_BASE_ADDRESS_5),
377         CFG_FIELD_ROM(PCI_ROM_ADDRESS),
378         {}
379 };
380
381 static const struct config_field header_1[] = {
382         CFG_FIELD_BAR(PCI_BASE_ADDRESS_0),
383         CFG_FIELD_BAR(PCI_BASE_ADDRESS_1),
384         CFG_FIELD_ROM(PCI_ROM_ADDRESS1),
385         {}
386 };
387
388 int xen_pcibk_config_header_add_fields(struct pci_dev *dev)
389 {
390         int err;
391
392         err = xen_pcibk_config_add_fields(dev, header_common);
393         if (err)
394                 goto out;
395
396         switch (dev->hdr_type) {
397         case PCI_HEADER_TYPE_NORMAL:
398                 err = xen_pcibk_config_add_fields(dev, header_0);
399                 break;
400
401         case PCI_HEADER_TYPE_BRIDGE:
402                 err = xen_pcibk_config_add_fields(dev, header_1);
403                 break;
404
405         default:
406                 err = -EINVAL;
407                 pr_err("%s: Unsupported header type %d!\n",
408                        pci_name(dev), dev->hdr_type);
409                 break;
410         }
411
412 out:
413         return err;
414 }