]> www.infradead.org Git - linux.git/commitdiff
usb: xhci: improve Interrupt Management register macros
authorNiklas Neronin <niklas.neronin@linux.intel.com>
Thu, 15 May 2025 13:56:12 +0000 (16:56 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 21 May 2025 10:35:33 +0000 (12:35 +0200)
The Interrupt Management register (IMAN), contains three fields:
 - Bit 0: Interrupt Pending (IP)
 - Bit 1: Interrupt Enable (IE)
 - Bits 31:2: RsvdP (Reserved and Preserved)

Currently, there are multiple macros for both the IP and IE fields.
Consolidates them into single mask macros for better clarity and
maintainability.

Comment "THIS IS BUGGY - FIXME - IP IS WRITE 1 TO CLEAR" refers to the
fact that both macros 'ER_IRQ_ENABLE' and 'ER_IRQ_DISABLE' clear the IP bit
by writing '0' before modifying the IE bit. However, the IP bit is actually
cleared by writing '1'. To prevent any regression, this behavior has not
been altered. Instead, when the IE bit is modified, the IP macro is used
explicitly to highlight this "quirk".

Signed-off-by: Niklas Neronin <niklas.neronin@linux.intel.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20250515135621.335595-16-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h

index c3a1a67b65632ddce339fd7c25cb01a4d595c13b..472589679af39546795c66276ad15e9044343a7a 100644 (file)
@@ -331,7 +331,9 @@ int xhci_enable_interrupter(struct xhci_interrupter *ir)
                return -EINVAL;
 
        iman = readl(&ir->ir_set->irq_pending);
-       writel(ER_IRQ_ENABLE(iman), &ir->ir_set->irq_pending);
+       iman &= ~IMAN_IP;
+       iman |= IMAN_IE;
+       writel(iman, &ir->ir_set->irq_pending);
 
        return 0;
 }
@@ -344,7 +346,9 @@ int xhci_disable_interrupter(struct xhci_interrupter *ir)
                return -EINVAL;
 
        iman = readl(&ir->ir_set->irq_pending);
-       writel(ER_IRQ_DISABLE(iman), &ir->ir_set->irq_pending);
+       iman &= ~IMAN_IP;
+       iman &= ~IMAN_IE;
+       writel(iman, &ir->ir_set->irq_pending);
 
        return 0;
 }
index b0b16cd7df91f41a5c675912740a05966a645cbb..28c4ad7534c189278a48ed6fa3eaff6134f368cc 100644 (file)
@@ -152,10 +152,6 @@ struct xhci_op_regs {
 #define XHCI_RESET_LONG_USEC           (10 * 1000 * 1000)
 #define XHCI_RESET_SHORT_USEC          (250 * 1000)
 
-/* IMAN - Interrupt Management Register */
-#define IMAN_IE                (1 << 1)
-#define IMAN_IP                (1 << 0)
-
 /* USBSTS - USB status - status bitmasks */
 /* HC not running - set to 1 when run/stop bit is cleared. */
 #define STS_HALT       XHCI_STS_HALT
@@ -240,12 +236,10 @@ struct xhci_intr_reg {
 };
 
 /* irq_pending bitmasks */
-#define        ER_IRQ_PENDING(p)       ((p) & 0x1)
-/* bits 2:31 need to be preserved */
-/* THIS IS BUGGY - FIXME - IP IS WRITE 1 TO CLEAR */
-#define        ER_IRQ_CLEAR(p)         ((p) & 0xfffffffe)
-#define        ER_IRQ_ENABLE(p)        ((ER_IRQ_CLEAR(p)) | 0x2)
-#define        ER_IRQ_DISABLE(p)       ((ER_IRQ_CLEAR(p)) & ~(0x2))
+/* bit 0 - Interrupt Pending (IP), whether there is an interrupt pending. Write-1-to-clear. */
+#define        IMAN_IP                 (1 << 0)
+/* bit 1 - Interrupt Enable (IE), whether the interrupter is capable of generating an interrupt */
+#define        IMAN_IE                 (1 << 1)
 
 /* irq_control bitmasks */
 /* Minimum interval between interrupts (in 250ns intervals).  The interval