aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/setup-res.c
diff options
context:
space:
mode:
authorYinghai Lu <yinghai@kernel.org>2009-04-23 23:49:25 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-06-11 15:04:07 -0400
commitd09ee9687e027fc7d2c6b95daf05a8ef3ff06340 (patch)
treea7423042ba31ae5c1eb709d0e03115961b2b63b3 /drivers/pci/setup-res.c
parent1f82de10d6b1d845155363c895c552e61b36b51a (diff)
PCI: improve resource allocation under transparent bridges
We could run out of space under under 4g, but devices under transparent bridges can use 64bit resources, so keep trying on the parent bus until we hit a non-transparent bridge. Impact: better support for assigning unassigned resources Reviewed-by: Ivan Kokshaysky <ink@jurassic.park.msu.ru> Signed-off-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/setup-res.c')
-rw-r--r--drivers/pci/setup-res.c49
1 files changed, 36 insertions, 13 deletions
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 3039fcb86afc..0b6908b48935 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -135,23 +135,16 @@ void pci_disable_bridge_window(struct pci_dev *dev)
135} 135}
136#endif /* CONFIG_PCI_QUIRKS */ 136#endif /* CONFIG_PCI_QUIRKS */
137 137
138int pci_assign_resource(struct pci_dev *dev, int resno) 138static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
139 int resno)
139{ 140{
140 struct pci_bus *bus = dev->bus;
141 struct resource *res = dev->resource + resno; 141 struct resource *res = dev->resource + resno;
142 resource_size_t size, min, align; 142 resource_size_t size, min, align;
143 int ret; 143 int ret;
144 144
145 size = resource_size(res); 145 size = resource_size(res);
146 min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM; 146 min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
147
148 align = resource_alignment(res); 147 align = resource_alignment(res);
149 if (!align) {
150 dev_info(&dev->dev, "BAR %d: can't allocate resource (bogus "
151 "alignment) %pR flags %#lx\n",
152 resno, res, res->flags);
153 return -EINVAL;
154 }
155 148
156 /* First, try exact prefetching match.. */ 149 /* First, try exact prefetching match.. */
157 ret = pci_bus_alloc_resource(bus, res, size, align, min, 150 ret = pci_bus_alloc_resource(bus, res, size, align, min,
@@ -169,10 +162,7 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
169 pcibios_align_resource, dev); 162 pcibios_align_resource, dev);
170 } 163 }
171 164
172 if (ret) { 165 if (!ret) {
173 dev_info(&dev->dev, "BAR %d: can't allocate %s resource %pR\n",
174 resno, res->flags & IORESOURCE_IO ? "I/O" : "mem", res);
175 } else {
176 res->flags &= ~IORESOURCE_STARTALIGN; 166 res->flags &= ~IORESOURCE_STARTALIGN;
177 if (resno < PCI_BRIDGE_RESOURCES) 167 if (resno < PCI_BRIDGE_RESOURCES)
178 pci_update_resource(dev, resno); 168 pci_update_resource(dev, resno);
@@ -181,6 +171,39 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
181 return ret; 171 return ret;
182} 172}
183 173
174int pci_assign_resource(struct pci_dev *dev, int resno)
175{
176 struct resource *res = dev->resource + resno;
177 resource_size_t align;
178 struct pci_bus *bus;
179 int ret;
180
181 align = resource_alignment(res);
182 if (!align) {
183 dev_info(&dev->dev, "BAR %d: can't allocate resource (bogus "
184 "alignment) %pR flags %#lx\n",
185 resno, res, res->flags);
186 return -EINVAL;
187 }
188
189 bus = dev->bus;
190 while ((ret = __pci_assign_resource(bus, dev, resno))) {
191 if (bus->parent && bus->self->transparent)
192 bus = bus->parent;
193 else
194 bus = NULL;
195 if (bus)
196 continue;
197 break;
198 }
199
200 if (ret)
201 dev_info(&dev->dev, "BAR %d: can't allocate %s resource %pR\n",
202 resno, res->flags & IORESOURCE_IO ? "I/O" : "mem", res);
203
204 return ret;
205}
206
184#if 0 207#if 0
185int pci_assign_resource_fixed(struct pci_dev *dev, int resno) 208int pci_assign_resource_fixed(struct pci_dev *dev, int resno)
186{ 209{