Commit df81749db7d7303508be41503e4c8d1229a07d4c

Authored by Bin Meng
Committed by Simon Glass
1 parent 8c38e4d0b8

x86: Reduce PIRQ routing table size

There is no need to populate multiple irq info entries with the same
bus number and device number, but with different interrupt pin. We
can use the same entry to store all the 4 interrupt pin (INT A/B/C/D)
routing information to reduce the whole PIRQ routing table size.

Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Acked-by: Simon Glass <sjg@chromium.org>

Showing 1 changed file with 56 additions and 9 deletions Side-by-side Diff

... ... @@ -58,17 +58,28 @@
58 58 writeb(irq, irq_router.ibase + LINK_N2V(link, base));
59 59 }
60 60  
61   -static inline void fill_irq_info(struct irq_info **slotp, int *entries, u8 bus,
62   - u8 device, u8 pin, u8 pirq)
  61 +static struct irq_info *check_dup_entry(struct irq_info *slot_base,
  62 + int entry_num, int bus, int device)
63 63 {
64   - struct irq_info *slot = *slotp;
  64 + struct irq_info *slot = slot_base;
  65 + int i;
65 66  
  67 + for (i = 0; i < entry_num; i++) {
  68 + if (slot->bus == bus && slot->devfn == (device << 3))
  69 + break;
  70 + slot++;
  71 + }
  72 +
  73 + return (i == entry_num) ? NULL : slot;
  74 +}
  75 +
  76 +static inline void fill_irq_info(struct irq_info *slot, int bus, int device,
  77 + int pin, int pirq)
  78 +{
66 79 slot->bus = bus;
67 80 slot->devfn = (device << 3) | 0;
68 81 slot->irq[pin - 1].link = LINK_N2V(pirq, irq_router.link_base);
69 82 slot->irq[pin - 1].bitmap = irq_router.irq_mask;
70   - (*entries)++;
71   - (*slotp)++;
72 83 }
73 84  
74 85 __weak void cpu_irq_init(void)
... ... @@ -84,7 +95,7 @@
84 95 int len, count;
85 96 const u32 *cell;
86 97 struct irq_routing_table *rt;
87   - struct irq_info *slot;
  98 + struct irq_info *slot, *slot_base;
88 99 int irq_entries = 0;
89 100 int i;
90 101 int ret;
... ... @@ -167,7 +178,7 @@
167 178 rt->rtr_vendor = PCI_VENDOR_ID_INTEL;
168 179 rt->rtr_device = PCI_DEVICE_ID_INTEL_ICH7_31;
169 180  
170   - slot = rt->slots;
  181 + slot_base = rt->slots;
171 182  
172 183 /* Now fill in the irq_info entries in the PIRQ table */
173 184 for (i = 0; i < count; i++) {
... ... @@ -181,8 +192,44 @@
181 192 i, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf),
182 193 PCI_FUNC(pr.bdf), 'A' + pr.pin - 1,
183 194 'A' + pr.pirq);
184   - fill_irq_info(&slot, &irq_entries, PCI_BUS(pr.bdf),
185   - PCI_DEV(pr.bdf), pr.pin, pr.pirq);
  195 +
  196 + slot = check_dup_entry(slot_base, irq_entries,
  197 + PCI_BUS(pr.bdf), PCI_DEV(pr.bdf));
  198 + if (slot) {
  199 + debug("found entry for bus %d device %d, ",
  200 + PCI_BUS(pr.bdf), PCI_DEV(pr.bdf));
  201 +
  202 + if (slot->irq[pr.pin - 1].link) {
  203 + debug("skipping\n");
  204 +
  205 + /*
  206 + * Sanity test on the routed PIRQ pin
  207 + *
  208 + * If they don't match, show a warning to tell
  209 + * there might be something wrong with the PIRQ
  210 + * routing information in the device tree.
  211 + */
  212 + if (slot->irq[pr.pin - 1].link !=
  213 + LINK_N2V(pr.pirq, irq_router.link_base))
  214 + debug("WARNING: Inconsistent PIRQ routing information\n");
  215 +
  216 + cell += sizeof(struct pirq_routing) /
  217 + sizeof(u32);
  218 + continue;
  219 + } else {
  220 + debug("writing INT%c\n", 'A' + pr.pin - 1);
  221 + fill_irq_info(slot, PCI_BUS(pr.bdf),
  222 + PCI_DEV(pr.bdf), pr.pin, pr.pirq);
  223 + cell += sizeof(struct pirq_routing) /
  224 + sizeof(u32);
  225 + continue;
  226 + }
  227 + }
  228 +
  229 + slot = slot_base + irq_entries;
  230 + fill_irq_info(slot, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf),
  231 + pr.pin, pr.pirq);
  232 + irq_entries++;
186 233 cell += sizeof(struct pirq_routing) / sizeof(u32);
187 234 }
188 235