summaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2016-07-17 15:01:46 -0400
committerMarc Zyngier <marc.zyngier@arm.com>2016-07-18 13:15:18 -0400
commit17a21f58ff3e60fef3df788561b65e576a0b494d (patch)
treeee028f95d99b2e0f307cd06e7526f0bcbca13658 /virt
parentd6c7f865f00adf98ca79712167fb0f1b9dccb272 (diff)
KVM: arm64: vgic-its: Add collection allocator/destructor
Instead of spreading random allocations all over the place, consolidate allocation/init/freeing of collections in a pair of constructor/destructor. Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'virt')
-rw-r--r--virt/kvm/arm/vgic/vgic-its.c92
1 files changed, 54 insertions, 38 deletions
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 2faf1f458e8a..d6f68e9c946d 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -581,14 +581,45 @@ static int vgic_its_cmd_handle_movi(struct kvm *kvm, struct vgic_its *its,
581 return 0; 581 return 0;
582} 582}
583 583
584static void vgic_its_init_collection(struct vgic_its *its, 584static int vgic_its_alloc_collection(struct vgic_its *its,
585 struct its_collection *collection, 585 struct its_collection **colp,
586 u32 coll_id) 586 u32 coll_id)
587{ 587{
588 struct its_collection *collection;
589
590 collection = kzalloc(sizeof(*collection), GFP_KERNEL);
591
588 collection->collection_id = coll_id; 592 collection->collection_id = coll_id;
589 collection->target_addr = COLLECTION_NOT_MAPPED; 593 collection->target_addr = COLLECTION_NOT_MAPPED;
590 594
591 list_add_tail(&collection->coll_list, &its->collection_list); 595 list_add_tail(&collection->coll_list, &its->collection_list);
596 *colp = collection;
597
598 return 0;
599}
600
601static void vgic_its_free_collection(struct vgic_its *its, u32 coll_id)
602{
603 struct its_collection *collection;
604 struct its_device *device;
605 struct its_itte *itte;
606
607 /*
608 * Clearing the mapping for that collection ID removes the
609 * entry from the list. If there wasn't any before, we can
610 * go home early.
611 */
612 collection = find_collection(its, coll_id);
613 if (!collection)
614 return;
615
616 for_each_lpi_its(device, itte, its)
617 if (itte->collection &&
618 itte->collection->collection_id == coll_id)
619 itte->collection = NULL;
620
621 list_del(&collection->coll_list);
622 kfree(collection);
592} 623}
593 624
594/* 625/*
@@ -605,6 +636,7 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
605 struct its_device *device; 636 struct its_device *device;
606 struct its_collection *collection, *new_coll = NULL; 637 struct its_collection *collection, *new_coll = NULL;
607 int lpi_nr; 638 int lpi_nr;
639 int ret;
608 640
609 device = find_its_device(its, device_id); 641 device = find_its_device(its, device_id);
610 if (!device) 642 if (!device)
@@ -612,9 +644,10 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
612 644
613 collection = find_collection(its, coll_id); 645 collection = find_collection(its, coll_id);
614 if (!collection) { 646 if (!collection) {
615 new_coll = kzalloc(sizeof(struct its_collection), GFP_KERNEL); 647 ret = vgic_its_alloc_collection(its, &collection, coll_id);
616 if (!new_coll) 648 if (ret)
617 return -ENOMEM; 649 return ret;
650 new_coll = collection;
618 } 651 }
619 652
620 if (subcmd == GITS_CMD_MAPTI) 653 if (subcmd == GITS_CMD_MAPTI)
@@ -623,27 +656,22 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
623 lpi_nr = event_id; 656 lpi_nr = event_id;
624 if (lpi_nr < GIC_LPI_OFFSET || 657 if (lpi_nr < GIC_LPI_OFFSET ||
625 lpi_nr >= max_lpis_propbaser(kvm->arch.vgic.propbaser)) { 658 lpi_nr >= max_lpis_propbaser(kvm->arch.vgic.propbaser)) {
626 kfree(new_coll); 659 ret = E_ITS_MAPTI_PHYSICALID_OOR;
627 return E_ITS_MAPTI_PHYSICALID_OOR; 660 goto err;
628 } 661 }
629 662
630 itte = find_itte(its, device_id, event_id); 663 itte = find_itte(its, device_id, event_id);
631 if (!itte) { 664 if (!itte) {
632 itte = kzalloc(sizeof(struct its_itte), GFP_KERNEL); 665 itte = kzalloc(sizeof(struct its_itte), GFP_KERNEL);
633 if (!itte) { 666 if (!itte) {
634 kfree(new_coll); 667 ret = -ENOMEM;
635 return -ENOMEM; 668 goto err;
636 } 669 }
637 670
638 itte->event_id = event_id; 671 itte->event_id = event_id;
639 list_add_tail(&itte->itte_list, &device->itt_head); 672 list_add_tail(&itte->itte_list, &device->itt_head);
640 } 673 }
641 674
642 if (!collection) {
643 collection = new_coll;
644 vgic_its_init_collection(its, collection, coll_id);
645 }
646
647 itte->collection = collection; 675 itte->collection = collection;
648 itte->lpi = lpi_nr; 676 itte->lpi = lpi_nr;
649 itte->irq = vgic_add_lpi(kvm, lpi_nr); 677 itte->irq = vgic_add_lpi(kvm, lpi_nr);
@@ -657,6 +685,10 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
657 update_lpi_config(kvm, itte->irq, NULL); 685 update_lpi_config(kvm, itte->irq, NULL);
658 686
659 return 0; 687 return 0;
688err:
689 if (new_coll)
690 vgic_its_free_collection(its, coll_id);
691 return ret;
660} 692}
661 693
662/* Requires the its_lock to be held. */ 694/* Requires the its_lock to be held. */
@@ -809,34 +841,18 @@ static int vgic_its_cmd_handle_mapc(struct kvm *kvm, struct vgic_its *its,
809 if (coll_id >= vgic_its_nr_collection_ids(its)) 841 if (coll_id >= vgic_its_nr_collection_ids(its))
810 return E_ITS_MAPC_COLLECTION_OOR; 842 return E_ITS_MAPC_COLLECTION_OOR;
811 843
812 collection = find_collection(its, coll_id);
813
814 if (!valid) { 844 if (!valid) {
815 struct its_device *device; 845 vgic_its_free_collection(its, coll_id);
816 struct its_itte *itte;
817 /*
818 * Clearing the mapping for that collection ID removes the
819 * entry from the list. If there wasn't any before, we can
820 * go home early.
821 */
822 if (!collection)
823 return 0;
824
825 for_each_lpi_its(device, itte, its)
826 if (itte->collection &&
827 itte->collection->collection_id == coll_id)
828 itte->collection = NULL;
829
830 list_del(&collection->coll_list);
831 kfree(collection);
832 } else { 846 } else {
847 collection = find_collection(its, coll_id);
848
833 if (!collection) { 849 if (!collection) {
834 collection = kzalloc(sizeof(struct its_collection), 850 int ret;
835 GFP_KERNEL);
836 if (!collection)
837 return -ENOMEM;
838 851
839 vgic_its_init_collection(its, collection, coll_id); 852 ret = vgic_its_alloc_collection(its, &collection,
853 coll_id);
854 if (ret)
855 return ret;
840 collection->target_addr = target_addr; 856 collection->target_addr = target_addr;
841 } else { 857 } else {
842 collection->target_addr = target_addr; 858 collection->target_addr = target_addr;