|
@@ -1010,6 +1010,26 @@ iosapic_check_gsi_range (unsigned int gsi_base, unsigned int ver)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int
|
|
|
+iosapic_delete_rte(unsigned int irq, unsigned int gsi)
|
|
|
+{
|
|
|
+ struct iosapic_rte_info *rte, *temp;
|
|
|
+
|
|
|
+ list_for_each_entry_safe(rte, temp, &iosapic_intr_info[irq].rtes,
|
|
|
+ rte_list) {
|
|
|
+ if (rte->iosapic->gsi_base + rte->rte_index == gsi) {
|
|
|
+ if (rte->refcnt)
|
|
|
+ return -EBUSY;
|
|
|
+
|
|
|
+ list_del(&rte->rte_list);
|
|
|
+ kfree(rte);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return -EINVAL;
|
|
|
+}
|
|
|
+
|
|
|
int iosapic_init(unsigned long phys_addr, unsigned int gsi_base)
|
|
|
{
|
|
|
int num_rte, err, index;
|
|
@@ -1069,7 +1089,7 @@ int iosapic_init(unsigned long phys_addr, unsigned int gsi_base)
|
|
|
|
|
|
int iosapic_remove(unsigned int gsi_base)
|
|
|
{
|
|
|
- int index, err = 0;
|
|
|
+ int i, irq, index, err = 0;
|
|
|
unsigned long flags;
|
|
|
|
|
|
spin_lock_irqsave(&iosapic_lock, flags);
|
|
@@ -1087,6 +1107,16 @@ int iosapic_remove(unsigned int gsi_base)
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
+ for (i = gsi_base; i < gsi_base + iosapic_lists[index].num_rte; i++) {
|
|
|
+ irq = __gsi_to_irq(i);
|
|
|
+ if (irq < 0)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ err = iosapic_delete_rte(irq, i);
|
|
|
+ if (err)
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
iounmap(iosapic_lists[index].addr);
|
|
|
iosapic_free(index);
|
|
|
out:
|