diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/dmar.c | 61 | ||||
-rw-r--r-- | drivers/pci/intr_remapping.c | 21 |
2 files changed, 57 insertions, 25 deletions
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index 2b4162d9ca30..8d3e9c261061 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c | |||
@@ -573,19 +573,49 @@ static inline void reclaim_free_desc(struct q_inval *qi) | |||
573 | } | 573 | } |
574 | } | 574 | } |
575 | 575 | ||
576 | static int qi_check_fault(struct intel_iommu *iommu, int index) | ||
577 | { | ||
578 | u32 fault; | ||
579 | int head; | ||
580 | struct q_inval *qi = iommu->qi; | ||
581 | int wait_index = (index + 1) % QI_LENGTH; | ||
582 | |||
583 | fault = readl(iommu->reg + DMAR_FSTS_REG); | ||
584 | |||
585 | /* | ||
586 | * If IQE happens, the head points to the descriptor associated | ||
587 | * with the error. No new descriptors are fetched until the IQE | ||
588 | * is cleared. | ||
589 | */ | ||
590 | if (fault & DMA_FSTS_IQE) { | ||
591 | head = readl(iommu->reg + DMAR_IQH_REG); | ||
592 | if ((head >> 4) == index) { | ||
593 | memcpy(&qi->desc[index], &qi->desc[wait_index], | ||
594 | sizeof(struct qi_desc)); | ||
595 | __iommu_flush_cache(iommu, &qi->desc[index], | ||
596 | sizeof(struct qi_desc)); | ||
597 | writel(DMA_FSTS_IQE, iommu->reg + DMAR_FSTS_REG); | ||
598 | return -EINVAL; | ||
599 | } | ||
600 | } | ||
601 | |||
602 | return 0; | ||
603 | } | ||
604 | |||
576 | /* | 605 | /* |
577 | * Submit the queued invalidation descriptor to the remapping | 606 | * Submit the queued invalidation descriptor to the remapping |
578 | * hardware unit and wait for its completion. | 607 | * hardware unit and wait for its completion. |
579 | */ | 608 | */ |
580 | void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu) | 609 | int qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu) |
581 | { | 610 | { |
611 | int rc = 0; | ||
582 | struct q_inval *qi = iommu->qi; | 612 | struct q_inval *qi = iommu->qi; |
583 | struct qi_desc *hw, wait_desc; | 613 | struct qi_desc *hw, wait_desc; |
584 | int wait_index, index; | 614 | int wait_index, index; |
585 | unsigned long flags; | 615 | unsigned long flags; |
586 | 616 | ||
587 | if (!qi) | 617 | if (!qi) |
588 | return; | 618 | return 0; |
589 | 619 | ||
590 | hw = qi->desc; | 620 | hw = qi->desc; |
591 | 621 | ||
@@ -603,7 +633,8 @@ void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu) | |||
603 | 633 | ||
604 | hw[index] = *desc; | 634 | hw[index] = *desc; |
605 | 635 | ||
606 | wait_desc.low = QI_IWD_STATUS_DATA(2) | QI_IWD_STATUS_WRITE | QI_IWD_TYPE; | 636 | wait_desc.low = QI_IWD_STATUS_DATA(QI_DONE) | |
637 | QI_IWD_STATUS_WRITE | QI_IWD_TYPE; | ||
607 | wait_desc.high = virt_to_phys(&qi->desc_status[wait_index]); | 638 | wait_desc.high = virt_to_phys(&qi->desc_status[wait_index]); |
608 | 639 | ||
609 | hw[wait_index] = wait_desc; | 640 | hw[wait_index] = wait_desc; |
@@ -614,13 +645,11 @@ void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu) | |||
614 | qi->free_head = (qi->free_head + 2) % QI_LENGTH; | 645 | qi->free_head = (qi->free_head + 2) % QI_LENGTH; |
615 | qi->free_cnt -= 2; | 646 | qi->free_cnt -= 2; |
616 | 647 | ||
617 | spin_lock(&iommu->register_lock); | ||
618 | /* | 648 | /* |
619 | * update the HW tail register indicating the presence of | 649 | * update the HW tail register indicating the presence of |
620 | * new descriptors. | 650 | * new descriptors. |
621 | */ | 651 | */ |
622 | writel(qi->free_head << 4, iommu->reg + DMAR_IQT_REG); | 652 | writel(qi->free_head << 4, iommu->reg + DMAR_IQT_REG); |
623 | spin_unlock(&iommu->register_lock); | ||
624 | 653 | ||
625 | while (qi->desc_status[wait_index] != QI_DONE) { | 654 | while (qi->desc_status[wait_index] != QI_DONE) { |
626 | /* | 655 | /* |
@@ -630,15 +659,21 @@ void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu) | |||
630 | * a deadlock where the interrupt context can wait indefinitely | 659 | * a deadlock where the interrupt context can wait indefinitely |
631 | * for free slots in the queue. | 660 | * for free slots in the queue. |
632 | */ | 661 | */ |
662 | rc = qi_check_fault(iommu, index); | ||
663 | if (rc) | ||
664 | goto out; | ||
665 | |||
633 | spin_unlock(&qi->q_lock); | 666 | spin_unlock(&qi->q_lock); |
634 | cpu_relax(); | 667 | cpu_relax(); |
635 | spin_lock(&qi->q_lock); | 668 | spin_lock(&qi->q_lock); |
636 | } | 669 | } |
637 | 670 | out: | |
638 | qi->desc_status[index] = QI_DONE; | 671 | qi->desc_status[index] = qi->desc_status[wait_index] = QI_DONE; |
639 | 672 | ||
640 | reclaim_free_desc(qi); | 673 | reclaim_free_desc(qi); |
641 | spin_unlock_irqrestore(&qi->q_lock, flags); | 674 | spin_unlock_irqrestore(&qi->q_lock, flags); |
675 | |||
676 | return rc; | ||
642 | } | 677 | } |
643 | 678 | ||
644 | /* | 679 | /* |
@@ -651,13 +686,13 @@ void qi_global_iec(struct intel_iommu *iommu) | |||
651 | desc.low = QI_IEC_TYPE; | 686 | desc.low = QI_IEC_TYPE; |
652 | desc.high = 0; | 687 | desc.high = 0; |
653 | 688 | ||
689 | /* should never fail */ | ||
654 | qi_submit_sync(&desc, iommu); | 690 | qi_submit_sync(&desc, iommu); |
655 | } | 691 | } |
656 | 692 | ||
657 | int qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid, u8 fm, | 693 | int qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid, u8 fm, |
658 | u64 type, int non_present_entry_flush) | 694 | u64 type, int non_present_entry_flush) |
659 | { | 695 | { |
660 | |||
661 | struct qi_desc desc; | 696 | struct qi_desc desc; |
662 | 697 | ||
663 | if (non_present_entry_flush) { | 698 | if (non_present_entry_flush) { |
@@ -671,10 +706,7 @@ int qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid, u8 fm, | |||
671 | | QI_CC_GRAN(type) | QI_CC_TYPE; | 706 | | QI_CC_GRAN(type) | QI_CC_TYPE; |
672 | desc.high = 0; | 707 | desc.high = 0; |
673 | 708 | ||
674 | qi_submit_sync(&desc, iommu); | 709 | return qi_submit_sync(&desc, iommu); |
675 | |||
676 | return 0; | ||
677 | |||
678 | } | 710 | } |
679 | 711 | ||
680 | int qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr, | 712 | int qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr, |
@@ -704,10 +736,7 @@ int qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr, | |||
704 | desc.high = QI_IOTLB_ADDR(addr) | QI_IOTLB_IH(ih) | 736 | desc.high = QI_IOTLB_ADDR(addr) | QI_IOTLB_IH(ih) |
705 | | QI_IOTLB_AM(size_order); | 737 | | QI_IOTLB_AM(size_order); |
706 | 738 | ||
707 | qi_submit_sync(&desc, iommu); | 739 | return qi_submit_sync(&desc, iommu); |
708 | |||
709 | return 0; | ||
710 | |||
711 | } | 740 | } |
712 | 741 | ||
713 | /* | 742 | /* |
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c index f78371b22529..45effc5726c0 100644 --- a/drivers/pci/intr_remapping.c +++ b/drivers/pci/intr_remapping.c | |||
@@ -207,7 +207,7 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count) | |||
207 | return index; | 207 | return index; |
208 | } | 208 | } |
209 | 209 | ||
210 | static void qi_flush_iec(struct intel_iommu *iommu, int index, int mask) | 210 | static int qi_flush_iec(struct intel_iommu *iommu, int index, int mask) |
211 | { | 211 | { |
212 | struct qi_desc desc; | 212 | struct qi_desc desc; |
213 | 213 | ||
@@ -215,7 +215,7 @@ static void qi_flush_iec(struct intel_iommu *iommu, int index, int mask) | |||
215 | | QI_IEC_SELECTIVE; | 215 | | QI_IEC_SELECTIVE; |
216 | desc.high = 0; | 216 | desc.high = 0; |
217 | 217 | ||
218 | qi_submit_sync(&desc, iommu); | 218 | return qi_submit_sync(&desc, iommu); |
219 | } | 219 | } |
220 | 220 | ||
221 | int map_irq_to_irte_handle(int irq, u16 *sub_handle) | 221 | int map_irq_to_irte_handle(int irq, u16 *sub_handle) |
@@ -283,6 +283,7 @@ int clear_irte_irq(int irq, struct intel_iommu *iommu, u16 index) | |||
283 | 283 | ||
284 | int modify_irte(int irq, struct irte *irte_modified) | 284 | int modify_irte(int irq, struct irte *irte_modified) |
285 | { | 285 | { |
286 | int rc; | ||
286 | int index; | 287 | int index; |
287 | struct irte *irte; | 288 | struct irte *irte; |
288 | struct intel_iommu *iommu; | 289 | struct intel_iommu *iommu; |
@@ -303,14 +304,15 @@ int modify_irte(int irq, struct irte *irte_modified) | |||
303 | set_64bit((unsigned long *)irte, irte_modified->low | (1 << 1)); | 304 | set_64bit((unsigned long *)irte, irte_modified->low | (1 << 1)); |
304 | __iommu_flush_cache(iommu, irte, sizeof(*irte)); | 305 | __iommu_flush_cache(iommu, irte, sizeof(*irte)); |
305 | 306 | ||
306 | qi_flush_iec(iommu, index, 0); | 307 | rc = qi_flush_iec(iommu, index, 0); |
307 | |||
308 | spin_unlock(&irq_2_ir_lock); | 308 | spin_unlock(&irq_2_ir_lock); |
309 | return 0; | 309 | |
310 | return rc; | ||
310 | } | 311 | } |
311 | 312 | ||
312 | int flush_irte(int irq) | 313 | int flush_irte(int irq) |
313 | { | 314 | { |
315 | int rc; | ||
314 | int index; | 316 | int index; |
315 | struct intel_iommu *iommu; | 317 | struct intel_iommu *iommu; |
316 | struct irq_2_iommu *irq_iommu; | 318 | struct irq_2_iommu *irq_iommu; |
@@ -326,10 +328,10 @@ int flush_irte(int irq) | |||
326 | 328 | ||
327 | index = irq_iommu->irte_index + irq_iommu->sub_handle; | 329 | index = irq_iommu->irte_index + irq_iommu->sub_handle; |
328 | 330 | ||
329 | qi_flush_iec(iommu, index, irq_iommu->irte_mask); | 331 | rc = qi_flush_iec(iommu, index, irq_iommu->irte_mask); |
330 | spin_unlock(&irq_2_ir_lock); | 332 | spin_unlock(&irq_2_ir_lock); |
331 | 333 | ||
332 | return 0; | 334 | return rc; |
333 | } | 335 | } |
334 | 336 | ||
335 | struct intel_iommu *map_ioapic_to_ir(int apic) | 337 | struct intel_iommu *map_ioapic_to_ir(int apic) |
@@ -355,6 +357,7 @@ struct intel_iommu *map_dev_to_ir(struct pci_dev *dev) | |||
355 | 357 | ||
356 | int free_irte(int irq) | 358 | int free_irte(int irq) |
357 | { | 359 | { |
360 | int rc = 0; | ||
358 | int index, i; | 361 | int index, i; |
359 | struct irte *irte; | 362 | struct irte *irte; |
360 | struct intel_iommu *iommu; | 363 | struct intel_iommu *iommu; |
@@ -375,7 +378,7 @@ int free_irte(int irq) | |||
375 | if (!irq_iommu->sub_handle) { | 378 | if (!irq_iommu->sub_handle) { |
376 | for (i = 0; i < (1 << irq_iommu->irte_mask); i++) | 379 | for (i = 0; i < (1 << irq_iommu->irte_mask); i++) |
377 | set_64bit((unsigned long *)irte, 0); | 380 | set_64bit((unsigned long *)irte, 0); |
378 | qi_flush_iec(iommu, index, irq_iommu->irte_mask); | 381 | rc = qi_flush_iec(iommu, index, irq_iommu->irte_mask); |
379 | } | 382 | } |
380 | 383 | ||
381 | irq_iommu->iommu = NULL; | 384 | irq_iommu->iommu = NULL; |
@@ -385,7 +388,7 @@ int free_irte(int irq) | |||
385 | 388 | ||
386 | spin_unlock(&irq_2_ir_lock); | 389 | spin_unlock(&irq_2_ir_lock); |
387 | 390 | ||
388 | return 0; | 391 | return rc; |
389 | } | 392 | } |
390 | 393 | ||
391 | static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode) | 394 | static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode) |