]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net: airoha: Introduce airoha_irq_bank struct
authorLorenzo Bianconi <lorenzo@kernel.org>
Fri, 18 Apr 2025 10:40:49 +0000 (12:40 +0200)
committerJakub Kicinski <kuba@kernel.org>
Thu, 24 Apr 2025 00:03:53 +0000 (17:03 -0700)
EN7581 ethernet SoC supports 4 programmable IRQ lines each one composed
by 4 IRQ configuration registers. Add airoha_irq_bank struct as a
container for independent IRQ lines info (e.g. IRQ number, enabled source
interrupts, ecc). This is a preliminary patch to support multiple IRQ lines
in airoha_eth driver.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://patch.msgid.link/20250418-airoha-eth-multi-irq-v1-1-1ab0083ca3c1@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/airoha/airoha_eth.c
drivers/net/ethernet/airoha/airoha_eth.h
drivers/net/ethernet/airoha/airoha_regs.h

index c773b5ea9c051ab40ddd5c9ba5a1795ed36e6820..e1c1cf965c2f16e3fb4ad17f5299b27d9615da3f 100644 (file)
@@ -34,37 +34,40 @@ u32 airoha_rmw(void __iomem *base, u32 offset, u32 mask, u32 val)
        return val;
 }
 
-static void airoha_qdma_set_irqmask(struct airoha_qdma *qdma, int index,
-                                   u32 clear, u32 set)
+static void airoha_qdma_set_irqmask(struct airoha_irq_bank *irq_bank,
+                                   int index, u32 clear, u32 set)
 {
+       struct airoha_qdma *qdma = irq_bank->qdma;
+       int bank = irq_bank - &qdma->irq_banks[0];
        unsigned long flags;
 
-       if (WARN_ON_ONCE(index >= ARRAY_SIZE(qdma->irqmask)))
+       if (WARN_ON_ONCE(index >= ARRAY_SIZE(irq_bank->irqmask)))
                return;
 
-       spin_lock_irqsave(&qdma->irq_lock, flags);
+       spin_lock_irqsave(&irq_bank->irq_lock, flags);
 
-       qdma->irqmask[index] &= ~clear;
-       qdma->irqmask[index] |= set;
-       airoha_qdma_wr(qdma, REG_INT_ENABLE(index), qdma->irqmask[index]);
+       irq_bank->irqmask[index] &= ~clear;
+       irq_bank->irqmask[index] |= set;
+       airoha_qdma_wr(qdma, REG_INT_ENABLE(bank, index),
+                      irq_bank->irqmask[index]);
        /* Read irq_enable register in order to guarantee the update above
         * completes in the spinlock critical section.
         */
-       airoha_qdma_rr(qdma, REG_INT_ENABLE(index));
+       airoha_qdma_rr(qdma, REG_INT_ENABLE(bank, index));
 
-       spin_unlock_irqrestore(&qdma->irq_lock, flags);
+       spin_unlock_irqrestore(&irq_bank->irq_lock, flags);
 }
 
-static void airoha_qdma_irq_enable(struct airoha_qdma *qdma, int index,
-                                  u32 mask)
+static void airoha_qdma_irq_enable(struct airoha_irq_bank *irq_bank,
+                                  int index, u32 mask)
 {
-       airoha_qdma_set_irqmask(qdma, index, 0, mask);
+       airoha_qdma_set_irqmask(irq_bank, index, 0, mask);
 }
 
-static void airoha_qdma_irq_disable(struct airoha_qdma *qdma, int index,
-                                   u32 mask)
+static void airoha_qdma_irq_disable(struct airoha_irq_bank *irq_bank,
+                                   int index, u32 mask)
 {
-       airoha_qdma_set_irqmask(qdma, index, mask, 0);
+       airoha_qdma_set_irqmask(irq_bank, index, mask, 0);
 }
 
 static bool airhoa_is_lan_gdm_port(struct airoha_gdm_port *port)
