Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
setup-res.c
Go to the documentation of this file.
1 /*
2  * drivers/pci/setup-res.c
3  *
4  * Extruded from code written by
5  * Dave Rusling ([email protected])
6  * David Mosberger ([email protected])
7  * David Miller ([email protected])
8  *
9  * Support routines for initializing a PCI subsystem.
10  */
11 
12 /* fixed for multiple pci buses, 1999 Andrea Arcangeli <[email protected]> */
13 
14 /*
15  * Nov 2000, Ivan Kokshaysky <[email protected]>
16  * Resource sorting
17  */
18 
19 #include <linux/init.h>
20 #include <linux/kernel.h>
21 #include <linux/export.h>
22 #include <linux/pci.h>
23 #include <linux/errno.h>
24 #include <linux/ioport.h>
25 #include <linux/cache.h>
26 #include <linux/slab.h>
27 #include "pci.h"
28 
29 
30 void pci_update_resource(struct pci_dev *dev, int resno)
31 {
32  struct pci_bus_region region;
33  bool disable;
34  u16 cmd;
35  u32 new, check, mask;
36  int reg;
37  enum pci_bar_type type;
38  struct resource *res = dev->resource + resno;
39 
40  /*
41  * Ignore resources for unimplemented BARs and unused resource slots
42  * for 64 bit BARs.
43  */
44  if (!res->flags)
45  return;
46 
47  /*
48  * Ignore non-moveable resources. This might be legacy resources for
49  * which no functional BAR register exists or another important
50  * system resource we shouldn't move around.
51  */
52  if (res->flags & IORESOURCE_PCI_FIXED)
53  return;
54 
55  pcibios_resource_to_bus(dev, &region, res);
56 
57  new = region.start | (res->flags & PCI_REGION_FLAG_MASK);
58  if (res->flags & IORESOURCE_IO)
60  else
62 
63  reg = pci_resource_bar(dev, resno, &type);
64  if (!reg)
65  return;
66  if (type != pci_bar_unknown) {
67  if (!(res->flags & IORESOURCE_ROM_ENABLE))
68  return;
70  }
71 
72  /*
73  * We can't update a 64-bit BAR atomically, so when possible,
74  * disable decoding so that a half-updated BAR won't conflict
75  * with another device.
76  */
77  disable = (res->flags & IORESOURCE_MEM_64) && !dev->mmio_always_on;
78  if (disable) {
79  pci_read_config_word(dev, PCI_COMMAND, &cmd);
80  pci_write_config_word(dev, PCI_COMMAND,
81  cmd & ~PCI_COMMAND_MEMORY);
82  }
83 
84  pci_write_config_dword(dev, reg, new);
85  pci_read_config_dword(dev, reg, &check);
86 
87  if ((new ^ check) & mask) {
88  dev_err(&dev->dev, "BAR %d: error updating (%#08x != %#08x)\n",
89  resno, new, check);
90  }
91 
92  if (res->flags & IORESOURCE_MEM_64) {
93  new = region.start >> 16 >> 16;
94  pci_write_config_dword(dev, reg + 4, new);
95  pci_read_config_dword(dev, reg + 4, &check);
96  if (check != new) {
97  dev_err(&dev->dev, "BAR %d: error updating "
98  "(high %#08x != %#08x)\n", resno, new, check);
99  }
100  }
101 
102  if (disable)
103  pci_write_config_word(dev, PCI_COMMAND, cmd);
104 
105  res->flags &= ~IORESOURCE_UNSET;
106  dev_dbg(&dev->dev, "BAR %d: set to %pR (PCI address [%#llx-%#llx])\n",
107  resno, res, (unsigned long long)region.start,
108  (unsigned long long)region.end);
109 }
110 
112 {
113  struct resource *res = &dev->resource[resource];
114  struct resource *root, *conflict;
115 
116  root = pci_find_parent_resource(dev, res);
117  if (!root) {
118  dev_info(&dev->dev, "no compatible bridge window for %pR\n",
119  res);
120  return -EINVAL;
121  }
122 
123  conflict = request_resource_conflict(root, res);
124  if (conflict) {
125  dev_info(&dev->dev,
126  "address space collision: %pR conflicts with %s %pR\n",
127  res, conflict->name, conflict);
128  return -EBUSY;
129  }
130 
131  return 0;
132 }
134 
136 {
137  dev_info(&dev->dev, "disabling bridge mem windows\n");
138 
139  /* MMIO Base/Limit */
140  pci_write_config_dword(dev, PCI_MEMORY_BASE, 0x0000fff0);
141 
142  /* Prefetchable MMIO Base/Limit */
143  pci_write_config_dword(dev, PCI_PREF_LIMIT_UPPER32, 0);
144  pci_write_config_dword(dev, PCI_PREF_MEMORY_BASE, 0x0000fff0);
145  pci_write_config_dword(dev, PCI_PREF_BASE_UPPER32, 0xffffffff);
146 }
147 
148 /*
149  * Generic function that returns a value indicating that the device's
150  * original BIOS BAR address was not saved and so is not available for
151  * reinstatement.
152  *
153  * Can be over-ridden by architecture specific code that implements
154  * reinstatement functionality rather than leaving it disabled when
155  * normal allocation attempts fail.
156  */
158 {
159  return 0;
160 }
161 
162 static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev,
163  int resno, resource_size_t size)
164 {
165  struct resource *root, *conflict;
166  resource_size_t fw_addr, start, end;
167  int ret = 0;
168 
169  fw_addr = pcibios_retrieve_fw_addr(dev, resno);
170  if (!fw_addr)
171  return 1;
172 
173  start = res->start;
174  end = res->end;
175  res->start = fw_addr;
176  res->end = res->start + size - 1;
177 
178  root = pci_find_parent_resource(dev, res);
179  if (!root) {
180  if (res->flags & IORESOURCE_IO)
181  root = &ioport_resource;
182  else
183  root = &iomem_resource;
184  }
185 
186  dev_info(&dev->dev, "BAR %d: trying firmware assignment %pR\n",
187  resno, res);
188  conflict = request_resource_conflict(root, res);
189  if (conflict) {
190  dev_info(&dev->dev,
191  "BAR %d: %pR conflicts with %s %pR\n", resno,
192  res, conflict->name, conflict);
193  res->start = start;
194  res->end = end;
195  ret = 1;
196  }
197  return ret;
198 }
199 
200 static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
201  int resno, resource_size_t size, resource_size_t align)
202 {
203  struct resource *res = dev->resource + resno;
205  int ret;
206 
208 
209  /* First, try exact prefetching match.. */
210  ret = pci_bus_alloc_resource(bus, res, size, align, min,
213 
214  if (ret < 0 && (res->flags & IORESOURCE_PREFETCH)) {
215  /*
216  * That failed.
217  *
218  * But a prefetching area can handle a non-prefetching
219  * window (it will just not perform as well).
220  */
221  ret = pci_bus_alloc_resource(bus, res, size, align, min, 0,
223  }
224  return ret;
225 }
226 
227 static int _pci_assign_resource(struct pci_dev *dev, int resno,
228  resource_size_t size, resource_size_t min_align)
229 {
230  struct resource *res = dev->resource + resno;
231  struct pci_bus *bus;
232  int ret;
233  char *type;
234 
235  bus = dev->bus;
236  while ((ret = __pci_assign_resource(bus, dev, resno, size, min_align))) {
237  if (!bus->parent || !bus->self->transparent)
238  break;
239  bus = bus->parent;
240  }
241 
242  if (ret) {
243  if (res->flags & IORESOURCE_MEM)
244  if (res->flags & IORESOURCE_PREFETCH)
245  type = "mem pref";
246  else
247  type = "mem";
248  else if (res->flags & IORESOURCE_IO)
249  type = "io";
250  else
251  type = "unknown";
252  dev_info(&dev->dev,
253  "BAR %d: can't assign %s (size %#llx)\n",
254  resno, type, (unsigned long long) resource_size(res));
255  }
256 
257  return ret;
258 }
259 
260 int pci_assign_resource(struct pci_dev *dev, int resno)
261 {
262  struct resource *res = dev->resource + resno;
264  struct pci_bus *bus;
265  int ret;
266 
267  align = pci_resource_alignment(dev, res);
268  if (!align) {
269  dev_info(&dev->dev, "BAR %d: can't assign %pR "
270  "(bogus alignment)\n", resno, res);
271  return -EINVAL;
272  }
273 
274  bus = dev->bus;
275  size = resource_size(res);
276  ret = _pci_assign_resource(dev, resno, size, align);
277 
278  /*
279  * If we failed to assign anything, let's try the address
280  * where firmware left it. That at least has a chance of
281  * working, which is better than just leaving it disabled.
282  */
283  if (ret < 0)
284  ret = pci_revert_fw_address(res, dev, resno, size);
285 
286  if (!ret) {
287  res->flags &= ~IORESOURCE_STARTALIGN;
288  dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res);
289  if (resno < PCI_BRIDGE_RESOURCES)
290  pci_update_resource(dev, resno);
291  }
292  return ret;
293 }
294 
295 int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsize,
296  resource_size_t min_align)
297 {
298  struct resource *res = dev->resource + resno;
299  resource_size_t new_size;
300  int ret;
301 
302  if (!res->parent) {
303  dev_info(&dev->dev, "BAR %d: can't reassign an unassigned resource %pR "
304  "\n", resno, res);
305  return -EINVAL;
306  }
307 
308  /* already aligned with min_align */
309  new_size = resource_size(res) + addsize;
310  ret = _pci_assign_resource(dev, resno, new_size, min_align);
311  if (!ret) {
312  res->flags &= ~IORESOURCE_STARTALIGN;
313  dev_info(&dev->dev, "BAR %d: reassigned %pR\n", resno, res);
314  if (resno < PCI_BRIDGE_RESOURCES)
315  pci_update_resource(dev, resno);
316  }
317  return ret;
318 }
319 
320 int pci_enable_resources(struct pci_dev *dev, int mask)
321 {
322  u16 cmd, old_cmd;
323  int i;
324  struct resource *r;
325 
326  pci_read_config_word(dev, PCI_COMMAND, &cmd);
327  old_cmd = cmd;
328 
329  for (i = 0; i < PCI_NUM_RESOURCES; i++) {
330  if (!(mask & (1 << i)))
331  continue;
332 
333  r = &dev->resource[i];
334 
335  if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
336  continue;
337  if ((i == PCI_ROM_RESOURCE) &&
338  (!(r->flags & IORESOURCE_ROM_ENABLE)))
339  continue;
340 
341  if (!r->parent) {
342  dev_err(&dev->dev, "device not available "
343  "(can't reserve %pR)\n", r);
344  return -EINVAL;
345  }
346 
347  if (r->flags & IORESOURCE_IO)
348  cmd |= PCI_COMMAND_IO;
349  if (r->flags & IORESOURCE_MEM)
350  cmd |= PCI_COMMAND_MEMORY;
351  }
352 
353  if (cmd != old_cmd) {
354  dev_info(&dev->dev, "enabling device (%04x -> %04x)\n",
355  old_cmd, cmd);
356  pci_write_config_word(dev, PCI_COMMAND, cmd);
357  }
358  return 0;
359 }