From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-ej1-f43.google.com (mail-ej1-f43.google.com [209.85.218.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0A9A33FBED9 for ; Wed, 5 Aug 2026 09:35:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.43 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785922557; cv=none; b=sTNo8HFXZMOrtpe4OFgAN9VOzCbZDdjXX3HHNWxIL1/c/W9ZnLHLlsUEUj12Vm0NBPLdL0tFstaCaaBKfmwDre3Snz1+Cdsm3F6teGLHLTu2frjoqBcTvZlSJ3iE8byZkjLqG8VySVA75GySlcqMmFsXh/oza3kY5UDaINOv12E= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785922557; c=relaxed/simple; bh=/LmQT0ek0Mooi3MI+1xhBI34VXWuqXBjL5XHyS+N4Ps=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References; b=UAEyQaxfV1QUSGzZfeVVJRC6Et9GXB+oPEgc60fdnVHEP4WniGUy2Vug1PE0mBKfByM58wuxHQm/B2yDSfP5PxiyhEb3+EHFUB0O/eXHTK65qfDZgjIgVXzl9bVVOZwNhIoWMXbjaGF5atj70uSxuq443Fuac3INfVQtb05Gcuc= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=IBXbHWaU; arc=none smtp.client-ip=209.85.218.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="IBXbHWaU" Received: by mail-ej1-f43.google.com with SMTP id a640c23a62f3a-c1c52d920b8so125071766b.2 for ; Wed, 05 Aug 2026 02:35:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785922554; x=1786527354; darn=vger.kernel.org; h=references:in-reply-to:message-id:date:subject:cc:to:from:from:to :cc:subject:date:message-id:reply-to:content-type; bh=zY9r44Lb7ex++1L3xPMlIrRosbjH5n7EJEbtOHpnc/g=; b=IBXbHWaUj+26toFSqOq2PqlZnju3/dCfRy+shJ4IPw+SwaKMEusrWI4uXvbQELeKWU gu7kIwN0vnNuISTNnED+5etv/pN2jy7Hc4P5D6fM/hmnomwDYTaej8TSnq8juD9swWXL PmL53Vj5GKqqCeuROwxcCKZSbdNLj9vrqSszXm+kSA5tIUFq+YumKLr4xwPjG9kIxtPk OzDujByTcnPQFNhzXfgtANX2bk9vu6ILhDioAdfbyPZIxFSTly6zNnyJwwvk10cIBdrz jAvkOVNL0IHAlyKqcPCmyYhBVY7CR5E0vQtDGaT4YbRxfP5jSCEHUxcfDJ0sEW9l7H5I 3sxg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785922554; x=1786527354; h=references:in-reply-to:message-id:date:subject:cc:to:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=zY9r44Lb7ex++1L3xPMlIrRosbjH5n7EJEbtOHpnc/g=; b=aPpc1XhQdKx5ZblZX+W/+sH7qJUdJ1Pn0DZAxt7yyL4kKNbDqKTydcqcz4f35fzhTN Tyab+h09Rj4NSajvRllf6vSnrrCoaBk5iRk2RUZlkAD39HdhWC9N3PwDBFOCz+3NcxLC OGq8MV0JxsdKtaDBWD9d0kvE7HqDsg3DcJy0DmQ4gdrRN1Omd446CxiW0VAJxNY0YTeR w7LWetfcdmN4evbYIcUZXNPp3+pwv0koiBNrAqGjxGd73decCtvV1liE4U8yVqN70bAz WvDICfm0aaKqf33Tgt5Ifni3/DD1gPwovMnv37QYzZndfXpQ++PRgf0oQaFmwHGowmvK klVw== X-Forwarded-Encrypted: i=1; AHgh+RoLUEfKiayCvBqK+WUK54tT9YfKzIwlp4uzDV4X8JyB73SrS6tFzuzILVSFA8KLXZ5ZZ9X0J29qFMuG7eA=@vger.kernel.org X-Gm-Message-State: AOJu0YzklRax/OMbqWsc1KkB4Gwx2q4vB08DP/ShPrYyvjvyteRjDUl3 cy+LuQWMmICehBWTaqCu/3wIfSJqT7aiSeXNRIqrs3yg/QL5KgdrG4DArXwwnYjAuSw= X-Gm-Gg: AR+sD10wt+9NBwM1OtAxF+lRWNKE8YvRTLIbYBA5z7mKoPU1rguwzREZxbeDcG45Aj1 ILKnJN5FWLZKoM2xTtv4Oj8WSiaStDFGwb8bWbv/5izlOhkJy1SWSF+5aZaDTylR5Pw79+vjE1X kpEO8UXv7CbxNTSf7D62Kr8it+X+zmI8nHxUvOmFwuWK2SIzNi0cT/Ln/Rli1/zfG0TgBoOYMZj ylhV/2ViRFSZo6RiIfSrsYKtU7JRD7UYkrnfFM+Xv8deCy6tuLC18fOaUntKOMr2S+Lk0+POJGX 1jTD4mKowOYw8b3IWNnX8pQBU/Bo7Caj6lr//gcrbPq92dpis/NFsJ7tC9FH9NHHzIsdSHhExN0 ielk/HAX1zvWTDus8RqqlmYkCIvITvwlQTQPWBezTqWFX3oILrOQNg2zACN5KMQ50TCj5Y7VQov 4UnC6urzvRxWQSoVnHaep8yBK6P4y60DlYHtPnzFKrZwmlSkRgOfnUhAHR2Lr8cFn4m11ur5S14 CoAK9u7cP6UYj3x X-Received: by 2002:a17:907:934d:b0:c12:9b98:209e with SMTP id a640c23a62f3a-c2039c6806fmr223553266b.23.1785922553847; Wed, 05 Aug 2026 02:35:53 -0700 (PDT) Received: from localhost (c-85-228-45-68.bbcust.telenor.se. [85.228.45.68]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-c20363e72a5sm87586166b.33.2026.08.05.02.35.53 (version=TLS1_2 cipher=ECDHE-ECDSA-CHACHA20-POLY1305 bits=256/256); Wed, 05 Aug 2026 02:35:53 -0700 (PDT) From: Eli Billauer To: gregkh@linuxfoundation.org Cc: arnd@arndb.de, linux-kernel@vger.kernel.org, corbet@lwn.net, Eli Billauer Subject: [PATCH v4 7/7] char: xillybus: Ignore and report unsolicited interrupts Date: Wed, 5 Aug 2026 11:34:36 +0200 Message-Id: <20260805093436.59740-8-eli.billauer@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20260805093436.59740-1-eli.billauer@gmail.com> References: <20260805093436.59740-1-eli.billauer@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: During initialization, the hardware should issue interrupts only in response to requests from the host. Ignore and log unexpected interrupts, as these indicate misbehaving hardware, and return IRQ_NONE when the interrupt appears to be spurious. In the same spirit, in xilly_quiesce(), assign endpoint->num_channels = 0 before allowing the ISR, in order to expose whether the hardware incorrectly sends messages related to data channels during shutdown. Assisted-by: Deepseek:v4-pro Kimi:K2.6 ChatGPT:GPT-5.5 Claude:Sonnet-4.6 Assisted-by: Sashiko-0.2.5:gemini-3.1-pro-preview Signed-off-by: Eli Billauer --- Notes: Changelog: ========= Changes v3->v4: -- Return IRQ_NONE if the interrupt is considered spurious, following Sashiko's remark + add attribution to Sashiko. Changes v2->v3: -- Add Assisted-by tag to description No change on v1->v2. drivers/char/xillybus/xillybus.h | 3 ++ drivers/char/xillybus/xillybus_core.c | 47 ++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/drivers/char/xillybus/xillybus.h b/drivers/char/xillybus/xillybus.h index 51de7cbc579e..98c7ac4dd1f9 100644 --- a/drivers/char/xillybus/xillybus.h +++ b/drivers/char/xillybus/xillybus.h @@ -94,6 +94,9 @@ struct xilly_endpoint { __iomem void *registers; int fatal_error; + bool allow_isr; + spinlock_t allow_isr_lock; + struct mutex register_mutex; wait_queue_head_t ep_wait; diff --git a/drivers/char/xillybus/xillybus_core.c b/drivers/char/xillybus/xillybus_core.c index 6bc72d9dfb16..037e3801d068 100644 --- a/drivers/char/xillybus/xillybus_core.c +++ b/drivers/char/xillybus/xillybus_core.c @@ -72,6 +72,8 @@ static struct workqueue_struct *xillybus_wq; * * rd_spinlock does the same with rd_*_buf_idx, rd_empty and end_offset. * + * allow_isr_lock protects allow_isr. + * * register_mutex is endpoint-specific, and is held when non-atomic * register operations are performed. wr_mutex and rd_mutex may be * held when register_mutex is taken, but none of the spinlocks. Note that @@ -84,7 +86,8 @@ static struct workqueue_struct *xillybus_wq; * Only interruptible blocking is allowed on mutexes and wait queues. * * All in all, the locking order goes (with skips allowed, of course): - * wr_mutex -> rd_mutex -> register_mutex -> wr_spinlock -> rd_spinlock + * wr_mutex -> rd_mutex -> register_mutex -> + * allow_isr_lock -> wr_spinlock -> rd_spinlock */ static void malformed_message(struct xilly_endpoint *endpoint, u32 *buf) @@ -119,6 +122,13 @@ irqreturn_t xillybus_isr(int irq, void *data) unsigned int msg_channel, msg_bufno, msg_data, msg_dir; struct xilly_channel *channel; + guard(spinlock)(&ep->allow_isr_lock); + + if (!ep->allow_isr) { + dev_err_ratelimited(ep->dev, "Unexpected interrupt! Something is wrong with the hardware.\n"); + return IRQ_NONE; + } + buf = ep->msgbuf_addr; buf_size = ep->msg_buf_size/sizeof(u32); @@ -137,6 +147,7 @@ irqreturn_t xillybus_isr(int irq, void *data) if (++ep->failed_messages > 10) { dev_err(ep->dev, "Lost sync with interrupt messages. Stopping.\n"); + return IRQ_NONE; } else { dma_sync_single_for_device(ep->dev, ep->msgbuf_dma_addr, @@ -283,6 +294,19 @@ irqreturn_t xillybus_isr(int irq, void *data) } EXPORT_SYMBOL(xillybus_isr); +/* + * xilly_allow_isr() is similar to enabling / disabling the interrupt, + * with the difference that if an interrupt is issued while ep->allow_isr + * is false, this is visible in the kernel log. + */ + +static void xilly_allow_isr(struct xilly_endpoint *ep, bool newstate) +{ + guard(spinlock_irqsave)(&ep->allow_isr_lock); + + ep->allow_isr = newstate; +} + /* * A few trivial memory management functions. * NOTE: These functions are used only on probe and remove, and therefore @@ -651,6 +675,8 @@ static int xilly_obtain_idt(struct xilly_endpoint *endpoint) channel->wr_sleepy = 1; + xilly_allow_isr(endpoint, true); + iowrite32(1 | (3 << 24), /* Opcode 3 for channel 0 = Send IDT */ endpoint->registers + fpga_buf_ctrl_reg); @@ -659,6 +685,8 @@ static int xilly_obtain_idt(struct xilly_endpoint *endpoint) (!channel->wr_sleepy), XILLY_TIMEOUT); + xilly_allow_isr(endpoint, false); + if (t <= 0) { dev_err(endpoint->dev, "Failed to obtain IDT. Aborting.\n"); @@ -1837,6 +1865,9 @@ struct xilly_endpoint *xillybus_init_endpoint(struct device *dev) endpoint->failed_messages = 0; endpoint->fatal_error = 0; + endpoint->allow_isr = false; + spin_lock_init(&endpoint->allow_isr_lock); + init_waitqueue_head(&endpoint->ep_wait); mutex_init(&endpoint->register_mutex); @@ -1849,6 +1880,9 @@ static int xilly_quiesce(struct xilly_endpoint *endpoint) long t; endpoint->idtlen = -1; + endpoint->num_channels = 0; + + xilly_allow_isr(endpoint, true); iowrite32((u32) (endpoint->dma_using_dac & 0x0001), endpoint->registers + fpga_dma_control_reg); @@ -1856,6 +1890,9 @@ static int xilly_quiesce(struct xilly_endpoint *endpoint) t = wait_event_interruptible_timeout(endpoint->ep_wait, (endpoint->idtlen >= 0), XILLY_TIMEOUT); + + xilly_allow_isr(endpoint, false); + if (t <= 0) { dev_err(endpoint->dev, "Failed to quiesce the device on exit.\n"); @@ -1909,6 +1946,8 @@ int xillybus_endpoint_discovery(struct xilly_endpoint *endpoint) endpoint->idtlen = -1; + xilly_allow_isr(endpoint, true); + /* * Set DMA 32/64 bit mode, quiesce the device (?!) and get IDT * buffer size. @@ -1919,6 +1958,9 @@ int xillybus_endpoint_discovery(struct xilly_endpoint *endpoint) t = wait_event_interruptible_timeout(endpoint->ep_wait, (endpoint->idtlen >= 0), XILLY_TIMEOUT); + + xilly_allow_isr(endpoint, false); + if (t <= 0) { dev_err(endpoint->dev, "No response from FPGA. Aborting.\n"); return -ENODEV; @@ -1945,6 +1987,7 @@ int xillybus_endpoint_discovery(struct xilly_endpoint *endpoint) if (rc) goto failed_idt; + /* xilly_obtain_idt() allows and then disallows the ISR */ rc = xilly_obtain_idt(endpoint); if (rc) goto failed_idt; @@ -1963,6 +2006,8 @@ int xillybus_endpoint_discovery(struct xilly_endpoint *endpoint) if (rc) goto failed_idt; + xilly_allow_isr(endpoint, true); + rc = xillybus_init_chrdev(dev, &xillybus_fops, endpoint->owner, endpoint, idt_handle.names, -- 2.34.1