@@ -732,6 +735,7 @@ free_frag:
 static int airoha_qdma_rx_napi_poll(struct napi_struct *napi, int budget)
 {
        struct airoha_queue *q = container_of(napi, struct airoha_queue, napi);
+       struct airoha_irq_bank *irq_bank = &q->qdma->irq_banks[0];
        int cur, done = 0;
 
        do {
@@ -740,7 +744,7 @@ static int airoha_qdma_rx_napi_poll(struct napi_struct *napi, int budget)
        } while (cur && done < budget);
 
        if (done < budget && napi_complete(napi))
-               airoha_qdma_irq_enable(q->qdma, QDMA_INT_REG_IDX1,
+               airoha_qdma_irq_enable(irq_bank, QDMA_INT_REG_IDX1,
                                       RX_DONE_INT_MASK);
 
        return done;
@@ -944,7 +948,7 @@ unlock:
        }
 
        if (done < budget && napi_complete(napi))
-               airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX0,
+               airoha_qdma_irq_enable(&qdma->irq_banks[0], QDMA_INT_REG_IDX0,
                                       TX_DONE_INT_MASK(id));
 
        return done;
@@ -1175,13 +1179,16 @@ static int airoha_qdma_hw_init(struct airoha_qdma *qdma)
        int i;
 
        /* clear pending irqs */
-       for (i = 0; i < ARRAY_SIZE(qdma->irqmask); i++)
+       for (i = 0; i < ARRAY_SIZE(qdma->irq_banks[0].irqmask); i++)
                airoha_qdma_wr(qdma, REG_INT_STATUS(i), 0xffffffff);
 
        /* setup irqs */
-       airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX0, INT_IDX0_MASK);
-       airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX1, INT_IDX1_MASK);
-       airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX4, INT_IDX4_MASK);
+       airoha_qdma_irq_enable(&qdma->irq_banks[0], QDMA_INT_REG_IDX0,
+                              INT_IDX0_MASK);
+       airoha_qdma_irq_enable(&qdma->irq_banks[0], QDMA_INT_REG_IDX1,
+                              INT_IDX1_MASK);
+       airoha_qdma_irq_enable(&qdma->irq_banks[0], QDMA_INT_REG_IDX4,
+                              INT_IDX4_MASK);
 
        /* setup irq binding */
        for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
