linux/drivers/pci/intr_remapping.c
<<
>>
Prefs
   1#include <linux/interrupt.h>
   2#include <linux/dmar.h>
   3#include <linux/spinlock.h>
   4#include <linux/jiffies.h>
   5#include <linux/pci.h>
   6#include <linux/irq.h>
   7#include <asm/io_apic.h>
   8#include <asm/smp.h>
   9#include <asm/cpu.h>
  10#include <linux/intel-iommu.h>
  11#include "intr_remapping.h"
  12#include <acpi/acpi.h>
  13#include <asm/pci-direct.h>
  14#include "pci.h"
  15
  16static struct ioapic_scope ir_ioapic[MAX_IO_APICS];
  17static int ir_ioapic_num;
  18int intr_remapping_enabled;
  19
  20static int disable_intremap;
  21static __init int setup_nointremap(char *str)
  22{
  23        disable_intremap = 1;
  24        return 0;
  25}
  26early_param("nointremap", setup_nointremap);
  27
  28struct irq_2_iommu {
  29        struct intel_iommu *iommu;
  30        u16 irte_index;
  31        u16 sub_handle;
  32        u8  irte_mask;
  33};
  34
  35#ifdef CONFIG_GENERIC_HARDIRQS
  36static struct irq_2_iommu *get_one_free_irq_2_iommu(int node)
  37{
  38        struct irq_2_iommu *iommu;
  39
  40        iommu = kzalloc_node(sizeof(*iommu), GFP_ATOMIC, node);
  41        printk(KERN_DEBUG "alloc irq_2_iommu on node %d\n", node);
  42
  43        return iommu;
  44}
  45
  46static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
  47{
  48        struct irq_desc *desc;
  49
  50        desc = irq_to_desc(irq);
  51
  52        if (WARN_ON_ONCE(!desc))
  53                return NULL;
  54
  55        return desc->irq_2_iommu;
  56}
  57
  58static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq)
  59{
  60        struct irq_desc *desc;
  61        struct irq_2_iommu *irq_iommu;
  62
  63        desc = irq_to_desc(irq);
  64        if (!desc) {
  65                printk(KERN_INFO "can not get irq_desc for %d\n", irq);
  66                return NULL;
  67        }
  68
  69        irq_iommu = desc->irq_2_iommu;
  70
  71        if (!irq_iommu)
  72                desc->irq_2_iommu = get_one_free_irq_2_iommu(irq_node(irq));
  73
  74        return desc->irq_2_iommu;
  75}
  76
  77#else /* !CONFIG_SPARSE_IRQ */
  78
  79static struct irq_2_iommu irq_2_iommuX[NR_IRQS];
  80
  81static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
  82{
  83        if (irq < nr_irqs)
  84                return &irq_2_iommuX[irq];
  85
  86        return NULL;
  87}
  88static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq)
  89{
  90        return irq_2_iommu(irq);
  91}
  92#endif
  93
  94static DEFINE_SPINLOCK(irq_2_ir_lock);
  95
  96static struct irq_2_iommu *valid_irq_2_iommu(unsigned int irq)
  97{
  98        struct irq_2_iommu *irq_iommu;
  99
 100        irq_iommu = irq_2_iommu(irq);
 101
 102        if (!irq_iommu)
 103                return NULL;
 104
 105        if (!irq_iommu->iommu)
 106                return NULL;
 107
 108        return irq_iommu;
 109}
 110
 111int irq_remapped(int irq)
 112{
 113        return valid_irq_2_iommu(irq) != NULL;
 114}
 115
 116int get_irte(int irq, struct irte *entry)
 117{
 118        int index;
 119        struct irq_2_iommu *irq_iommu;
 120        unsigned long flags;
 121
 122        if (!entry)
 123                return -1;
 124
 125        spin_lock_irqsave(&irq_2_ir_lock, flags);
 126        irq_iommu = valid_irq_2_iommu(irq);
 127        if (!irq_iommu) {
 128                spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 129                return -1;
 130        }
 131
 132        index = irq_iommu->irte_index + irq_iommu->sub_handle;
 133        *entry = *(irq_iommu->iommu->ir_table->base + index);
 134
 135        spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 136        return 0;
 137}
 138
 139int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
 140{
 141        struct ir_table *table = iommu->ir_table;
 142        struct irq_2_iommu *irq_iommu;
 143        u16 index, start_index;
 144        unsigned int mask = 0;
 145        unsigned long flags;
 146        int i;
 147
 148        if (!count)
 149                return -1;
 150
 151#ifndef CONFIG_SPARSE_IRQ
 152        /* protect irq_2_iommu_alloc later */
 153        if (irq >= nr_irqs)
 154                return -1;
 155#endif
 156
 157        /*
 158         * start the IRTE search from index 0.
 159         */
 160        index = start_index = 0;
 161
 162        if (count > 1) {
 163                count = __roundup_pow_of_two(count);
 164                mask = ilog2(count);
 165        }
 166
 167        if (mask > ecap_max_handle_mask(iommu->ecap)) {
 168                printk(KERN_ERR
 169                       "Requested mask %x exceeds the max invalidation handle"
 170                       " mask value %Lx\n", mask,
 171                       ecap_max_handle_mask(iommu->ecap));
 172                return -1;
 173        }
 174
 175        spin_lock_irqsave(&irq_2_ir_lock, flags);
 176        do {
 177                for (i = index; i < index + count; i++)
 178                        if  (table->base[i].present)
 179                                break;
 180                /* empty index found */
 181                if (i == index + count)
 182                        break;
 183
 184                index = (index + count) % INTR_REMAP_TABLE_ENTRIES;
 185
 186                if (index == start_index) {
 187                        spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 188                        printk(KERN_ERR "can't allocate an IRTE\n");
 189                        return -1;
 190                }
 191        } while (1);
 192
 193        for (i = index; i < index + count; i++)
 194                table->base[i].present = 1;
 195
 196        irq_iommu = irq_2_iommu_alloc(irq);
 197        if (!irq_iommu) {
 198                spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 199                printk(KERN_ERR "can't allocate irq_2_iommu\n");
 200                return -1;
 201        }
 202
 203        irq_iommu->iommu = iommu;
 204        irq_iommu->irte_index =  index;
 205        irq_iommu->sub_handle = 0;
 206        irq_iommu->irte_mask = mask;
 207
 208        spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 209
 210        return index;
 211}
 212
 213static int qi_flush_iec(struct intel_iommu *iommu, int index, int mask)
 214{
 215        struct qi_desc desc;
 216
 217        desc.low = QI_IEC_IIDEX(index) | QI_IEC_TYPE | QI_IEC_IM(mask)
 218                   | QI_IEC_SELECTIVE;
 219        desc.high = 0;
 220
 221        return qi_submit_sync(&desc, iommu);
 222}
 223
 224int map_irq_to_irte_handle(int irq, u16 *sub_handle)
 225{
 226        int index;
 227        struct irq_2_iommu *irq_iommu;
 228        unsigned long flags;
 229
 230        spin_lock_irqsave(&irq_2_ir_lock, flags);
 231        irq_iommu = valid_irq_2_iommu(irq);
 232        if (!irq_iommu) {
 233                spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 234                return -1;
 235        }
 236
 237        *sub_handle = irq_iommu->sub_handle;
 238        index = irq_iommu->irte_index;
 239        spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 240        return index;
 241}
 242
 243int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
 244{
 245        struct irq_2_iommu *irq_iommu;
 246        unsigned long flags;
 247
 248        spin_lock_irqsave(&irq_2_ir_lock, flags);
 249
 250        irq_iommu = irq_2_iommu_alloc(irq);
 251
 252        if (!irq_iommu) {
 253                spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 254                printk(KERN_ERR "can't allocate irq_2_iommu\n");
 255                return -1;
 256        }
 257
 258        irq_iommu->iommu = iommu;
 259        irq_iommu->irte_index = index;
 260        irq_iommu->sub_handle = subhandle;
 261        irq_iommu->irte_mask = 0;
 262
 263        spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 264
 265        return 0;
 266}
 267
 268int clear_irte_irq(int irq, struct intel_iommu *iommu, u16 index)
 269{
 270        struct irq_2_iommu *irq_iommu;
 271        unsigned long flags;
 272
 273        spin_lock_irqsave(&irq_2_ir_lock, flags);
 274        irq_iommu = valid_irq_2_iommu(irq);
 275        if (!irq_iommu) {
 276                spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 277                return -1;
 278        }
 279
 280        irq_iommu->iommu = NULL;
 281        irq_iommu->irte_index = 0;
 282        irq_iommu->sub_handle = 0;
 283        irq_2_iommu(irq)->irte_mask = 0;
 284
 285        spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 286
 287        return 0;
 288}
 289
 290int modify_irte(int irq, struct irte *irte_modified)
 291{
 292        int rc;
 293        int index;
 294        struct irte *irte;
 295        struct intel_iommu *iommu;
 296        struct irq_2_iommu *irq_iommu;
 297        unsigned long flags;
 298
 299        spin_lock_irqsave(&irq_2_ir_lock, flags);
 300        irq_iommu = valid_irq_2_iommu(irq);
 301        if (!irq_iommu) {
 302                spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 303                return -1;
 304        }
 305
 306        iommu = irq_iommu->iommu;
 307
 308        index = irq_iommu->irte_index + irq_iommu->sub_handle;
 309        irte = &iommu->ir_table->base[index];
 310
 311        set_64bit((unsigned long *)&irte->low, irte_modified->low);
 312        set_64bit((unsigned long *)&irte->high, irte_modified->high);
 313        __iommu_flush_cache(iommu, irte, sizeof(*irte));
 314
 315        rc = qi_flush_iec(iommu, index, 0);
 316        spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 317
 318        return rc;
 319}
 320
 321int flush_irte(int irq)
 322{
 323        int rc;
 324        int index;
 325        struct intel_iommu *iommu;
 326        struct irq_2_iommu *irq_iommu;
 327        unsigned long flags;
 328
 329        spin_lock_irqsave(&irq_2_ir_lock, flags);
 330        irq_iommu = valid_irq_2_iommu(irq);
 331        if (!irq_iommu) {
 332                spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 333                return -1;
 334        }
 335
 336        iommu = irq_iommu->iommu;
 337
 338        index = irq_iommu->irte_index + irq_iommu->sub_handle;
 339
 340        rc = qi_flush_iec(iommu, index, irq_iommu->irte_mask);
 341        spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 342
 343        return rc;
 344}
 345
 346struct intel_iommu *map_ioapic_to_ir(int apic)
 347{
 348        int i;
 349
 350        for (i = 0; i < MAX_IO_APICS; i++)
 351                if (ir_ioapic[i].id == apic)
 352                        return ir_ioapic[i].iommu;
 353        return NULL;
 354}
 355
 356struct intel_iommu *map_dev_to_ir(struct pci_dev *dev)
 357{
 358        struct dmar_drhd_unit *drhd;
 359
 360        drhd = dmar_find_matched_drhd_unit(dev);
 361        if (!drhd)
 362                return NULL;
 363
 364        return drhd->iommu;
 365}
 366
 367static int clear_entries(struct irq_2_iommu *irq_iommu)
 368{
 369        struct irte *start, *entry, *end;
 370        struct intel_iommu *iommu;
 371        int index;
 372
 373        if (irq_iommu->sub_handle)
 374                return 0;
 375
 376        iommu = irq_iommu->iommu;
 377        index = irq_iommu->irte_index + irq_iommu->sub_handle;
 378
 379        start = iommu->ir_table->base + index;
 380        end = start + (1 << irq_iommu->irte_mask);
 381
 382        for (entry = start; entry < end; entry++) {
 383                set_64bit((unsigned long *)&entry->low, 0);
 384                set_64bit((unsigned long *)&entry->high, 0);
 385        }
 386
 387        return qi_flush_iec(iommu, index, irq_iommu->irte_mask);
 388}
 389
 390int free_irte(int irq)
 391{
 392        int rc = 0;
 393        struct irq_2_iommu *irq_iommu;
 394        unsigned long flags;
 395
 396        spin_lock_irqsave(&irq_2_ir_lock, flags);
 397        irq_iommu = valid_irq_2_iommu(irq);
 398        if (!irq_iommu) {
 399                spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 400                return -1;
 401        }
 402
 403        rc = clear_entries(irq_iommu);
 404
 405        irq_iommu->iommu = NULL;
 406        irq_iommu->irte_index = 0;
 407        irq_iommu->sub_handle = 0;
 408        irq_iommu->irte_mask = 0;
 409
 410        spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 411
 412        return rc;
 413}
 414
 415/*
 416 * source validation type
 417 */
 418#define SVT_NO_VERIFY           0x0  /* no verification is required */
 419#define SVT_VERIFY_SID_SQ       0x1  /* verify using SID and SQ fiels */
 420#define SVT_VERIFY_BUS          0x2  /* verify bus of request-id */
 421
 422/*
 423 * source-id qualifier
 424 */
 425#define SQ_ALL_16       0x0  /* verify all 16 bits of request-id */
 426#define SQ_13_IGNORE_1  0x1  /* verify most significant 13 bits, ignore
 427                              * the third least significant bit
 428                              */
 429#define SQ_13_IGNORE_2  0x2  /* verify most significant 13 bits, ignore
 430                              * the second and third least significant bits
 431                              */
 432#define SQ_13_IGNORE_3  0x3  /* verify most significant 13 bits, ignore
 433                              * the least three significant bits
 434                              */
 435
 436/*
 437 * set SVT, SQ and SID fields of irte to verify
 438 * source ids of interrupt requests
 439 */
 440static void set_irte_sid(struct irte *irte, unsigned int svt,
 441                         unsigned int sq, unsigned int sid)
 442{
 443        irte->svt = svt;
 444        irte->sq = sq;
 445        irte->sid = sid;
 446}
 447
 448int set_ioapic_sid(struct irte *irte, int apic)
 449{
 450        int i;
 451        u16 sid = 0;
 452
 453        if (!irte)
 454                return -1;
 455
 456        for (i = 0; i < MAX_IO_APICS; i++) {
 457                if (ir_ioapic[i].id == apic) {
 458                        sid = (ir_ioapic[i].bus << 8) | ir_ioapic[i].devfn;
 459                        break;
 460                }
 461        }
 462
 463        if (sid == 0) {
 464                pr_warning("Failed to set source-id of IOAPIC (%d)\n", apic);
 465                return -1;
 466        }
 467
 468        set_irte_sid(irte, 1, 0, sid);
 469
 470        return 0;
 471}
 472
 473int set_msi_sid(struct irte *irte, struct pci_dev *dev)
 474{
 475        struct pci_dev *bridge;
 476
 477        if (!irte || !dev)
 478                return -1;
 479
 480        /* PCIe device or Root Complex integrated PCI device */
 481        if (dev->is_pcie || !dev->bus->parent) {
 482                set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16,
 483                             (dev->bus->number << 8) | dev->devfn);
 484                return 0;
 485        }
 486
 487        bridge = pci_find_upstream_pcie_bridge(dev);
 488        if (bridge) {
 489                if (bridge->is_pcie) /* this is a PCIE-to-PCI/PCIX bridge */
 490                        set_irte_sid(irte, SVT_VERIFY_BUS, SQ_ALL_16,
 491                                (bridge->bus->number << 8) | dev->bus->number);
 492                else /* this is a legacy PCI bridge */
 493                        set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16,
 494                                (bridge->bus->number << 8) | bridge->devfn);
 495        }
 496
 497        return 0;
 498}
 499
 500static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode)
 501{
 502        u64 addr;
 503        u32 sts;
 504        unsigned long flags;
 505
 506        addr = virt_to_phys((void *)iommu->ir_table->base);
 507
 508        spin_lock_irqsave(&iommu->register_lock, flags);
 509
 510        dmar_writeq(iommu->reg + DMAR_IRTA_REG,
 511                    (addr) | IR_X2APIC_MODE(mode) | INTR_REMAP_TABLE_REG_SIZE);
 512
 513        /* Set interrupt-remapping table pointer */
 514        iommu->gcmd |= DMA_GCMD_SIRTP;
 515        writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
 516
 517        IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
 518                      readl, (sts & DMA_GSTS_IRTPS), sts);
 519        spin_unlock_irqrestore(&iommu->register_lock, flags);
 520
 521        /*
 522         * global invalidation of interrupt entry cache before enabling
 523         * interrupt-remapping.
 524         */
 525        qi_global_iec(iommu);
 526
 527        spin_lock_irqsave(&iommu->register_lock, flags);
 528
 529        /* Enable interrupt-remapping */
 530        iommu->gcmd |= DMA_GCMD_IRE;
 531        writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
 532
 533        IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
 534                      readl, (sts & DMA_GSTS_IRES), sts);
 535
 536        spin_unlock_irqrestore(&iommu->register_lock, flags);
 537}
 538
 539
 540static int setup_intr_remapping(struct intel_iommu *iommu, int mode)
 541{
 542        struct ir_table *ir_table;
 543        struct page *pages;
 544
 545        ir_table = iommu->ir_table = kzalloc(sizeof(struct ir_table),
 546                                             GFP_ATOMIC);
 547
 548        if (!iommu->ir_table)
 549                return -ENOMEM;
 550
 551        pages = alloc_pages(GFP_ATOMIC | __GFP_ZERO, INTR_REMAP_PAGE_ORDER);
 552
 553        if (!pages) {
 554                printk(KERN_ERR "failed to allocate pages of order %d\n",
 555                       INTR_REMAP_PAGE_ORDER);
 556                kfree(iommu->ir_table);
 557                return -ENOMEM;
 558        }
 559
 560        ir_table->base = page_address(pages);
 561
 562        iommu_set_intr_remapping(iommu, mode);
 563        return 0;
 564}
 565
 566/*
 567 * Disable Interrupt Remapping.
 568 */
 569static void iommu_disable_intr_remapping(struct intel_iommu *iommu)
 570{
 571        unsigned long flags;
 572        u32 sts;
 573
 574        if (!ecap_ir_support(iommu->ecap))
 575                return;
 576
 577        /*
 578         * global invalidation of interrupt entry cache before disabling
 579         * interrupt-remapping.
 580         */
 581        qi_global_iec(iommu);
 582
 583        spin_lock_irqsave(&iommu->register_lock, flags);
 584
 585        sts = dmar_readq(iommu->reg + DMAR_GSTS_REG);
 586        if (!(sts & DMA_GSTS_IRES))
 587                goto end;
 588
 589        iommu->gcmd &= ~DMA_GCMD_IRE;
 590        writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
 591
 592        IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
 593                      readl, !(sts & DMA_GSTS_IRES), sts);
 594
 595end:
 596        spin_unlock_irqrestore(&iommu->register_lock, flags);
 597}
 598
 599int __init intr_remapping_supported(void)
 600{
 601        struct dmar_drhd_unit *drhd;
 602
 603        if (disable_intremap)
 604                return 0;
 605
 606        if (!dmar_ir_support())
 607                return 0;
 608
 609        for_each_drhd_unit(drhd) {
 610                struct intel_iommu *iommu = drhd->iommu;
 611
 612                if (!ecap_ir_support(iommu->ecap))
 613                        return 0;
 614        }
 615
 616        return 1;
 617}
 618
 619int __init enable_intr_remapping(int eim)
 620{
 621        struct dmar_drhd_unit *drhd;
 622        int setup = 0;
 623
 624        if (parse_ioapics_under_ir() != 1) {
 625                printk(KERN_INFO "Not enable interrupt remapping\n");
 626                return -1;
 627        }
 628
 629        for_each_drhd_unit(drhd) {
 630                struct intel_iommu *iommu = drhd->iommu;
 631
 632                /*
 633                 * If the queued invalidation is already initialized,
 634                 * shouldn't disable it.
 635                 */
 636                if (iommu->qi)
 637                        continue;
 638
 639                /*
 640                 * Clear previous faults.
 641                 */
 642                dmar_fault(-1, iommu);
 643
 644                /*
 645                 * Disable intr remapping and queued invalidation, if already
 646                 * enabled prior to OS handover.
 647                 */
 648                iommu_disable_intr_remapping(iommu);
 649
 650                dmar_disable_qi(iommu);
 651        }
 652
 653        /*
 654         * check for the Interrupt-remapping support
 655         */
 656        for_each_drhd_unit(drhd) {
 657                struct intel_iommu *iommu = drhd->iommu;
 658
 659                if (!ecap_ir_support(iommu->ecap))
 660                        continue;
 661
 662                if (eim && !ecap_eim_support(iommu->ecap)) {
 663                        printk(KERN_INFO "DRHD %Lx: EIM not supported by DRHD, "
 664                               " ecap %Lx\n", drhd->reg_base_addr, iommu->ecap);
 665                        return -1;
 666                }
 667        }
 668
 669        /*
 670         * Enable queued invalidation for all the DRHD's.
 671         */
 672        for_each_drhd_unit(drhd) {
 673                int ret;
 674                struct intel_iommu *iommu = drhd->iommu;
 675                ret = dmar_enable_qi(iommu);
 676
 677                if (ret) {
 678                        printk(KERN_ERR "DRHD %Lx: failed to enable queued, "
 679                               " invalidation, ecap %Lx, ret %d\n",
 680                               drhd->reg_base_addr, iommu->ecap, ret);
 681                        return -1;
 682                }
 683        }
 684
 685        /*
 686         * Setup Interrupt-remapping for all the DRHD's now.
 687         */
 688        for_each_drhd_unit(drhd) {
 689                struct intel_iommu *iommu = drhd->iommu;
 690
 691                if (!ecap_ir_support(iommu->ecap))
 692                        continue;
 693
 694                if (setup_intr_remapping(iommu, eim))
 695                        goto error;
 696
 697                setup = 1;
 698        }
 699
 700        if (!setup)
 701                goto error;
 702
 703        intr_remapping_enabled = 1;
 704
 705        return 0;
 706
 707error:
 708        /*
 709         * handle error condition gracefully here!
 710         */
 711        return -1;
 712}
 713
 714static void ir_parse_one_ioapic_scope(struct acpi_dmar_device_scope *scope,
 715                                      struct intel_iommu *iommu)
 716{
 717        struct acpi_dmar_pci_path *path;
 718        u8 bus;
 719        int count;
 720
 721        bus = scope->bus;
 722        path = (struct acpi_dmar_pci_path *)(scope + 1);
 723        count = (scope->length - sizeof(struct acpi_dmar_device_scope))
 724                / sizeof(struct acpi_dmar_pci_path);
 725
 726        while (--count > 0) {
 727                /*
 728                 * Access PCI directly due to the PCI
 729                 * subsystem isn't initialized yet.
 730                 */
 731                bus = read_pci_config_byte(bus, path->dev, path->fn,
 732                                           PCI_SECONDARY_BUS);
 733                path++;
 734        }
 735
 736        ir_ioapic[ir_ioapic_num].bus   = bus;
 737        ir_ioapic[ir_ioapic_num].devfn = PCI_DEVFN(path->dev, path->fn);
 738        ir_ioapic[ir_ioapic_num].iommu = iommu;
 739        ir_ioapic[ir_ioapic_num].id    = scope->enumeration_id;
 740        ir_ioapic_num++;
 741}
 742
 743static int ir_parse_ioapic_scope(struct acpi_dmar_header *header,
 744                                 struct intel_iommu *iommu)
 745{
 746        struct acpi_dmar_hardware_unit *drhd;
 747        struct acpi_dmar_device_scope *scope;
 748        void *start, *end;
 749
 750        drhd = (struct acpi_dmar_hardware_unit *)header;
 751
 752        start = (void *)(drhd + 1);
 753        end = ((void *)drhd) + header->length;
 754
 755        while (start < end) {
 756                scope = start;
 757                if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_IOAPIC) {
 758                        if (ir_ioapic_num == MAX_IO_APICS) {
 759                                printk(KERN_WARNING "Exceeded Max IO APICS\n");
 760                                return -1;
 761                        }
 762
 763                        printk(KERN_INFO "IOAPIC id %d under DRHD base"
 764                               " 0x%Lx\n", scope->enumeration_id,
 765                               drhd->address);
 766
 767                        ir_parse_one_ioapic_scope(scope, iommu);
 768                }
 769                start += scope->length;
 770        }
 771
 772        return 0;
 773}
 774
 775/*
 776 * Finds the assocaition between IOAPIC's and its Interrupt-remapping
 777 * hardware unit.
 778 */
 779int __init parse_ioapics_under_ir(void)
 780{
 781        struct dmar_drhd_unit *drhd;
 782        int ir_supported = 0;
 783
 784        for_each_drhd_unit(drhd) {
 785                struct intel_iommu *iommu = drhd->iommu;
 786
 787                if (ecap_ir_support(iommu->ecap)) {
 788                        if (ir_parse_ioapic_scope(drhd->hdr, iommu))
 789                                return -1;
 790
 791                        ir_supported = 1;
 792                }
 793        }
 794
 795        if (ir_supported && ir_ioapic_num != nr_ioapics) {
 796                printk(KERN_WARNING
 797                       "Not all IO-APIC's listed under remapping hardware\n");
 798                return -1;
 799        }
 800
 801        return ir_supported;
 802}
 803
 804void disable_intr_remapping(void)
 805{
 806        struct dmar_drhd_unit *drhd;
 807        struct intel_iommu *iommu = NULL;
 808
 809        /*
 810         * Disable Interrupt-remapping for all the DRHD's now.
 811         */
 812        for_each_iommu(iommu, drhd) {
 813                if (!ecap_ir_support(iommu->ecap))
 814                        continue;
 815
 816                iommu_disable_intr_remapping(iommu);
 817        }
 818}
 819
 820int reenable_intr_remapping(int eim)
 821{
 822        struct dmar_drhd_unit *drhd;
 823        int setup = 0;
 824        struct intel_iommu *iommu = NULL;
 825
 826        for_each_iommu(iommu, drhd)
 827                if (iommu->qi)
 828                        dmar_reenable_qi(iommu);
 829
 830        /*
 831         * Setup Interrupt-remapping for all the DRHD's now.
 832         */
 833        for_each_iommu(iommu, drhd) {
 834                if (!ecap_ir_support(iommu->ecap))
 835                        continue;
 836
 837                /* Set up interrupt remapping for iommu.*/
 838                iommu_set_intr_remapping(iommu, eim);
 839                setup = 1;
 840        }
 841
 842        if (!setup)
 843                goto error;
 844
 845        return 0;
 846
 847error:
 848        /*
 849         * handle error condition gracefully here!
 850         */
 851        return -1;
 852}
 853
 854
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.