hv: free ptdev device IRQs when shutting down VM

Currently ptdev_release_all_entries() calls ptirq_release_entry() to
release ptdev IRQs, which is not sufficient because free_irq() is not
included in ptirq_release_entry().

Furthermore, function ptirq_deactivate_entry() and ptirq_release_entry()
have lots of overlaps which make the differences between them are not
clear.

This patch does:

- Adds ptirq_deactivate_entry() call in ptdev_release_all_entries() if the
  irq has not already freed.

- Remove unnecessary code from ptirq_deactivate_entry() to make it do the
  exact opposite to function ptirq_activate_entry(), except that
  entry->allocated_pirq is not reset, which is not necessary.

- Added the missing del_timer() to ptirq_release_entry() to make it almost
  opposite to ptirq_alloc_entry(); Added memset() to clear the whole entry,
  which doesn't have impacts to the functionalities but keep the data structure
  clean.

Tracked-On: #2700
Signed-off-by: Sainath Grandhi <sainath.grandhi@intel.com>
Signed-off-by: Zide Chen <zide.chen@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Zide Chen 2019-04-17 16:30:28 -07:00 committed by wenlingz
parent 82fa9946e0
commit aef5a4fd29

View File

@ -112,16 +112,15 @@ void ptirq_release_entry(struct ptirq_remapping_info *entry)
{
uint64_t rflags;
/*
* remove entry from softirq list
* is required before calling ptirq_release_entry.
*/
spinlock_irqsave_obtain(&entry->vm->softirq_dev_lock, &rflags);
list_del_init(&entry->softirq_node);
del_timer(&entry->intr_delay_timer);
spinlock_irqrestore_release(&entry->vm->softirq_dev_lock, rflags);
atomic_clear32(&entry->active, ACTIVE_FLAG);
bitmap_clear_nolock((entry->ptdev_entry_id) & 0x3FU,
&ptirq_entry_bitmaps[((entry->ptdev_entry_id) & 0x3FU) >> 6U]);
(void)memset((void *)entry, 0U, sizeof(struct ptirq_remapping_info));
}
/* interrupt context */
@ -176,18 +175,8 @@ int32_t ptirq_activate_entry(struct ptirq_remapping_info *entry, uint32_t phys_i
void ptirq_deactivate_entry(struct ptirq_remapping_info *entry)
{
uint64_t rflags;
atomic_clear32(&entry->active, ACTIVE_FLAG);
free_irq(entry->allocated_pirq);
entry->allocated_pirq = IRQ_INVALID;
/* remove from softirq list if added */
spinlock_irqsave_obtain(&entry->vm->softirq_dev_lock, &rflags);
list_del_init(&entry->softirq_node);
del_timer(&entry->intr_delay_timer);
spinlock_irqrestore_release(&entry->vm->softirq_dev_lock, rflags);
}
void ptdev_init(void)
@ -207,8 +196,9 @@ void ptdev_release_all_entries(const struct acrn_vm *vm)
/* VM already down */
for (idx = 0U; idx < CONFIG_MAX_PT_IRQ_ENTRIES; idx++) {
entry = &ptirq_entries[idx];
if (entry->vm == vm) {
if ((entry->vm == vm) && is_entry_active(entry)) {
spinlock_obtain(&ptdev_lock);
ptirq_deactivate_entry(entry);
ptirq_release_entry(entry);
spinlock_release(&ptdev_lock);
}