@@ -1226,13 +1233,14 @@ static int airoha_qdma_hw_init(struct airoha_qdma *qdma)
 
 static irqreturn_t airoha_irq_handler(int irq, void *dev_instance)
 {
-       struct airoha_qdma *qdma = dev_instance;
-       u32 intr[ARRAY_SIZE(qdma->irqmask)];
+       struct airoha_irq_bank *irq_bank = dev_instance;
+       struct airoha_qdma *qdma = irq_bank->qdma;
+       u32 intr[ARRAY_SIZE(irq_bank->irqmask)];
        int i;
 
-       for (i = 0; i < ARRAY_SIZE(qdma->irqmask); i++) {
+       for (i = 0; i < ARRAY_SIZE(intr); i++) {
                intr[i] = airoha_qdma_rr(qdma, REG_INT_STATUS(i));
-               intr[i] &= qdma->irqmask[i];
+               intr[i] &= irq_bank->irqmask[i];
                airoha_qdma_wr(qdma, REG_INT_STATUS(i), intr[i]);
        }
 
@@ -1240,7 +1248,7 @@ static irqreturn_t airoha_irq_handler(int irq, void *dev_instance)
                return IRQ_NONE;
 
        if (intr[1] & RX_DONE_INT_MASK) {
-               airoha_qdma_irq_disable(qdma, QDMA_INT_REG_IDX1,
+               airoha_qdma_irq_disable(irq_bank, QDMA_INT_REG_IDX1,
                                        RX_DONE_INT_MASK);
 
                for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
@@ -1257,7 +1265,7 @@ static irqreturn_t airoha_irq_handler(int irq, void *dev_instance)
                        if (!(intr[0] & TX_DONE_INT_MASK(i)))
                                continue;
 
-                       airoha_qdma_irq_disable(qdma, QDMA_INT_REG_IDX0,
+                       airoha_qdma_irq_disable(irq_bank, QDMA_INT_REG_IDX0,
                                                TX_DONE_INT_MASK(i));
                        napi_schedule(&qdma->q_tx_irq[i].napi);
                }
@@ -1266,6 +1274,39 @@ static irqreturn_t airoha_irq_handler(int irq, void *dev_instance)
        return IRQ_HANDLED;
 }
 
+static int airoha_qdma_init_irq_banks(struct platform_device *pdev,
+                                     struct airoha_qdma *qdma)
+{
+       struct airoha_eth *eth = qdma->eth;
+       int i, id = qdma - &eth->qdma[0];
+
+       for (i = 0; i < ARRAY_SIZE(qdma->irq_banks); i++) {
+               struct airoha_irq_bank *irq_bank = &qdma->irq_banks[i];
+               int err, irq_index = 4 * id + i;
+               const char *name;
+
+               spin_lock_init(&irq_bank->irq_lock);
+               irq_bank->qdma = qdma;
+
+               irq_bank->irq = platform_get_irq(pdev, irq_index);
+               if (irq_bank->irq < 0)
+                       return irq_bank->irq;
+
+               name = devm_kasprintf(eth->dev, GFP_KERNEL,
+                                     KBUILD_MODNAME ".%d", irq_index);
+               if (!name)
+                       return -ENOMEM;
+
+               err = devm_request_irq(eth->dev, irq_bank->irq,
+                                      airoha_irq_handler, IRQF_SHARED, name,
+                                      irq_bank);
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+
 static int airoha_qdma_init(struct platform_device *pdev,
                            struct airoha_eth *eth,
                            struct airoha_qdma *qdma)
@@ -1273,9 +1314,7 @@ static int airoha_qdma_init(struct platform_device *pdev,
        int err, id = qdma - &eth->qdma[0];
        const char *res;
 
-       spin_lock_init(&qdma->irq_lock);
        qdma->eth = eth;
-
        res = devm_kasprintf(eth->dev, GFP_KERNEL, "qdma%d", id);
        if (!res)
                return -ENOMEM;
@@ -1285,12 +1324,7 @@ static int airoha_qdma_init(struct platform_device *pdev,
                return dev_err_probe(eth->dev, PTR_ERR(qdma->regs),
                                     "failed to iomap qdma%d regs\n", id);
 
-       qdma->irq = platform_get_irq(pdev, 4 * id);
-       if (qdma->irq < 0)
-               return qdma->irq;
-
-       err = devm_request_irq(eth->dev, qdma->irq, airoha_irq_handler,
-                              IRQF_SHARED, KBUILD_MODNAME, qdma);
+       err = airoha_qdma_init_irq_banks(pdev, qdma);
        if (err)
                return err;
 
@@ -2784,7 +2818,7 @@ static int airoha_alloc_gdm_port(struct airoha_eth *eth,
        dev->features |= dev->hw_features;
        dev->vlan_features = dev->hw_features;
        dev->dev.of_node = np;
-       dev->irq = qdma->irq;
+       dev->irq = qdma->irq_banks[0].irq;
        SET_NETDEV_DEV(dev, eth->dev);
 
        /* reserve hw queues for HTB offloading */
index da5371bcd14732afdeb2430e24bcbddaf9c479f7..af263203d488e1246f4ff16921684a2532645fa4 100644 (file)
@@ -17,6 +17,7 @@
 
 #define AIROHA_MAX_NUM_GDM_PORTS       4
 #define AIROHA_MAX_NUM_QDMA            2
+#define AIROHA_MAX_NUM_IRQ_BANKS       1
 #define AIROHA_MAX_DSA_PORTS           7
 #define AIROHA_MAX_NUM_RSTS            3
 #define AIROHA_MAX_NUM_XSI_RSTS                5
@@ -452,17 +453,23 @@ struct airoha_flow_table_entry {
        unsigned long cookie;
 };
 
-struct airoha_qdma {
-       struct airoha_eth *eth;
-       void __iomem *regs;
+struct airoha_irq_bank {
+       struct airoha_qdma *qdma;
 
        /* protect concurrent irqmask accesses */
        spinlock_t irq_lock;
        u32 irqmask[QDMA_INT_REG_MAX];
        int irq;
+};
+
+struct airoha_qdma {
+       struct airoha_eth *eth;
+       void __iomem *regs;
 
        atomic_t users;
 
+       struct airoha_irq_bank irq_banks[AIROHA_MAX_NUM_IRQ_BANKS];
+
        struct airoha_tx_irq_queue q_tx_irq[AIROHA_NUM_TX_IRQ];
 
        struct airoha_queue q_tx[AIROHA_NUM_TX_RING];
index 29c8f046b9910c371ab4edc34b01f58d7383ae8d..1d99fe9f81124441e3f8fda77df4e04eee0e131b 100644 (file)
         ((_n) == 2) ? 0x0720 :         \
         ((_n) == 1) ? 0x0024 : 0x0020)
 
-#define REG_INT_ENABLE(_n)             \
-       (((_n) == 4) ? 0x0750 :         \
-        ((_n) == 3) ? 0x0744 :         \
-        ((_n) == 2) ? 0x0740 :         \
-        ((_n) == 1) ? 0x002c : 0x0028)
+#define REG_INT_ENABLE(_b, _n)         \
+       (((_n) == 4) ? 0x0750 + ((_b) << 5) :   \
+        ((_n) == 3) ? 0x0744 + ((_b) << 5) :   \
+        ((_n) == 2) ? 0x0740 + ((_b) << 5) :   \
+        ((_n) == 1) ? 0x002c + ((_b) << 3) :   \
+                      0x0028 + ((_b) << 3))
 
 /* QDMA_CSR_INT_ENABLE1 */
 #define RX15_COHERENT_INT_MASK         BIT(31)