diff --git a/drivers/virt/geniezone/gzvm_irqfd.c b/drivers/virt/geniezone/gzvm_irqfd.c index b10ac3a940ee..88fd3570b430 100644 --- a/drivers/virt/geniezone/gzvm_irqfd.c +++ b/drivers/virt/geniezone/gzvm_irqfd.c @@ -14,41 +14,11 @@ struct gzvm_irq_ack_notifier { void (*irq_acked)(struct gzvm_irq_ack_notifier *ian); }; -/** - * struct gzvm_kernel_irqfd_resampler - irqfd resampler descriptor. - * @gzvm: Poiner to gzvm. - * @list: List of resampling struct _irqfd objects sharing this gsi. - * RCU list modified under gzvm->irqfds.resampler_lock. - * @notifier: gzvm irq ack notifier. - * @link: Entry in list of gzvm->irqfd.resampler_list. - * Use for sharing esamplers among irqfds on the same gsi. - * Accessed and modified under gzvm->irqfds.resampler_lock. - * - * Resampling irqfds are a special variety of irqfds used to emulate - * level triggered interrupts. The interrupt is asserted on eventfd - * trigger. On acknowledgment through the irq ack notifier, the - * interrupt is de-asserted and userspace is notified through the - * resamplefd. All resamplers on the same gsi are de-asserted - * together, so we don't need to track the state of each individual - * user. We can also therefore share the same irq source ID. - */ -struct gzvm_kernel_irqfd_resampler { - struct gzvm *gzvm; - - struct list_head list; - struct gzvm_irq_ack_notifier notifier; - - struct list_head link; -}; - /** * struct gzvm_kernel_irqfd: gzvm kernel irqfd descriptor. * @gzvm: Pointer to struct gzvm. * @wait: Wait queue entry. * @gsi: Used for level IRQ fast-path. - * @resampler: The resampler used by this irqfd (resampler-only). - * @resamplefd: Eventfd notified on resample (resampler-only). - * @resampler_link: Entry in list of irqfds for a resampler (resampler-only). * @eventfd: Used for setup/shutdown. * @list: struct list_head. * @pt: struct poll_table_struct. @@ -60,12 +30,6 @@ struct gzvm_kernel_irqfd { int gsi; - struct gzvm_kernel_irqfd_resampler *resampler; - - struct eventfd_ctx *resamplefd; - - struct list_head resampler_link; - struct eventfd_ctx *eventfd; struct list_head list; poll_table pt; @@ -89,77 +53,6 @@ static void irqfd_set_spi(struct gzvm *gzvm, int irq_source_id, u32 irq, gzvm_irqchip_inject_irq(gzvm, irq_source_id, 0, irq, level); } -/** - * irqfd_resampler_ack() - Notify all of the resampler irqfds using this GSI - * when IRQ de-assert once. - * @ian: Pointer to gzvm_irq_ack_notifier. - * - * Since resampler irqfds share an IRQ source ID, we de-assert once - * then notify all of the resampler irqfds using this GSI. We can't - * do multiple de-asserts or we risk racing with incoming re-asserts. - */ -static void irqfd_resampler_ack(struct gzvm_irq_ack_notifier *ian) -{ - struct gzvm_kernel_irqfd_resampler *resampler; - struct gzvm *gzvm; - struct gzvm_kernel_irqfd *irqfd; - int idx; - - resampler = container_of(ian, - struct gzvm_kernel_irqfd_resampler, notifier); - gzvm = resampler->gzvm; - - irqfd_set_spi(gzvm, GZVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID, - resampler->notifier.gsi, 0, false); - - idx = srcu_read_lock(&gzvm->irq_srcu); - - list_for_each_entry_srcu(irqfd, &resampler->list, resampler_link, - srcu_read_lock_held(&gzvm->irq_srcu)) { - eventfd_signal(irqfd->resamplefd, 1); - } - - srcu_read_unlock(&gzvm->irq_srcu, idx); -} - -static void gzvm_register_irq_ack_notifier(struct gzvm *gzvm, - struct gzvm_irq_ack_notifier *ian) -{ - mutex_lock(&gzvm->irq_lock); - hlist_add_head_rcu(&ian->link, &gzvm->irq_ack_notifier_list); - mutex_unlock(&gzvm->irq_lock); -} - -static void gzvm_unregister_irq_ack_notifier(struct gzvm *gzvm, - struct gzvm_irq_ack_notifier *ian) -{ - mutex_lock(&gzvm->irq_lock); - hlist_del_init_rcu(&ian->link); - mutex_unlock(&gzvm->irq_lock); - synchronize_srcu(&gzvm->irq_srcu); -} - -static void irqfd_resampler_shutdown(struct gzvm_kernel_irqfd *irqfd) -{ - struct gzvm_kernel_irqfd_resampler *resampler = irqfd->resampler; - struct gzvm *gzvm = resampler->gzvm; - - mutex_lock(&gzvm->irqfds.resampler_lock); - - list_del_rcu(&irqfd->resampler_link); - synchronize_srcu(&gzvm->irq_srcu); - - if (list_empty(&resampler->list)) { - list_del(&resampler->link); - gzvm_unregister_irq_ack_notifier(gzvm, &resampler->notifier); - irqfd_set_spi(gzvm, GZVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID, - resampler->notifier.gsi, 0, false); - kfree(resampler); - } - - mutex_unlock(&gzvm->irqfds.resampler_lock); -} - /** * irqfd_shutdown() - Race-free decouple logic (ordering is critical). * @work: Pointer to work_struct. @@ -180,11 +73,6 @@ static void irqfd_shutdown(struct work_struct *work) */ eventfd_ctx_remove_wait_queue(irqfd->eventfd, &irqfd->wait, &cnt); - if (irqfd->resampler) { - irqfd_resampler_shutdown(irqfd); - eventfd_ctx_put(irqfd->resamplefd); - } - /* * It is now safe to release the object's resources */ @@ -278,9 +166,8 @@ static int gzvm_irqfd_assign(struct gzvm *gzvm, struct gzvm_irqfd *args) { struct gzvm_kernel_irqfd *irqfd, *tmp; struct fd f; - struct eventfd_ctx *eventfd = NULL, *resamplefd = NULL; + struct eventfd_ctx *eventfd = NULL; int ret; - __poll_t events; int idx; irqfd = kzalloc(sizeof(*irqfd), GFP_KERNEL_ACCOUNT); @@ -289,7 +176,6 @@ static int gzvm_irqfd_assign(struct gzvm *gzvm, struct gzvm_irqfd *args) irqfd->gzvm = gzvm; irqfd->gsi = args->gsi; - irqfd->resampler = NULL; INIT_LIST_HEAD(&irqfd->list); INIT_WORK(&irqfd->shutdown, irqfd_shutdown); @@ -308,55 +194,6 @@ static int gzvm_irqfd_assign(struct gzvm *gzvm, struct gzvm_irqfd *args) irqfd->eventfd = eventfd; - if (args->flags & GZVM_IRQFD_FLAG_RESAMPLE) { - struct gzvm_kernel_irqfd_resampler *resampler; - - resamplefd = eventfd_ctx_fdget(args->resamplefd); - if (IS_ERR(resamplefd)) { - ret = PTR_ERR(resamplefd); - goto fail; - } - - irqfd->resamplefd = resamplefd; - INIT_LIST_HEAD(&irqfd->resampler_link); - - mutex_lock(&gzvm->irqfds.resampler_lock); - - list_for_each_entry(resampler, - &gzvm->irqfds.resampler_list, link) { - if (resampler->notifier.gsi == irqfd->gsi) { - irqfd->resampler = resampler; - break; - } - } - - if (!irqfd->resampler) { - resampler = kzalloc(sizeof(*resampler), - GFP_KERNEL_ACCOUNT); - if (!resampler) { - ret = -ENOMEM; - mutex_unlock(&gzvm->irqfds.resampler_lock); - goto fail; - } - - resampler->gzvm = gzvm; - INIT_LIST_HEAD(&resampler->list); - resampler->notifier.gsi = irqfd->gsi; - resampler->notifier.irq_acked = irqfd_resampler_ack; - INIT_LIST_HEAD(&resampler->link); - - list_add(&resampler->link, &gzvm->irqfds.resampler_list); - gzvm_register_irq_ack_notifier(gzvm, - &resampler->notifier); - irqfd->resampler = resampler; - } - - list_add_rcu(&irqfd->resampler_link, &irqfd->resampler->list); - synchronize_srcu(&gzvm->irq_srcu); - - mutex_unlock(&gzvm->irqfds.resampler_lock); - } - /* * Install our own custom wake-up handling so we are notified via * a callback whenever someone signals the underlying eventfd @@ -383,16 +220,7 @@ static int gzvm_irqfd_assign(struct gzvm *gzvm, struct gzvm_irqfd *args) spin_unlock_irq(&gzvm->irqfds.lock); - /* - * Check if there was an event already pending on the eventfd - * before we registered, and trigger it as if we didn't miss it. - */ - events = vfs_poll(f.file, &irqfd->pt); - - /* In case there is already a pending event */ - if (events & EPOLLIN) - irqfd_set_spi(gzvm, GZVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID, - irqfd->gsi, 1, false); + vfs_poll(f.file, &irqfd->pt); srcu_read_unlock(&gzvm->irq_srcu, idx); @@ -404,12 +232,6 @@ static int gzvm_irqfd_assign(struct gzvm *gzvm, struct gzvm_irqfd *args) return 0; fail: - if (irqfd->resampler) - irqfd_resampler_shutdown(irqfd); - - if (resamplefd && !IS_ERR(resamplefd)) - eventfd_ctx_put(resamplefd); - if (eventfd && !IS_ERR(eventfd)) eventfd_ctx_put(eventfd); @@ -509,11 +331,9 @@ int gzvm_vm_irqfd_init(struct gzvm *gzvm) spin_lock_init(&gzvm->irqfds.lock); INIT_LIST_HEAD(&gzvm->irqfds.items); - INIT_LIST_HEAD(&gzvm->irqfds.resampler_list); if (init_srcu_struct(&gzvm->irq_srcu)) return -EINVAL; INIT_HLIST_HEAD(&gzvm->irq_ack_notifier_list); - mutex_init(&gzvm->irqfds.resampler_lock); return 0; }