diff options
-rw-r--r-- | drivers/iommu/intel_irq_remapping.c | 55 | ||||
-rw-r--r-- | include/linux/intel-iommu.h | 1 |
2 files changed, 27 insertions, 29 deletions
diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index c988b8d85df8..3aa9b5c347e4 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c | |||
@@ -72,7 +72,6 @@ static int alloc_irte(struct intel_iommu *iommu, int irq, u16 count) | |||
72 | u16 index, start_index; | 72 | u16 index, start_index; |
73 | unsigned int mask = 0; | 73 | unsigned int mask = 0; |
74 | unsigned long flags; | 74 | unsigned long flags; |
75 | int i; | ||
76 | 75 | ||
77 | if (!count || !irq_iommu) | 76 | if (!count || !irq_iommu) |
78 | return -1; | 77 | return -1; |
@@ -96,32 +95,17 @@ static int alloc_irte(struct intel_iommu *iommu, int irq, u16 count) | |||
96 | } | 95 | } |
97 | 96 | ||
98 | raw_spin_lock_irqsave(&irq_2_ir_lock, flags); | 97 | raw_spin_lock_irqsave(&irq_2_ir_lock, flags); |
99 | do { | 98 | index = bitmap_find_free_region(table->bitmap, |
100 | for (i = index; i < index + count; i++) | 99 | INTR_REMAP_TABLE_ENTRIES, mask); |
101 | if (table->base[i].present) | 100 | if (index < 0) { |
102 | break; | 101 | pr_warn("IR%d: can't allocate an IRTE\n", iommu->seq_id); |
103 | /* empty index found */ | 102 | } else { |
104 | if (i == index + count) | 103 | cfg->remapped = 1; |
105 | break; | 104 | irq_iommu->iommu = iommu; |
106 | 105 | irq_iommu->irte_index = index; | |
107 | index = (index + count) % INTR_REMAP_TABLE_ENTRIES; | 106 | irq_iommu->sub_handle = 0; |
108 | 107 | irq_iommu->irte_mask = mask; | |
109 | if (index == start_index) { | 108 | } |
110 | raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags); | ||
111 | printk(KERN_ERR "can't allocate an IRTE\n"); | ||
112 | return -1; | ||
113 | } | ||
114 | } while (1); | ||
115 | |||
116 | for (i = index; i < index + count; i++) | ||
117 | table->base[i].present = 1; | ||
118 | |||
119 | cfg->remapped = 1; | ||
120 | irq_iommu->iommu = iommu; | ||
121 | irq_iommu->irte_index = index; | ||
122 | irq_iommu->sub_handle = 0; | ||
123 | irq_iommu->irte_mask = mask; | ||
124 | |||
125 | raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags); | 109 | raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags); |
126 | 110 | ||
127 | return index; | 111 | return index; |
@@ -254,6 +238,8 @@ static int clear_entries(struct irq_2_iommu *irq_iommu) | |||
254 | set_64bit(&entry->low, 0); | 238 | set_64bit(&entry->low, 0); |
255 | set_64bit(&entry->high, 0); | 239 | set_64bit(&entry->high, 0); |
256 | } | 240 | } |
241 | bitmap_release_region(iommu->ir_table->bitmap, index, | ||
242 | irq_iommu->irte_mask); | ||
257 | 243 | ||
258 | return qi_flush_iec(iommu, index, irq_iommu->irte_mask); | 244 | return qi_flush_iec(iommu, index, irq_iommu->irte_mask); |
259 | } | 245 | } |
@@ -453,6 +439,7 @@ static int intel_setup_irq_remapping(struct intel_iommu *iommu, int mode) | |||
453 | { | 439 | { |
454 | struct ir_table *ir_table; | 440 | struct ir_table *ir_table; |
455 | struct page *pages; | 441 | struct page *pages; |
442 | unsigned long *bitmap; | ||
456 | 443 | ||
457 | ir_table = iommu->ir_table = kzalloc(sizeof(struct ir_table), | 444 | ir_table = iommu->ir_table = kzalloc(sizeof(struct ir_table), |
458 | GFP_ATOMIC); | 445 | GFP_ATOMIC); |
@@ -464,13 +451,23 @@ static int intel_setup_irq_remapping(struct intel_iommu *iommu, int mode) | |||
464 | INTR_REMAP_PAGE_ORDER); | 451 | INTR_REMAP_PAGE_ORDER); |
465 | 452 | ||
466 | if (!pages) { | 453 | if (!pages) { |
467 | printk(KERN_ERR "failed to allocate pages of order %d\n", | 454 | pr_err("IR%d: failed to allocate pages of order %d\n", |
468 | INTR_REMAP_PAGE_ORDER); | 455 | iommu->seq_id, INTR_REMAP_PAGE_ORDER); |
469 | kfree(iommu->ir_table); | 456 | kfree(iommu->ir_table); |
470 | return -ENOMEM; | 457 | return -ENOMEM; |
471 | } | 458 | } |
472 | 459 | ||
460 | bitmap = kcalloc(BITS_TO_LONGS(INTR_REMAP_TABLE_ENTRIES), | ||
461 | sizeof(long), GFP_ATOMIC); | ||
462 | if (bitmap == NULL) { | ||
463 | pr_err("IR%d: failed to allocate bitmap\n", iommu->seq_id); | ||
464 | __free_pages(pages, INTR_REMAP_PAGE_ORDER); | ||
465 | kfree(ir_table); | ||
466 | return -ENOMEM; | ||
467 | } | ||
468 | |||
473 | ir_table->base = page_address(pages); | 469 | ir_table->base = page_address(pages); |
470 | ir_table->bitmap = bitmap; | ||
474 | 471 | ||
475 | iommu_set_irq_remapping(iommu, mode); | 472 | iommu_set_irq_remapping(iommu, mode); |
476 | return 0; | 473 | return 0; |
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index d380c5e68008..de1e5e936420 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h | |||
@@ -288,6 +288,7 @@ struct q_inval { | |||
288 | 288 | ||
289 | struct ir_table { | 289 | struct ir_table { |
290 | struct irte *base; | 290 | struct irte *base; |
291 | unsigned long *bitmap; | ||
291 | }; | 292 | }; |
292 | #endif | 293 | #endif |
293 | 294 | ||