]> git.baikalelectronics.ru Git - kernel.git/commitdiff
tsnep: Move interrupt from device to queue
authorGerhard Engleder <gerhard@engleder-embedded.com>
Tue, 27 Sep 2022 19:58:39 +0000 (21:58 +0200)
committerDavid S. Miller <davem@davemloft.net>
Fri, 30 Sep 2022 10:32:26 +0000 (11:32 +0100)
For multiple queues multiple interrupts shall be used. Therefore, rework
global interrupt to per queue interrupt.

Every interrupt name shall contain interface name and queue information.
To get a valid interface name, the interrupt request needs to by done
during open like in other drivers. Additionally, this allows the removal
of some initialisation checks in the interrupt handler.

Signed-off-by: Gerhard Engleder <gerhard@engleder-embedded.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/engleder/tsnep.h
drivers/net/ethernet/engleder/tsnep_main.c

index 147fe03ca979b9d32e6cb314e6fc9e5fd1e14bdf..149c9acbae9c67572a6a0d2a30c013df5f5cf1b1 100644 (file)
@@ -55,6 +55,7 @@ struct tsnep_tx_entry {
 struct tsnep_tx {
        struct tsnep_adapter *adapter;
        void __iomem *addr;
+       int queue_index;
 
        void *page[TSNEP_RING_PAGE_COUNT];
        dma_addr_t page_dma[TSNEP_RING_PAGE_COUNT];
@@ -105,12 +106,14 @@ struct tsnep_rx {
 
 struct tsnep_queue {
        struct tsnep_adapter *adapter;
+       char name[IFNAMSIZ + 9];
 
        struct tsnep_tx *tx;
        struct tsnep_rx *rx;
 
        struct napi_struct napi;
 
+       int irq;
        u32 irq_mask;
 };
 
@@ -126,7 +129,6 @@ struct tsnep_adapter {
        struct platform_device *pdev;
        struct device *dmadev;
        void __iomem *addr;
-       int irq;
 
        bool gate_control;
        /* gate control lock */
index fbb0243661bc6bec8cfe075efeeb253c14e4e7f1..fd6a392f5b0b5e01321944fb4e824555cefdcaad 100644 (file)
@@ -60,22 +60,29 @@ static irqreturn_t tsnep_irq(int irq, void *arg)
                iowrite32(active, adapter->addr + ECM_INT_ACKNOWLEDGE);
 
        /* handle link interrupt */
-       if ((active & ECM_INT_LINK) != 0) {
-               if (adapter->netdev->phydev)
-                       phy_mac_interrupt(adapter->netdev->phydev);
-       }
+       if ((active & ECM_INT_LINK) != 0)
+               phy_mac_interrupt(adapter->netdev->phydev);
 
        /* handle TX/RX queue 0 interrupt */
        if ((active & adapter->queue[0].irq_mask) != 0) {
-               if (adapter->netdev) {
-                       tsnep_disable_irq(adapter, adapter->queue[0].irq_mask);
-                       napi_schedule(&adapter->queue[0].napi);
-               }
+               tsnep_disable_irq(adapter, adapter->queue[0].irq_mask);
+               napi_schedule(&adapter->queue[0].napi);
        }
 
        return IRQ_HANDLED;
 }
 
+static irqreturn_t tsnep_irq_txrx(int irq, void *arg)
+{
+       struct tsnep_queue *queue = arg;
+
+       /* handle TX/RX queue interrupt */
+       tsnep_disable_irq(queue->adapter, queue->irq_mask);
+       napi_schedule(&queue->napi);
+
+       return IRQ_HANDLED;
+}
+
 static int tsnep_mdiobus_read(struct mii_bus *bus, int addr, int regnum)
 {
        struct tsnep_adapter *adapter = bus->priv;
@@ -536,7 +543,7 @@ static bool tsnep_tx_poll(struct tsnep_tx *tx, int napi_budget)
 }
 
 static int tsnep_tx_open(struct tsnep_adapter *adapter, void __iomem *addr,
-                        struct tsnep_tx *tx)
+                        int queue_index, struct tsnep_tx *tx)
 {
        dma_addr_t dma;
        int retval;
@@ -544,6 +551,7 @@ static int tsnep_tx_open(struct tsnep_adapter *adapter, void __iomem *addr,
        memset(tx, 0, sizeof(*tx));
        tx->adapter = adapter;
        tx->addr = addr;
+       tx->queue_index = queue_index;
 
        retval = tsnep_tx_ring_init(tx);
        if (retval)
@@ -854,6 +862,56 @@ static int tsnep_poll(struct napi_struct *napi, int budget)
        return min(done, budget - 1);
 }
 
+static int tsnep_request_irq(struct tsnep_queue *queue, bool first)
+{
+       const char *name = netdev_name(queue->adapter->netdev);
+       irq_handler_t handler;
+       void *dev;
+       int retval;
+
+       if (first) {
+               sprintf(queue->name, "%s-mac", name);
+               handler = tsnep_irq;
+               dev = queue->adapter;
+       } else {
+               if (queue->tx && queue->rx)
+                       sprintf(queue->name, "%s-txrx-%d", name,
+                               queue->rx->queue_index);
+               else if (queue->tx)
+                       sprintf(queue->name, "%s-tx-%d", name,
+                               queue->tx->queue_index);
+               else
+                       sprintf(queue->name, "%s-rx-%d", name,
+                               queue->rx->queue_index);
+               handler = tsnep_irq_txrx;
+               dev = queue;
+       }
+
+       retval = request_irq(queue->irq, handler, 0, queue->name, dev);
+       if (retval) {
+               /* if name is empty, then interrupt won't be freed */
+               memset(queue->name, 0, sizeof(queue->name));
+       }
+
+       return retval;
+}
+
+static void tsnep_free_irq(struct tsnep_queue *queue, bool first)
+{
+       void *dev;
+
+       if (!strlen(queue->name))
+               return;
+
+       if (first)
+               dev = queue->adapter;
+       else
+               dev = queue;
+
+       free_irq(queue->irq, dev);
+       memset(queue->name, 0, sizeof(queue->name));
+}
+
 static int tsnep_netdev_open(struct net_device *netdev)
 {
        struct tsnep_adapter *adapter = netdev_priv(netdev);
@@ -863,15 +921,11 @@ static int tsnep_netdev_open(struct net_device *netdev)
        int rx_queue_index = 0;
        int retval;
 
-       retval = tsnep_phy_open(adapter);
-       if (retval)
-               return retval;
-
        for (i = 0; i < adapter->num_queues; i++) {
                adapter->queue[i].adapter = adapter;
                if (adapter->queue[i].tx) {
                        addr = adapter->addr + TSNEP_QUEUE(tx_queue_index);
-                       retval = tsnep_tx_open(adapter, addr,
+                       retval = tsnep_tx_open(adapter, addr, tx_queue_index,
                                               adapter->queue[i].tx);
                        if (retval)
                                goto failed;
@@ -886,6 +940,14 @@ static int tsnep_netdev_open(struct net_device *netdev)
                                goto failed;
                        rx_queue_index++;
                }
+
+               retval = tsnep_request_irq(&adapter->queue[i], i == 0);
+               if (retval) {
+                       netif_err(adapter, drv, adapter->netdev,
+                                 "can't get assigned irq %d.\n",
+                                 adapter->queue[i].irq);
+                       goto failed;
+               }
        }
 
        retval = netif_set_real_num_tx_queues(adapter->netdev,
@@ -897,6 +959,11 @@ static int tsnep_netdev_open(struct net_device *netdev)
        if (retval)
                goto failed;
 
+       tsnep_enable_irq(adapter, ECM_INT_LINK);
+       retval = tsnep_phy_open(adapter);
+       if (retval)
+               goto phy_failed;
+
        for (i = 0; i < adapter->num_queues; i++) {
                netif_napi_add(adapter->netdev, &adapter->queue[i].napi,
                               tsnep_poll);
@@ -907,14 +974,18 @@ static int tsnep_netdev_open(struct net_device *netdev)
 
        return 0;
 
+phy_failed:
+       tsnep_disable_irq(adapter, ECM_INT_LINK);
+       tsnep_phy_close(adapter);
 failed:
        for (i = 0; i < adapter->num_queues; i++) {
+               tsnep_free_irq(&adapter->queue[i], i == 0);
+
                if (adapter->queue[i].rx)
                        tsnep_rx_close(adapter->queue[i].rx);
                if (adapter->queue[i].tx)
                        tsnep_tx_close(adapter->queue[i].tx);
        }
-       tsnep_phy_close(adapter);
        return retval;
 }
 
@@ -923,20 +994,23 @@ static int tsnep_netdev_close(struct net_device *netdev)
        struct tsnep_adapter *adapter = netdev_priv(netdev);
        int i;
 
+       tsnep_disable_irq(adapter, ECM_INT_LINK);
+       tsnep_phy_close(adapter);
+
        for (i = 0; i < adapter->num_queues; i++) {
                tsnep_disable_irq(adapter, adapter->queue[i].irq_mask);
 
                napi_disable(&adapter->queue[i].napi);
                netif_napi_del(&adapter->queue[i].napi);
 
+               tsnep_free_irq(&adapter->queue[i], i == 0);
+
                if (adapter->queue[i].rx)
                        tsnep_rx_close(adapter->queue[i].rx);
                if (adapter->queue[i].tx)
                        tsnep_tx_close(adapter->queue[i].tx);
        }
 
-       tsnep_phy_close(adapter);
-
        return 0;
 }
 
@@ -1225,10 +1299,8 @@ static int tsnep_probe(struct platform_device *pdev)
        adapter->addr = devm_ioremap_resource(&pdev->dev, io);
        if (IS_ERR(adapter->addr))
                return PTR_ERR(adapter->addr);
-       adapter->irq = platform_get_irq(pdev, 0);
        netdev->mem_start = io->start;
        netdev->mem_end = io->end;
-       netdev->irq = adapter->irq;
 
        type = ioread32(adapter->addr + ECM_TYPE);
        revision = (type & ECM_REVISION_MASK) >> ECM_REVISION_SHIFT;
@@ -1238,10 +1310,14 @@ static int tsnep_probe(struct platform_device *pdev)
        adapter->num_tx_queues = TSNEP_QUEUES;
        adapter->num_rx_queues = TSNEP_QUEUES;
        adapter->num_queues = TSNEP_QUEUES;
+       adapter->queue[0].irq = platform_get_irq(pdev, 0);
        adapter->queue[0].tx = &adapter->tx[0];
        adapter->queue[0].rx = &adapter->rx[0];
        adapter->queue[0].irq_mask = ECM_INT_TX_0 | ECM_INT_RX_0;
 
+       netdev->irq = adapter->queue[0].irq;
+       tsnep_disable_irq(adapter, ECM_INT_ALL);
+
        retval = dma_set_mask_and_coherent(&adapter->pdev->dev,
                                           DMA_BIT_MASK(64));
        if (retval) {
@@ -1249,19 +1325,9 @@ static int tsnep_probe(struct platform_device *pdev)
                return retval;
        }
 
-       tsnep_disable_irq(adapter, ECM_INT_ALL);
-       retval = devm_request_irq(&adapter->pdev->dev, adapter->irq, tsnep_irq,
-                                 0, TSNEP, adapter);
-       if (retval != 0) {
-               dev_err(&adapter->pdev->dev, "can't get assigned irq %d.\n",
-                       adapter->irq);
-               return retval;
-       }
-       tsnep_enable_irq(adapter, ECM_INT_LINK);
-
        retval = tsnep_mac_init(adapter);
        if (retval)
-               goto mac_init_failed;
+               return retval;
 
        retval = tsnep_mdio_init(adapter);
        if (retval)
@@ -1307,8 +1373,6 @@ phy_init_failed:
        if (adapter->mdiobus)
                mdiobus_unregister(adapter->mdiobus);
 mdio_init_failed:
-mac_init_failed:
-       tsnep_disable_irq(adapter, ECM_INT_ALL);
        return retval;
 }