Skip to content

Commit dbf9826

Browse files
Lorenzo Pieralisibjorn-helgaas
authored andcommitted
PCI: generic: Convert to DT resource parsing API
In order to consolidate DT configuration for PCI host controllers in the kernel, a new API, of_pci_get_host_bridge_resources(), was developed to allow parsing and assigning IO/BUS/MEM resources from DT, removing duplicated code present in the majority of PCI host driver implementations. Convert the existing PCI generic host controller driver to the new API. Most of the code parsing ranges and creating resources is now delegated to the of_pci_get_host_bridge_resources() API. The PCI host controller code filters the resulting resource list and maps IO space by using the newly introduced pci_ioremap_iospace() API. New code supports only one IO resource per generic host controller, which should cater for all existing host controller configurations. [bhelgaas: changelog] Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Will Deacon <will.deacon@arm.com>
1 parent a5525b2 commit dbf9826

File tree

1 file changed

+27
-93
lines changed

1 file changed

+27
-93
lines changed

drivers/pci/host/pci-host-generic.c

Lines changed: 27 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ struct gen_pci_cfg_bus_ops {
3232

3333
struct gen_pci_cfg_windows {
3434
struct resource res;
35-
struct resource bus_range;
35+
struct resource *bus_range;
3636
void __iomem **win;
3737

3838
const struct gen_pci_cfg_bus_ops *ops;
@@ -50,7 +50,7 @@ static void __iomem *gen_pci_map_cfg_bus_cam(struct pci_bus *bus,
5050
{
5151
struct pci_sys_data *sys = bus->sysdata;
5252
struct gen_pci *pci = sys->private_data;
53-
resource_size_t idx = bus->number - pci->cfg.bus_range.start;
53+
resource_size_t idx = bus->number - pci->cfg.bus_range->start;
5454

5555
return pci->cfg.win[idx] + ((devfn << 8) | where);
5656
}
@@ -66,7 +66,7 @@ static void __iomem *gen_pci_map_cfg_bus_ecam(struct pci_bus *bus,
6666
{
6767
struct pci_sys_data *sys = bus->sysdata;
6868
struct gen_pci *pci = sys->private_data;
69-
resource_size_t idx = bus->number - pci->cfg.bus_range.start;
69+
resource_size_t idx = bus->number - pci->cfg.bus_range->start;
7070

7171
return pci->cfg.win[idx] + ((devfn << 12) | where);
7272
}
@@ -138,106 +138,50 @@ static const struct of_device_id gen_pci_of_match[] = {
138138
};
139139
MODULE_DEVICE_TABLE(of, gen_pci_of_match);
140140

141-
static int gen_pci_calc_io_offset(struct device *dev,
142-
struct of_pci_range *range,
143-
struct resource *res,
144-
resource_size_t *offset)
145-
{
146-
static atomic_t wins = ATOMIC_INIT(0);
147-
int err, idx, max_win;
148-
unsigned int window;
149-
150-
if (!PAGE_ALIGNED(range->cpu_addr))
151-
return -EINVAL;
152-
153-
max_win = (IO_SPACE_LIMIT + 1) / SZ_64K;
154-
idx = atomic_inc_return(&wins);
155-
if (idx > max_win)
156-
return -ENOSPC;
157-
158-
window = (idx - 1) * SZ_64K;
159-
err = pci_ioremap_io(window, range->cpu_addr);
160-
if (err)
161-
return err;
162-
163-
of_pci_range_to_resource(range, dev->of_node, res);
164-
res->start = window;
165-
res->end = res->start + range->size - 1;
166-
*offset = window - range->pci_addr;
167-
return 0;
168-
}
169-
170-
static int gen_pci_calc_mem_offset(struct device *dev,
171-
struct of_pci_range *range,
172-
struct resource *res,
173-
resource_size_t *offset)
174-
{
175-
of_pci_range_to_resource(range, dev->of_node, res);
176-
*offset = range->cpu_addr - range->pci_addr;
177-
return 0;
178-
}
179-
180141
static void gen_pci_release_of_pci_ranges(struct gen_pci *pci)
181142
{
182-
struct pci_host_bridge_window *win;
183-
184-
list_for_each_entry(win, &pci->resources, list)
185-
release_resource(win->res);
186-
187143
pci_free_resource_list(&pci->resources);
188144
}
189145

190146
static int gen_pci_parse_request_of_pci_ranges(struct gen_pci *pci)
191147
{
192-
struct of_pci_range range;
193-
struct of_pci_range_parser parser;
194148
int err, res_valid = 0;
195149
struct device *dev = pci->host.dev.parent;
196150
struct device_node *np = dev->of_node;
151+
resource_size_t iobase;
152+
struct pci_host_bridge_window *win;
197153

198-
if (of_pci_range_parser_init(&parser, np)) {
199-
dev_err(dev, "missing \"ranges\" property\n");
200-
return -EINVAL;
201-
}
154+
err = of_pci_get_host_bridge_resources(np, 0, 0xff, &pci->resources,
155+
&iobase);
156+
if (err)
157+
return err;
202158

203-
for_each_of_pci_range(&parser, &range) {
204-
struct resource *parent, *res;
205-
resource_size_t offset;
206-
u32 restype = range.flags & IORESOURCE_TYPE_BITS;
159+
list_for_each_entry(win, &pci->resources, list) {
160+
struct resource *parent, *res = win->res;
207161

208-
res = devm_kmalloc(dev, sizeof(*res), GFP_KERNEL);
209-
if (!res) {
210-
err = -ENOMEM;
211-
goto out_release_res;
212-
}
213-
214-
switch (restype) {
162+
switch (resource_type(res)) {
215163
case IORESOURCE_IO:
216164
parent = &ioport_resource;
217-
err = gen_pci_calc_io_offset(dev, &range, res, &offset);
165+
err = pci_remap_iospace(res, iobase);
166+
if (err) {
167+
dev_warn(dev, "error %d: failed to map resource %pR\n",
168+
err, res);
169+
continue;
170+
}
218171
break;
219172
case IORESOURCE_MEM:
220173
parent = &iomem_resource;
221-
err = gen_pci_calc_mem_offset(dev, &range, res, &offset);
222-
res_valid |= !(res->flags & IORESOURCE_PREFETCH || err);
174+
res_valid |= !(res->flags & IORESOURCE_PREFETCH);
223175
break;
176+
case IORESOURCE_BUS:
177+
pci->cfg.bus_range = res;
224178
default:
225-
err = -EINVAL;
226179
continue;
227180
}
228181

229-
if (err) {
230-
dev_warn(dev,
231-
"error %d: failed to add resource [type 0x%x, %lld bytes]\n",
232-
err, restype, range.size);
233-
continue;
234-
}
235-
236-
err = request_resource(parent, res);
182+
err = devm_request_resource(dev, parent, res);
237183
if (err)
238184
goto out_release_res;
239-
240-
pci_add_resource_offset(&pci->resources, res, offset);
241185
}
242186

243187
if (!res_valid) {
@@ -262,27 +206,19 @@ static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci)
262206
struct device *dev = pci->host.dev.parent;
263207
struct device_node *np = dev->of_node;
264208

265-
if (of_pci_parse_bus_range(np, &pci->cfg.bus_range))
266-
pci->cfg.bus_range = (struct resource) {
267-
.name = np->name,
268-
.start = 0,
269-
.end = 0xff,
270-
.flags = IORESOURCE_BUS,
271-
};
272-
273209
err = of_address_to_resource(np, 0, &pci->cfg.res);
274210
if (err) {
275211
dev_err(dev, "missing \"reg\" property\n");
276212
return err;
277213
}
278214

279215
/* Limit the bus-range to fit within reg */
280-
bus_max = pci->cfg.bus_range.start +
216+
bus_max = pci->cfg.bus_range->start +
281217
(resource_size(&pci->cfg.res) >> pci->cfg.ops->bus_shift) - 1;
282-
pci->cfg.bus_range.end = min_t(resource_size_t, pci->cfg.bus_range.end,
283-
bus_max);
218+
pci->cfg.bus_range->end = min_t(resource_size_t,
219+
pci->cfg.bus_range->end, bus_max);
284220

285-
pci->cfg.win = devm_kcalloc(dev, resource_size(&pci->cfg.bus_range),
221+
pci->cfg.win = devm_kcalloc(dev, resource_size(pci->cfg.bus_range),
286222
sizeof(*pci->cfg.win), GFP_KERNEL);
287223
if (!pci->cfg.win)
288224
return -ENOMEM;
@@ -293,7 +229,7 @@ static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci)
293229
"Configuration Space"))
294230
return -ENOMEM;
295231

296-
bus_range = &pci->cfg.bus_range;
232+
bus_range = pci->cfg.bus_range;
297233
for (busn = bus_range->start; busn <= bus_range->end; ++busn) {
298234
u32 idx = busn - bus_range->start;
299235
u32 sz = 1 << pci->cfg.ops->bus_shift;
@@ -305,8 +241,6 @@ static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci)
305241
return -ENOMEM;
306242
}
307243

308-
/* Register bus resource */
309-
pci_add_resource(&pci->resources, bus_range);
310244
return 0;
311245
}
312246

0 commit comments

Comments
 (0)