From owner-dev-commits-src-branches@freebsd.org Sun Jul 18 00:36:55 2021 Return-Path: Delivered-To: dev-commits-src-branches@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 09FF665F55B; Sun, 18 Jul 2021 00:36:55 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4GS5df0GYNz4RYY; Sun, 18 Jul 2021 00:36:54 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 27D9D1A496; Sun, 18 Jul 2021 00:36:51 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 16I0ap1x049661; Sun, 18 Jul 2021 00:36:51 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 16I0apIi049660; Sun, 18 Jul 2021 00:36:51 GMT (envelope-from git) Date: Sun, 18 Jul 2021 00:36:51 GMT Message-Id: <202107180036.16I0apIi049660@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: "Bjoern A. Zeeb" Subject: git: 1eaaada457d6 - stable/13 - LinuxKPI: enhance the irq KPI for managed and threaded operations. MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: bz X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: 1eaaada457d6c559188c7abb5c8fc1fa372ec231 Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-branches@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commits to the stable branches of the FreeBSD src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 18 Jul 2021 00:36:55 -0000 The branch stable/13 has been updated by bz: URL: https://cgit.FreeBSD.org/src/commit/?id=1eaaada457d6c559188c7abb5c8fc1fa372ec231 commit 1eaaada457d6c559188c7abb5c8fc1fa372ec231 Author: Bjoern A. Zeeb AuthorDate: 2021-05-30 13:54:13 +0000 Commit: Bjoern A. Zeeb CommitDate: 2021-07-18 00:35:03 +0000 LinuxKPI: enhance the irq KPI for managed and threaded operations. Move request_irq() to an internal function which serves request_irq() and the newly added request_threaded_irq() and devm_request_threaded_irq(). Likewise factor out parts of free_irq() to also be used with devm_free_irq(). Add the storage and call to a thread_handler in case of IRQ_WAKE_THREAD. This is needed for the iwlwifi driver. Sponsored by: The FreeBSD Foundation Reviewed by: hselasky Differential Revision: https://reviews.freebsd.org/D30549 (cherry picked from commit d16b6cb17837162d685c960deb28f26f716fa440) --- .../linuxkpi/common/include/linux/interrupt.h | 97 ++++++++++++++++++---- sys/compat/linuxkpi/common/src/linux_compat.c | 31 ++++++- 2 files changed, 110 insertions(+), 18 deletions(-) diff --git a/sys/compat/linuxkpi/common/include/linux/interrupt.h b/sys/compat/linuxkpi/common/include/linux/interrupt.h index 90994a2f2315..6770adad2293 100644 --- a/sys/compat/linuxkpi/common/include/linux/interrupt.h +++ b/sys/compat/linuxkpi/common/include/linux/interrupt.h @@ -37,6 +37,7 @@ #include #include +#include #include #include #include @@ -51,10 +52,15 @@ struct irq_ent { struct resource *res; void *arg; irqreturn_t (*handler)(int, void *); + irqreturn_t (*thread_handler)(int, void *); void *tag; unsigned int irq; }; +void linux_irq_handler(void *); +void lkpi_devm_irq_release(struct device *, void *); +void lkpi_irq_release(struct device *, struct irq_ent *); + static inline int linux_irq_rid(struct device *dev, unsigned int irq) { @@ -65,8 +71,6 @@ linux_irq_rid(struct device *dev, unsigned int irq) return (0); } -extern void linux_irq_handler(void *); - static inline struct irq_ent * linux_irq_ent(struct device *dev, unsigned int irq) { @@ -80,8 +84,9 @@ linux_irq_ent(struct device *dev, unsigned int irq) } static inline int -request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, - const char *name, void *arg) +_request_irq(struct device *xdev, unsigned int irq, + irq_handler_t handler, irq_handler_t thread_handler, + unsigned long flags, const char *name, void *arg) { struct resource *res; struct irq_ent *irqe; @@ -92,27 +97,70 @@ request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, dev = linux_pci_find_irq_dev(irq); if (dev == NULL) return -ENXIO; + if (xdev != NULL && xdev != dev) + return -ENXIO; rid = linux_irq_rid(dev, irq); res = bus_alloc_resource_any(dev->bsddev, SYS_RES_IRQ, &rid, flags | RF_ACTIVE); if (res == NULL) return (-ENXIO); - irqe = kmalloc(sizeof(*irqe), GFP_KERNEL); + if (xdev != NULL) + irqe = lkpi_devres_alloc(lkpi_devm_irq_release, sizeof(*irqe), + GFP_KERNEL | __GFP_ZERO); + else + irqe = kzalloc(sizeof(*irqe), GFP_KERNEL); irqe->dev = dev; irqe->res = res; irqe->arg = arg; irqe->handler = handler; + irqe->thread_handler = thread_handler; irqe->irq = irq; + error = bus_setup_intr(dev->bsddev, res, INTR_TYPE_NET | INTR_MPSAFE, NULL, linux_irq_handler, irqe, &irqe->tag); - if (error) { - bus_release_resource(dev->bsddev, SYS_RES_IRQ, rid, irqe->res); - kfree(irqe); - return (-error); - } + if (error) + goto errout; list_add(&irqe->links, &dev->irqents); + if (xdev != NULL) + devres_add(xdev, irqe); return 0; + +errout: + bus_release_resource(dev->bsddev, SYS_RES_IRQ, rid, irqe->res); + if (xdev != NULL) + devres_free(irqe); + else + kfree(irqe); + return (-error); +} + +static inline int +request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, + const char *name, void *arg) +{ + + return (_request_irq(NULL, irq, handler, NULL, flags, name, arg)); +} + +static inline int +request_threaded_irq(int irq, irq_handler_t handler, + irq_handler_t thread_handler, unsigned long flags, + const char *name, void *arg) +{ + + return (_request_irq(NULL, irq, handler, thread_handler, + flags, name, arg)); +} + +static inline int +devm_request_threaded_irq(struct device *dev, int irq, + irq_handler_t handler, irq_handler_t thread_handler, + unsigned long flags, const char *name, void *arg) +{ + + return (_request_irq(dev, irq, handler, thread_handler, + flags, name, arg)); } static inline int @@ -166,26 +214,41 @@ bind_irq_to_cpu(unsigned int irq, int cpu_id) } static inline void -free_irq(unsigned int irq, void *device) +free_irq(unsigned int irq, void *device __unused) { struct irq_ent *irqe; struct device *dev; - int rid; dev = linux_pci_find_irq_dev(irq); if (dev == NULL) return; - rid = linux_irq_rid(dev, irq); irqe = linux_irq_ent(dev, irq); if (irqe == NULL) return; - if (irqe->tag != NULL) - bus_teardown_intr(dev->bsddev, irqe->res, irqe->tag); - bus_release_resource(dev->bsddev, SYS_RES_IRQ, rid, irqe->res); - list_del(&irqe->links); + lkpi_irq_release(dev, irqe); kfree(irqe); } +static inline void +devm_free_irq(struct device *xdev, unsigned int irq, void *p) +{ + struct device *dev; + struct irq_ent *irqe; + + dev = linux_pci_find_irq_dev(irq); + if (dev == NULL) + return; + if (xdev != dev) + return; + irqe = linux_irq_ent(dev, irq); + if (irqe == NULL) + return; + lkpi_irq_release(dev, irqe); + lkpi_devres_unlink(dev, irqe); + lkpi_devres_free(irqe); + return; +} + static inline int irq_set_affinity_hint(int vector, cpumask_t *mask) { diff --git a/sys/compat/linuxkpi/common/src/linux_compat.c b/sys/compat/linuxkpi/common/src/linux_compat.c index d4571173f93d..217c4081c603 100644 --- a/sys/compat/linuxkpi/common/src/linux_compat.c +++ b/sys/compat/linuxkpi/common/src/linux_compat.c @@ -2463,6 +2463,30 @@ list_sort(void *priv, struct list_head *head, int (*cmp)(void *priv, free(ar, M_KMALLOC); } +void +lkpi_irq_release(struct device *dev, struct irq_ent *irqe) +{ + + if (irqe->tag != NULL) + bus_teardown_intr(dev->bsddev, irqe->res, irqe->tag); + if (irqe->res != NULL) + bus_release_resource(dev->bsddev, SYS_RES_IRQ, + rman_get_rid(irqe->res), irqe->res); + list_del(&irqe->links); +} + +void +lkpi_devm_irq_release(struct device *dev, void *p) +{ + struct irq_ent *irqe; + + if (dev == NULL || p == NULL) + return; + + irqe = p; + lkpi_irq_release(dev, irqe); +} + void linux_irq_handler(void *ent) { @@ -2472,7 +2496,12 @@ linux_irq_handler(void *ent) return; irqe = ent; - irqe->handler(irqe->irq, irqe->arg); + if (irqe->handler(irqe->irq, irqe->arg) == IRQ_WAKE_THREAD && + irqe->thread_handler != NULL) { + THREAD_SLEEPING_OK(); + irqe->thread_handler(irqe->irq, irqe->arg); + THREAD_NO_SLEEPING(); + } } #if defined(__i386__) || defined(__amd64__)