.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * PCI address cache; allows the lookup of PCI devices based on I/O address |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright IBM Corporation 2004 |
---|
5 | 6 | * Copyright Linas Vepstas <linas@austin.ibm.com> 2004 |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or modify |
---|
8 | | - * it under the terms of the GNU General Public License as published by |
---|
9 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
10 | | - * (at your option) any later version. |
---|
11 | | - * |
---|
12 | | - * This program is distributed in the hope that it will be useful, |
---|
13 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
14 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
15 | | - * GNU General Public License for more details. |
---|
16 | | - * |
---|
17 | | - * You should have received a copy of the GNU General Public License |
---|
18 | | - * along with this program; if not, write to the Free Software |
---|
19 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
---|
20 | 7 | */ |
---|
21 | 8 | |
---|
22 | 9 | #include <linux/list.h> |
---|
.. | .. |
---|
26 | 13 | #include <linux/spinlock.h> |
---|
27 | 14 | #include <linux/atomic.h> |
---|
28 | 15 | #include <asm/pci-bridge.h> |
---|
| 16 | +#include <asm/debugfs.h> |
---|
29 | 17 | #include <asm/ppc-pci.h> |
---|
30 | 18 | |
---|
31 | 19 | |
---|
32 | 20 | /** |
---|
| 21 | + * DOC: Overview |
---|
| 22 | + * |
---|
33 | 23 | * The pci address cache subsystem. This subsystem places |
---|
34 | 24 | * PCI device address resources into a red-black tree, sorted |
---|
35 | 25 | * according to the address range, so that given only an i/o |
---|
.. | .. |
---|
46 | 36 | * than any hash algo I could think of for this problem, even |
---|
47 | 37 | * with the penalty of slow pointer chases for d-cache misses). |
---|
48 | 38 | */ |
---|
| 39 | + |
---|
49 | 40 | struct pci_io_addr_range { |
---|
50 | 41 | struct rb_node rb_node; |
---|
51 | 42 | resource_size_t addr_lo; |
---|
.. | .. |
---|
113 | 104 | while (n) { |
---|
114 | 105 | struct pci_io_addr_range *piar; |
---|
115 | 106 | piar = rb_entry(n, struct pci_io_addr_range, rb_node); |
---|
116 | | - pr_debug("PCI: %s addr range %d [%pap-%pap]: %s\n", |
---|
| 107 | + pr_info("PCI: %s addr range %d [%pap-%pap]: %s\n", |
---|
117 | 108 | (piar->flags & IORESOURCE_IO) ? "i/o" : "mem", cnt, |
---|
118 | 109 | &piar->addr_lo, &piar->addr_hi, pci_name(piar->pcidev)); |
---|
119 | 110 | cnt++; |
---|
.. | .. |
---|
157 | 148 | piar->pcidev = dev; |
---|
158 | 149 | piar->flags = flags; |
---|
159 | 150 | |
---|
160 | | -#ifdef DEBUG |
---|
161 | | - pr_debug("PIAR: insert range=[%pap:%pap] dev=%s\n", |
---|
162 | | - &alo, &ahi, pci_name(dev)); |
---|
163 | | -#endif |
---|
| 151 | + eeh_edev_dbg(piar->edev, "PIAR: insert range=[%pap:%pap]\n", |
---|
| 152 | + &alo, &ahi); |
---|
164 | 153 | |
---|
165 | 154 | rb_link_node(&piar->rb_node, parent, p); |
---|
166 | 155 | rb_insert_color(&piar->rb_node, &pci_io_addr_cache_root.rb_root); |
---|
.. | .. |
---|
170 | 159 | |
---|
171 | 160 | static void __eeh_addr_cache_insert_dev(struct pci_dev *dev) |
---|
172 | 161 | { |
---|
173 | | - struct pci_dn *pdn; |
---|
174 | 162 | struct eeh_dev *edev; |
---|
175 | 163 | int i; |
---|
176 | 164 | |
---|
177 | | - pdn = pci_get_pdn_by_devfn(dev->bus, dev->devfn); |
---|
178 | | - if (!pdn) { |
---|
179 | | - pr_warn("PCI: no pci dn found for dev=%s\n", |
---|
180 | | - pci_name(dev)); |
---|
181 | | - return; |
---|
182 | | - } |
---|
183 | | - |
---|
184 | | - edev = pdn_to_eeh_dev(pdn); |
---|
| 165 | + edev = pci_dev_to_eeh_dev(dev); |
---|
185 | 166 | if (!edev) { |
---|
186 | 167 | pr_warn("PCI: no EEH dev found for %s\n", |
---|
187 | 168 | pci_name(dev)); |
---|
.. | .. |
---|
240 | 221 | piar = rb_entry(n, struct pci_io_addr_range, rb_node); |
---|
241 | 222 | |
---|
242 | 223 | if (piar->pcidev == dev) { |
---|
| 224 | + eeh_edev_dbg(piar->edev, "PIAR: remove range=[%pap:%pap]\n", |
---|
| 225 | + &piar->addr_lo, &piar->addr_hi); |
---|
243 | 226 | rb_erase(n, &pci_io_addr_cache_root.rb_root); |
---|
244 | 227 | kfree(piar); |
---|
245 | 228 | goto restart; |
---|
.. | .. |
---|
267 | 250 | } |
---|
268 | 251 | |
---|
269 | 252 | /** |
---|
270 | | - * eeh_addr_cache_build - Build a cache of I/O addresses |
---|
| 253 | + * eeh_addr_cache_init - Initialize a cache of I/O addresses |
---|
271 | 254 | * |
---|
272 | | - * Build a cache of pci i/o addresses. This cache will be used to |
---|
| 255 | + * Initialize a cache of pci i/o addresses. This cache will be used to |
---|
273 | 256 | * find the pci device that corresponds to a given address. |
---|
274 | | - * This routine scans all pci busses to build the cache. |
---|
275 | | - * Must be run late in boot process, after the pci controllers |
---|
276 | | - * have been scanned for devices (after all device resources are known). |
---|
277 | 257 | */ |
---|
278 | | -void eeh_addr_cache_build(void) |
---|
| 258 | +void eeh_addr_cache_init(void) |
---|
279 | 259 | { |
---|
280 | | - struct pci_dn *pdn; |
---|
281 | | - struct eeh_dev *edev; |
---|
282 | | - struct pci_dev *dev = NULL; |
---|
283 | | - |
---|
284 | 260 | spin_lock_init(&pci_io_addr_cache_root.piar_lock); |
---|
| 261 | +} |
---|
285 | 262 | |
---|
286 | | - for_each_pci_dev(dev) { |
---|
287 | | - pdn = pci_get_pdn_by_devfn(dev->bus, dev->devfn); |
---|
288 | | - if (!pdn) |
---|
289 | | - continue; |
---|
| 263 | +static int eeh_addr_cache_show(struct seq_file *s, void *v) |
---|
| 264 | +{ |
---|
| 265 | + struct pci_io_addr_range *piar; |
---|
| 266 | + struct rb_node *n; |
---|
| 267 | + unsigned long flags; |
---|
290 | 268 | |
---|
291 | | - edev = pdn_to_eeh_dev(pdn); |
---|
292 | | - if (!edev) |
---|
293 | | - continue; |
---|
| 269 | + spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags); |
---|
| 270 | + for (n = rb_first(&pci_io_addr_cache_root.rb_root); n; n = rb_next(n)) { |
---|
| 271 | + piar = rb_entry(n, struct pci_io_addr_range, rb_node); |
---|
294 | 272 | |
---|
295 | | - dev->dev.archdata.edev = edev; |
---|
296 | | - edev->pdev = dev; |
---|
297 | | - |
---|
298 | | - eeh_addr_cache_insert_dev(dev); |
---|
299 | | - eeh_sysfs_add_device(dev); |
---|
| 273 | + seq_printf(s, "%s addr range [%pap-%pap]: %s\n", |
---|
| 274 | + (piar->flags & IORESOURCE_IO) ? "i/o" : "mem", |
---|
| 275 | + &piar->addr_lo, &piar->addr_hi, pci_name(piar->pcidev)); |
---|
300 | 276 | } |
---|
| 277 | + spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags); |
---|
301 | 278 | |
---|
302 | | -#ifdef DEBUG |
---|
303 | | - /* Verify tree built up above, echo back the list of addrs. */ |
---|
304 | | - eeh_addr_cache_print(&pci_io_addr_cache_root); |
---|
305 | | -#endif |
---|
| 279 | + return 0; |
---|
| 280 | +} |
---|
| 281 | +DEFINE_SHOW_ATTRIBUTE(eeh_addr_cache); |
---|
| 282 | + |
---|
| 283 | +void eeh_cache_debugfs_init(void) |
---|
| 284 | +{ |
---|
| 285 | + debugfs_create_file_unsafe("eeh_address_cache", 0400, |
---|
| 286 | + powerpc_debugfs_root, NULL, |
---|
| 287 | + &eeh_addr_cache_fops); |
---|
306 | 288 | } |
---|