0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/list.h>
0010 #include <linux/pci.h>
0011 #include <linux/rbtree.h>
0012 #include <linux/slab.h>
0013 #include <linux/spinlock.h>
0014 #include <linux/atomic.h>
0015 #include <linux/debugfs.h>
0016 #include <asm/pci-bridge.h>
0017 #include <asm/ppc-pci.h>
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 struct pci_io_addr_range {
0041 struct rb_node rb_node;
0042 resource_size_t addr_lo;
0043 resource_size_t addr_hi;
0044 struct eeh_dev *edev;
0045 struct pci_dev *pcidev;
0046 unsigned long flags;
0047 };
0048
0049 static struct pci_io_addr_cache {
0050 struct rb_root rb_root;
0051 spinlock_t piar_lock;
0052 } pci_io_addr_cache_root;
0053
0054 static inline struct eeh_dev *__eeh_addr_cache_get_device(unsigned long addr)
0055 {
0056 struct rb_node *n = pci_io_addr_cache_root.rb_root.rb_node;
0057
0058 while (n) {
0059 struct pci_io_addr_range *piar;
0060 piar = rb_entry(n, struct pci_io_addr_range, rb_node);
0061
0062 if (addr < piar->addr_lo)
0063 n = n->rb_left;
0064 else if (addr > piar->addr_hi)
0065 n = n->rb_right;
0066 else
0067 return piar->edev;
0068 }
0069
0070 return NULL;
0071 }
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082 struct eeh_dev *eeh_addr_cache_get_dev(unsigned long addr)
0083 {
0084 struct eeh_dev *edev;
0085 unsigned long flags;
0086
0087 spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
0088 edev = __eeh_addr_cache_get_device(addr);
0089 spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
0090 return edev;
0091 }
0092
0093 #ifdef DEBUG
0094
0095
0096
0097
0098 static void eeh_addr_cache_print(struct pci_io_addr_cache *cache)
0099 {
0100 struct rb_node *n;
0101 int cnt = 0;
0102
0103 n = rb_first(&cache->rb_root);
0104 while (n) {
0105 struct pci_io_addr_range *piar;
0106 piar = rb_entry(n, struct pci_io_addr_range, rb_node);
0107 pr_info("PCI: %s addr range %d [%pap-%pap]: %s\n",
0108 (piar->flags & IORESOURCE_IO) ? "i/o" : "mem", cnt,
0109 &piar->addr_lo, &piar->addr_hi, pci_name(piar->pcidev));
0110 cnt++;
0111 n = rb_next(n);
0112 }
0113 }
0114 #endif
0115
0116
0117 static struct pci_io_addr_range *
0118 eeh_addr_cache_insert(struct pci_dev *dev, resource_size_t alo,
0119 resource_size_t ahi, unsigned long flags)
0120 {
0121 struct rb_node **p = &pci_io_addr_cache_root.rb_root.rb_node;
0122 struct rb_node *parent = NULL;
0123 struct pci_io_addr_range *piar;
0124
0125
0126 while (*p) {
0127 parent = *p;
0128 piar = rb_entry(parent, struct pci_io_addr_range, rb_node);
0129 if (ahi < piar->addr_lo) {
0130 p = &parent->rb_left;
0131 } else if (alo > piar->addr_hi) {
0132 p = &parent->rb_right;
0133 } else {
0134 if (dev != piar->pcidev ||
0135 alo != piar->addr_lo || ahi != piar->addr_hi) {
0136 pr_warn("PIAR: overlapping address range\n");
0137 }
0138 return piar;
0139 }
0140 }
0141 piar = kzalloc(sizeof(struct pci_io_addr_range), GFP_ATOMIC);
0142 if (!piar)
0143 return NULL;
0144
0145 piar->addr_lo = alo;
0146 piar->addr_hi = ahi;
0147 piar->edev = pci_dev_to_eeh_dev(dev);
0148 piar->pcidev = dev;
0149 piar->flags = flags;
0150
0151 eeh_edev_dbg(piar->edev, "PIAR: insert range=[%pap:%pap]\n",
0152 &alo, &ahi);
0153
0154 rb_link_node(&piar->rb_node, parent, p);
0155 rb_insert_color(&piar->rb_node, &pci_io_addr_cache_root.rb_root);
0156
0157 return piar;
0158 }
0159
0160 static void __eeh_addr_cache_insert_dev(struct pci_dev *dev)
0161 {
0162 struct eeh_dev *edev;
0163 int i;
0164
0165 edev = pci_dev_to_eeh_dev(dev);
0166 if (!edev) {
0167 pr_warn("PCI: no EEH dev found for %s\n",
0168 pci_name(dev));
0169 return;
0170 }
0171
0172
0173 if (!edev->pe) {
0174 dev_dbg(&dev->dev, "EEH: Skip building address cache\n");
0175 return;
0176 }
0177
0178
0179
0180
0181
0182 for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
0183 resource_size_t start = pci_resource_start(dev,i);
0184 resource_size_t end = pci_resource_end(dev,i);
0185 unsigned long flags = pci_resource_flags(dev,i);
0186
0187
0188 if (0 == (flags & (IORESOURCE_IO | IORESOURCE_MEM)))
0189 continue;
0190 if (start == 0 || ~start == 0 || end == 0 || ~end == 0)
0191 continue;
0192 eeh_addr_cache_insert(dev, start, end, flags);
0193 }
0194 }
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204 void eeh_addr_cache_insert_dev(struct pci_dev *dev)
0205 {
0206 unsigned long flags;
0207
0208 spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
0209 __eeh_addr_cache_insert_dev(dev);
0210 spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
0211 }
0212
0213 static inline void __eeh_addr_cache_rmv_dev(struct pci_dev *dev)
0214 {
0215 struct rb_node *n;
0216
0217 restart:
0218 n = rb_first(&pci_io_addr_cache_root.rb_root);
0219 while (n) {
0220 struct pci_io_addr_range *piar;
0221 piar = rb_entry(n, struct pci_io_addr_range, rb_node);
0222
0223 if (piar->pcidev == dev) {
0224 eeh_edev_dbg(piar->edev, "PIAR: remove range=[%pap:%pap]\n",
0225 &piar->addr_lo, &piar->addr_hi);
0226 rb_erase(n, &pci_io_addr_cache_root.rb_root);
0227 kfree(piar);
0228 goto restart;
0229 }
0230 n = rb_next(n);
0231 }
0232 }
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243 void eeh_addr_cache_rmv_dev(struct pci_dev *dev)
0244 {
0245 unsigned long flags;
0246
0247 spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
0248 __eeh_addr_cache_rmv_dev(dev);
0249 spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
0250 }
0251
0252
0253
0254
0255
0256
0257
0258 void eeh_addr_cache_init(void)
0259 {
0260 spin_lock_init(&pci_io_addr_cache_root.piar_lock);
0261 }
0262
0263 static int eeh_addr_cache_show(struct seq_file *s, void *v)
0264 {
0265 struct pci_io_addr_range *piar;
0266 struct rb_node *n;
0267 unsigned long flags;
0268
0269 spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
0270 for (n = rb_first(&pci_io_addr_cache_root.rb_root); n; n = rb_next(n)) {
0271 piar = rb_entry(n, struct pci_io_addr_range, rb_node);
0272
0273 seq_printf(s, "%s addr range [%pap-%pap]: %s\n",
0274 (piar->flags & IORESOURCE_IO) ? "i/o" : "mem",
0275 &piar->addr_lo, &piar->addr_hi, pci_name(piar->pcidev));
0276 }
0277 spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
0278
0279 return 0;
0280 }
0281 DEFINE_SHOW_ATTRIBUTE(eeh_addr_cache);
0282
0283 void __init eeh_cache_debugfs_init(void)
0284 {
0285 debugfs_create_file_unsafe("eeh_address_cache", 0400,
0286 arch_debugfs_dir, NULL,
0287 &eeh_addr_cache_fops);
0288 }