From f4983704a63b3764418905a77d48105a8cbce97f Mon Sep 17 00:00:00 2001 From: Sandeep Gopalpet Date: Mon, 2 Nov 2009 07:03:09 +0000 Subject: [PATCH] gianfar: Introduce logical group support. This patch introduces the group structure. The elements of this structure are the interrupt lines, their corresponding names, the register memory map. The elements for this group are factored out from the gfar_private structure. The introduction of group structure will help in providing support for newer versions of etsec. Currently, the support is present only for single group and single tx/rx queues. Signed-off-by: Sandeep Gopalpet Signed-off-by: David S. Miller --- drivers/net/gianfar.c | 364 ++++++++++++++++++---------------- drivers/net/gianfar.h | 38 +++- drivers/net/gianfar_ethtool.c | 14 +- drivers/net/gianfar_sysfs.c | 34 ++-- 4 files changed, 250 insertions(+), 200 deletions(-) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 354b2b5936ea..fa0188ea9233 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -151,7 +151,6 @@ MODULE_LICENSE("GPL"); static void gfar_init_rxbdp(struct gfar_priv_rx_q *rx_queue, struct rxbd8 *bdp, dma_addr_t buf) { - struct net_device *dev = rx_queue->dev; u32 lstatus; bdp->bufPtr = buf; @@ -290,9 +289,9 @@ static int gfar_alloc_skb_resources(struct net_device *ndev) static void gfar_init_mac(struct net_device *ndev) { struct gfar_private *priv = netdev_priv(ndev); - struct gfar __iomem *regs = priv->regs; struct gfar_priv_tx_q *tx_queue = NULL; struct gfar_priv_rx_q *rx_queue = NULL; + struct gfar __iomem *regs = priv->gfargrp.regs; u32 rctrl = 0; u32 tctrl = 0; u32 attrs = 0; @@ -407,24 +406,25 @@ static int gfar_of_init(struct net_device *dev) /* get a pointer to the register memory */ addr = of_translate_address(np, of_get_address(np, 0, &size, NULL)); - priv->regs = ioremap(addr, size); + priv->gfargrp.regs = ioremap(addr, size); - if (priv->regs == NULL) + if (priv->gfargrp.regs == NULL) return -ENOMEM; - priv->interruptTransmit = irq_of_parse_and_map(np, 0); + priv->gfargrp.priv = priv; /* back pointer from group to priv */ + priv->gfargrp.interruptTransmit = irq_of_parse_and_map(np, 0); model = of_get_property(np, "model", NULL); /* If we aren't the FEC we have multiple interrupts */ if (model && strcasecmp(model, "FEC")) { - priv->interruptReceive = irq_of_parse_and_map(np, 1); + priv->gfargrp.interruptReceive = irq_of_parse_and_map(np, 1); - priv->interruptError = irq_of_parse_and_map(np, 2); + priv->gfargrp.interruptError = irq_of_parse_and_map(np, 2); - if (priv->interruptTransmit < 0 || - priv->interruptReceive < 0 || - priv->interruptError < 0) { + if (priv->gfargrp.interruptTransmit < 0 || + priv->gfargrp.interruptReceive < 0 || + priv->gfargrp.interruptError < 0) { err = -EINVAL; goto err_out; } @@ -491,7 +491,7 @@ static int gfar_of_init(struct net_device *dev) return 0; err_out: - iounmap(priv->regs); + iounmap(priv->gfargrp.regs); return err; } @@ -517,6 +517,7 @@ static int gfar_probe(struct of_device *ofdev, u32 tempval; struct net_device *dev = NULL; struct gfar_private *priv = NULL; + struct gfar __iomem *regs = NULL; int err = 0; int len_devname; @@ -549,32 +550,34 @@ static int gfar_probe(struct of_device *ofdev, spin_lock_init(&priv->tx_queue->txlock); spin_lock_init(&priv->rx_queue->rxlock); + spin_lock_init(&priv->gfargrp.grplock); spin_lock_init(&priv->bflock); INIT_WORK(&priv->reset_task, gfar_reset_task); dev_set_drvdata(&ofdev->dev, priv); + regs = priv->gfargrp.regs; /* Stop the DMA engine now, in case it was running before */ /* (The firmware could have used it, and left it running). */ gfar_halt(dev); /* Reset MAC layer */ - gfar_write(&priv->regs->maccfg1, MACCFG1_SOFT_RESET); + gfar_write(®s->maccfg1, MACCFG1_SOFT_RESET); /* We need to delay at least 3 TX clocks */ udelay(2); tempval = (MACCFG1_TX_FLOW | MACCFG1_RX_FLOW); - gfar_write(&priv->regs->maccfg1, tempval); + gfar_write(®s->maccfg1, tempval); /* Initialize MACCFG2. */ - gfar_write(&priv->regs->maccfg2, MACCFG2_INIT_SETTINGS); + gfar_write(®s->maccfg2, MACCFG2_INIT_SETTINGS); /* Initialize ECNTRL */ - gfar_write(&priv->regs->ecntrl, ECNTRL_INIT_SETTINGS); + gfar_write(®s->ecntrl, ECNTRL_INIT_SETTINGS); /* Set the dev->base_addr to the gfar reg region */ - dev->base_addr = (unsigned long) (priv->regs); + dev->base_addr = (unsigned long) regs; SET_NETDEV_DEV(dev, &ofdev->dev); @@ -602,35 +605,35 @@ static int gfar_probe(struct of_device *ofdev, priv->extended_hash = 1; priv->hash_width = 9; - priv->hash_regs[0] = &priv->regs->igaddr0; - priv->hash_regs[1] = &priv->regs->igaddr1; - priv->hash_regs[2] = &priv->regs->igaddr2; - priv->hash_regs[3] = &priv->regs->igaddr3; - priv->hash_regs[4] = &priv->regs->igaddr4; - priv->hash_regs[5] = &priv->regs->igaddr5; - priv->hash_regs[6] = &priv->regs->igaddr6; - priv->hash_regs[7] = &priv->regs->igaddr7; - priv->hash_regs[8] = &priv->regs->gaddr0; - priv->hash_regs[9] = &priv->regs->gaddr1; - priv->hash_regs[10] = &priv->regs->gaddr2; - priv->hash_regs[11] = &priv->regs->gaddr3; - priv->hash_regs[12] = &priv->regs->gaddr4; - priv->hash_regs[13] = &priv->regs->gaddr5; - priv->hash_regs[14] = &priv->regs->gaddr6; - priv->hash_regs[15] = &priv->regs->gaddr7; + priv->hash_regs[0] = ®s->igaddr0; + priv->hash_regs[1] = ®s->igaddr1; + priv->hash_regs[2] = ®s->igaddr2; + priv->hash_regs[3] = ®s->igaddr3; + priv->hash_regs[4] = ®s->igaddr4; + priv->hash_regs[5] = ®s->igaddr5; + priv->hash_regs[6] = ®s->igaddr6; + priv->hash_regs[7] = ®s->igaddr7; + priv->hash_regs[8] = ®s->gaddr0; + priv->hash_regs[9] = ®s->gaddr1; + priv->hash_regs[10] = ®s->gaddr2; + priv->hash_regs[11] = ®s->gaddr3; + priv->hash_regs[12] = ®s->gaddr4; + priv->hash_regs[13] = ®s->gaddr5; + priv->hash_regs[14] = ®s->gaddr6; + priv->hash_regs[15] = ®s->gaddr7; } else { priv->extended_hash = 0; priv->hash_width = 8; - priv->hash_regs[0] = &priv->regs->gaddr0; - priv->hash_regs[1] = &priv->regs->gaddr1; - priv->hash_regs[2] = &priv->regs->gaddr2; - priv->hash_regs[3] = &priv->regs->gaddr3; - priv->hash_regs[4] = &priv->regs->gaddr4; - priv->hash_regs[5] = &priv->regs->gaddr5; - priv->hash_regs[6] = &priv->regs->gaddr6; - priv->hash_regs[7] = &priv->regs->gaddr7; + priv->hash_regs[0] = ®s->gaddr0; + priv->hash_regs[1] = ®s->gaddr1; + priv->hash_regs[2] = ®s->gaddr2; + priv->hash_regs[3] = ®s->gaddr3; + priv->hash_regs[4] = ®s->gaddr4; + priv->hash_regs[5] = ®s->gaddr5; + priv->hash_regs[6] = ®s->gaddr6; + priv->hash_regs[7] = ®s->gaddr7; } if (priv->device_flags & FSL_GIANFAR_DEV_HAS_PADDING) @@ -672,20 +675,20 @@ static int gfar_probe(struct of_device *ofdev, /* fill out IRQ number and name fields */ len_devname = strlen(dev->name); - strncpy(&priv->int_name_tx[0], dev->name, len_devname); + strncpy(&priv->gfargrp.int_name_tx[0], dev->name, len_devname); if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { - strncpy(&priv->int_name_tx[len_devname], + strncpy(&priv->gfargrp.int_name_tx[len_devname], "_tx", sizeof("_tx") + 1); - strncpy(&priv->int_name_rx[0], dev->name, len_devname); - strncpy(&priv->int_name_rx[len_devname], + strncpy(&priv->gfargrp.int_name_rx[0], dev->name, len_devname); + strncpy(&priv->gfargrp.int_name_rx[len_devname], "_rx", sizeof("_rx") + 1); - strncpy(&priv->int_name_er[0], dev->name, len_devname); - strncpy(&priv->int_name_er[len_devname], + strncpy(&priv->gfargrp.int_name_er[0], dev->name, len_devname); + strncpy(&priv->gfargrp.int_name_er[len_devname], "_er", sizeof("_er") + 1); } else - priv->int_name_tx[len_devname] = '\0'; + priv->gfargrp.int_name_tx[len_devname] = '\0'; /* Create all the sysfs files */ gfar_init_sysfs(dev); @@ -702,7 +705,7 @@ static int gfar_probe(struct of_device *ofdev, return 0; register_fail: - iounmap(priv->regs); + iounmap(priv->gfargrp.regs); kfree(priv->rx_queue); rx_queue_fail: kfree(priv->tx_queue); @@ -727,7 +730,7 @@ static int gfar_remove(struct of_device *ofdev) dev_set_drvdata(&ofdev->dev, NULL); unregister_netdev(priv->ndev); - iounmap(priv->regs); + iounmap(priv->gfargrp.regs); free_netdev(priv->ndev); return 0; @@ -741,6 +744,7 @@ static int gfar_suspend(struct device *dev) struct net_device *ndev = priv->ndev; struct gfar_priv_tx_q *tx_queue = NULL; struct gfar_priv_rx_q *rx_queue = NULL; + struct gfar __iomem *regs = NULL; unsigned long flags; u32 tempval; @@ -750,6 +754,7 @@ static int gfar_suspend(struct device *dev) netif_device_detach(ndev); tx_queue = priv->tx_queue; rx_queue = priv->rx_queue; + regs = priv->gfargrp.regs; if (netif_running(ndev)) { spin_lock_irqsave(&tx_queue->txlock, flags); @@ -758,14 +763,14 @@ static int gfar_suspend(struct device *dev) gfar_halt_nodisable(ndev); /* Disable Tx, and Rx if wake-on-LAN is disabled. */ - tempval = gfar_read(&priv->regs->maccfg1); + tempval = gfar_read(®s->maccfg1); tempval &= ~MACCFG1_TX_EN; if (!magic_packet) tempval &= ~MACCFG1_RX_EN; - gfar_write(&priv->regs->maccfg1, tempval); + gfar_write(®s->maccfg1, tempval); spin_unlock(&rx_queue->rxlock); spin_unlock_irqrestore(&tx_queue->txlock, flags); @@ -774,12 +779,12 @@ static int gfar_suspend(struct device *dev) if (magic_packet) { /* Enable interrupt on Magic Packet */ - gfar_write(&priv->regs->imask, IMASK_MAG); + gfar_write(®s->imask, IMASK_MAG); /* Enable Magic Packet mode */ - tempval = gfar_read(&priv->regs->maccfg2); + tempval = gfar_read(®s->maccfg2); tempval |= MACCFG2_MPEN; - gfar_write(&priv->regs->maccfg2, tempval); + gfar_write(®s->maccfg2, tempval); } else { phy_stop(priv->phydev); } @@ -794,6 +799,7 @@ static int gfar_resume(struct device *dev) struct net_device *ndev = priv->ndev; struct gfar_priv_tx_q *tx_queue = NULL; struct gfar_priv_rx_q *rx_queue = NULL; + struct gfar __iomem *regs = NULL; unsigned long flags; u32 tempval; int magic_packet = priv->wol_en && @@ -812,13 +818,14 @@ static int gfar_resume(struct device *dev) */ rx_queue = priv->rx_queue; tx_queue = priv->tx_queue; + regs = priv->gfargrp.regs; spin_lock_irqsave(&tx_queue->txlock, flags); spin_lock(&rx_queue->rxlock); - tempval = gfar_read(&priv->regs->maccfg2); + tempval = gfar_read(®s->maccfg2); tempval &= ~MACCFG2_MPEN; - gfar_write(&priv->regs->maccfg2, tempval); + gfar_write(®s->maccfg2, tempval); gfar_start(ndev); @@ -893,7 +900,11 @@ static int gfar_legacy_resume(struct of_device *ofdev) static phy_interface_t gfar_get_interface(struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); - u32 ecntrl = gfar_read(&priv->regs->ecntrl); + struct gfar __iomem *regs = NULL; + u32 ecntrl; + + regs = priv->gfargrp.regs; + ecntrl = gfar_read(®s->ecntrl); if (ecntrl & ECNTRL_SGMII_MODE) return PHY_INTERFACE_MODE_SGMII; @@ -1015,46 +1026,48 @@ static void gfar_configure_serdes(struct net_device *dev) static void init_registers(struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); + struct gfar __iomem *regs = NULL; + regs = priv->gfargrp.regs; /* Clear IEVENT */ - gfar_write(&priv->regs->ievent, IEVENT_INIT_CLEAR); + gfar_write(®s->ievent, IEVENT_INIT_CLEAR); /* Initialize IMASK */ - gfar_write(&priv->regs->imask, IMASK_INIT_CLEAR); + gfar_write(®s->imask, IMASK_INIT_CLEAR); /* Init hash registers to zero */ - gfar_write(&priv->regs->igaddr0, 0); - gfar_write(&priv->regs->igaddr1, 0); - gfar_write(&priv->regs->igaddr2, 0); - gfar_write(&priv->regs->igaddr3, 0); - gfar_write(&priv->regs->igaddr4, 0); - gfar_write(&priv->regs->igaddr5, 0); - gfar_write(&priv->regs->igaddr6, 0); - gfar_write(&priv->regs->igaddr7, 0); - - gfar_write(&priv->regs->gaddr0, 0); - gfar_write(&priv->regs->gaddr1, 0); - gfar_write(&priv->regs->gaddr2, 0); - gfar_write(&priv->regs->gaddr3, 0); - gfar_write(&priv->regs->gaddr4, 0); - gfar_write(&priv->regs->gaddr5, 0); - gfar_write(&priv->regs->gaddr6, 0); - gfar_write(&priv->regs->gaddr7, 0); + gfar_write(®s->igaddr0, 0); + gfar_write(®s->igaddr1, 0); + gfar_write(®s->igaddr2, 0); + gfar_write(®s->igaddr3, 0); + gfar_write(®s->igaddr4, 0); + gfar_write(®s->igaddr5, 0); + gfar_write(®s->igaddr6, 0); + gfar_write(®s->igaddr7, 0); + + gfar_write(®s->gaddr0, 0); + gfar_write(®s->gaddr1, 0); + gfar_write(®s->gaddr2, 0); + gfar_write(®s->gaddr3, 0); + gfar_write(®s->gaddr4, 0); + gfar_write(®s->gaddr5, 0); + gfar_write(®s->gaddr6, 0); + gfar_write(®s->gaddr7, 0); /* Zero out the rmon mib registers if it has them */ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { - memset_io(&(priv->regs->rmon), 0, sizeof (struct rmon_mib)); + memset_io(&(regs->rmon), 0, sizeof (struct rmon_mib)); /* Mask off the CAM interrupts */ - gfar_write(&priv->regs->rmon.cam1, 0xffffffff); - gfar_write(&priv->regs->rmon.cam2, 0xffffffff); + gfar_write(®s->rmon.cam1, 0xffffffff); + gfar_write(®s->rmon.cam2, 0xffffffff); } /* Initialize the max receive buffer length */ - gfar_write(&priv->regs->mrblr, priv->rx_buffer_size); + gfar_write(®s->mrblr, priv->rx_buffer_size); /* Initialize the Minimum Frame Length Register */ - gfar_write(&priv->regs->minflr, MINFLR_INIT_SETTINGS); + gfar_write(®s->minflr, MINFLR_INIT_SETTINGS); } @@ -1062,7 +1075,7 @@ static void init_registers(struct net_device *dev) static void gfar_halt_nodisable(struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); - struct gfar __iomem *regs = priv->regs; + struct gfar __iomem *regs = priv->gfargrp.regs; u32 tempval; /* Mask all interrupts */ @@ -1072,13 +1085,13 @@ static void gfar_halt_nodisable(struct net_device *dev) gfar_write(®s->ievent, IEVENT_INIT_CLEAR); /* Stop the DMA, and wait for it to stop */ - tempval = gfar_read(&priv->regs->dmactrl); + tempval = gfar_read(®s->dmactrl); if ((tempval & (DMACTRL_GRS | DMACTRL_GTS)) != (DMACTRL_GRS | DMACTRL_GTS)) { tempval |= (DMACTRL_GRS | DMACTRL_GTS); - gfar_write(&priv->regs->dmactrl, tempval); + gfar_write(®s->dmactrl, tempval); - while (!(gfar_read(&priv->regs->ievent) & + while (!(gfar_read(®s->ievent) & (IEVENT_GRSC | IEVENT_GTSC))) cpu_relax(); } @@ -1088,7 +1101,7 @@ static void gfar_halt_nodisable(struct net_device *dev) void gfar_halt(struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); - struct gfar __iomem *regs = priv->regs; + struct gfar __iomem *regs = priv->gfargrp.regs; u32 tempval; gfar_halt_nodisable(dev); @@ -1122,11 +1135,11 @@ void stop_gfar(struct net_device *dev) /* Free the IRQs */ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { - free_irq(priv->interruptError, dev); - free_irq(priv->interruptTransmit, dev); - free_irq(priv->interruptReceive, dev); + free_irq(priv->gfargrp.interruptError, &priv->gfargrp); + free_irq(priv->gfargrp.interruptTransmit, &priv->gfargrp); + free_irq(priv->gfargrp.interruptReceive, &priv->gfargrp); } else { - free_irq(priv->interruptTransmit, dev); + free_irq(priv->gfargrp.interruptTransmit, &priv->gfargrp); } free_skb_resources(priv); @@ -1201,9 +1214,7 @@ static void free_skb_resources(struct gfar_private *priv) void gfar_start(struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); - struct gfar_priv_tx_q *tx_queue; - struct gfar_priv_rx_q *rx_queue; - struct gfar __iomem *regs = priv->regs; + struct gfar __iomem *regs = priv->gfargrp.regs; u32 tempval; /* Enable Rx and Tx in MACCFG1 */ @@ -1212,14 +1223,14 @@ void gfar_start(struct net_device *dev) gfar_write(®s->maccfg1, tempval); /* Initialize DMACTRL to have WWR and WOP */ - tempval = gfar_read(&priv->regs->dmactrl); + tempval = gfar_read(®s->dmactrl); tempval |= DMACTRL_INIT_SETTINGS; - gfar_write(&priv->regs->dmactrl, tempval); + gfar_write(®s->dmactrl, tempval); /* Make sure we aren't stopped */ - tempval = gfar_read(&priv->regs->dmactrl); + tempval = gfar_read(®s->dmactrl); tempval &= ~(DMACTRL_GRS | DMACTRL_GTS); - gfar_write(&priv->regs->dmactrl, tempval); + gfar_write(®s->dmactrl, tempval); /* Clear THLT/RHLT, so that the DMA starts polling now */ gfar_write(®s->tstat, TSTAT_CLEAR_THALT); @@ -1235,7 +1246,7 @@ void gfar_start(struct net_device *dev) int startup_gfar(struct net_device *ndev) { struct gfar_private *priv = netdev_priv(ndev); - struct gfar __iomem *regs = priv->regs; + struct gfar __iomem *regs = priv->gfargrp.regs; int err; gfar_write(®s->imask, IMASK_INIT_CLEAR); @@ -1251,39 +1262,46 @@ int startup_gfar(struct net_device *ndev) if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { /* Install our interrupt handlers for Error, * Transmit, and Receive */ - err = request_irq(priv->interruptError, gfar_error, 0, - priv->int_name_er, ndev); + err = request_irq(priv->gfargrp.interruptError, gfar_error, 0, + priv->gfargrp.int_name_er, &priv->gfargrp); if (err) { if (netif_msg_intr(priv)) pr_err("%s: Can't get IRQ %d\n", ndev->name, - priv->interruptError); + priv->gfargrp.interruptError); goto err_irq_fail; } - err = request_irq(priv->interruptTransmit, gfar_transmit, 0, - priv->int_name_tx, ndev); + err = request_irq(priv->gfargrp.interruptTransmit, + gfar_transmit, 0, + priv->gfargrp.int_name_tx, + &priv->gfargrp); if (err) { if (netif_msg_intr(priv)) pr_err("%s: Can't get IRQ %d\n", ndev->name, - priv->interruptTransmit); + priv->gfargrp.interruptTransmit); goto tx_irq_fail; } - err = request_irq(priv->interruptReceive, gfar_receive, 0, - priv->int_name_rx, ndev); + err = request_irq(priv->gfargrp.interruptReceive, + gfar_receive, 0, + priv->gfargrp.int_name_rx, + &priv->gfargrp); if (err) { if (netif_msg_intr(priv)) pr_err("%s: Can't get IRQ %d (receive0)\n", - ndev->name, priv->interruptReceive); + ndev->name, + priv->gfargrp.interruptReceive); goto rx_irq_fail; } } else { - err = request_irq(priv->interruptTransmit, gfar_interrupt, - 0, priv->int_name_tx, ndev); + err = request_irq(priv->gfargrp.interruptTransmit, + gfar_interrupt, 0, + priv->gfargrp.int_name_tx, + &priv->gfargrp); if (err) { if (netif_msg_intr(priv)) pr_err("%s: Can't get IRQ %d\n", ndev->name, - priv->interruptTransmit); + priv->gfargrp.interruptTransmit); goto err_irq_fail; } } @@ -1296,9 +1314,9 @@ int startup_gfar(struct net_device *ndev) return 0; rx_irq_fail: - free_irq(priv->interruptTransmit, ndev); + free_irq(priv->gfargrp.interruptTransmit, &priv->gfargrp); tx_irq_fail: - free_irq(priv->interruptError, ndev); + free_irq(priv->gfargrp.interruptError, &priv->gfargrp); err_irq_fail: free_skb_resources(priv); return err; @@ -1403,6 +1421,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); struct gfar_priv_tx_q *tx_queue = NULL; + struct gfar __iomem *regs = NULL; struct txfcb *fcb = NULL; struct txbd8 *txbdp, *txbdp_start, *base; u32 lstatus; @@ -1413,6 +1432,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) tx_queue = priv->tx_queue; base = tx_queue->tx_bd_base; + regs = priv->gfargrp.regs; /* make space for additional header when fcb is needed */ if (((skb->ip_summed == CHECKSUM_PARTIAL) || @@ -1536,7 +1556,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) } /* Tell the DMA to go go go */ - gfar_write(&priv->regs->tstat, TSTAT_CLEAR_THALT); + gfar_write(®s->tstat, TSTAT_CLEAR_THALT); /* Unlock priv */ spin_unlock_irqrestore(&tx_queue->txlock, flags); @@ -1579,40 +1599,42 @@ static void gfar_vlan_rx_register(struct net_device *dev, { struct gfar_private *priv = netdev_priv(dev); struct gfar_priv_rx_q *rx_queue = NULL; + struct gfar __iomem *regs = NULL; unsigned long flags; u32 tempval; rx_queue = priv->rx_queue; + regs = priv->gfargrp.regs; spin_lock_irqsave(&rx_queue->rxlock, flags); priv->vlgrp = grp; if (grp) { /* Enable VLAN tag insertion */ - tempval = gfar_read(&priv->regs->tctrl); + tempval = gfar_read(®s->tctrl); tempval |= TCTRL_VLINS; - gfar_write(&priv->regs->tctrl, tempval); + gfar_write(®s->tctrl, tempval); /* Enable VLAN tag extraction */ - tempval = gfar_read(&priv->regs->rctrl); + tempval = gfar_read(®s->rctrl); tempval |= (RCTRL_VLEX | RCTRL_PRSDEP_INIT); - gfar_write(&priv->regs->rctrl, tempval); + gfar_write(®s->rctrl, tempval); } else { /* Disable VLAN tag insertion */ - tempval = gfar_read(&priv->regs->tctrl); + tempval = gfar_read(®s->tctrl); tempval &= ~TCTRL_VLINS; - gfar_write(&priv->regs->tctrl, tempval); + gfar_write(®s->tctrl, tempval); /* Disable VLAN tag extraction */ - tempval = gfar_read(&priv->regs->rctrl); + tempval = gfar_read(®s->rctrl); tempval &= ~RCTRL_VLEX; /* If parse is no longer required, then disable parser */ if (tempval & RCTRL_REQ_PARSER) tempval |= RCTRL_PRSDEP_INIT; else tempval &= ~RCTRL_PRSDEP_INIT; - gfar_write(&priv->regs->rctrl, tempval); + gfar_write(®s->rctrl, tempval); } gfar_change_mtu(dev, dev->mtu); @@ -1624,6 +1646,7 @@ static int gfar_change_mtu(struct net_device *dev, int new_mtu) { int tempsize, tempval; struct gfar_private *priv = netdev_priv(dev); + struct gfar __iomem *regs = priv->gfargrp.regs; int oldsize = priv->rx_buffer_size; int frame_size = new_mtu + ETH_HLEN; @@ -1655,20 +1678,20 @@ static int gfar_change_mtu(struct net_device *dev, int new_mtu) dev->mtu = new_mtu; - gfar_write(&priv->regs->mrblr, priv->rx_buffer_size); - gfar_write(&priv->regs->maxfrm, priv->rx_buffer_size); + gfar_write(®s->mrblr, priv->rx_buffer_size); + gfar_write(®s->maxfrm, priv->rx_buffer_size); /* If the mtu is larger than the max size for standard * ethernet frames (ie, a jumbo frame), then set maccfg2 * to allow huge frames, and to check the length */ - tempval = gfar_read(&priv->regs->maccfg2); + tempval = gfar_read(®s->maccfg2); if (priv->rx_buffer_size > DEFAULT_RX_BUFFER_SIZE) tempval |= (MACCFG2_HUGEFRAME | MACCFG2_LENGTHCHECK); else tempval &= ~(MACCFG2_HUGEFRAME | MACCFG2_LENGTHCHECK); - gfar_write(&priv->regs->maccfg2, tempval); + gfar_write(®s->maccfg2, tempval); if ((oldsize != tempsize) && (dev->flags & IFF_UP)) startup_gfar(dev); @@ -1787,9 +1810,9 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue) return howmany; } -static void gfar_schedule_cleanup(struct net_device *dev) +static void gfar_schedule_cleanup(struct gfar_priv_grp *gfargrp) { - struct gfar_private *priv = netdev_priv(dev); + struct gfar_private *priv = gfargrp->priv; struct gfar_priv_tx_q *tx_queue = NULL; struct gfar_priv_rx_q *rx_queue = NULL; unsigned long flags; @@ -1800,14 +1823,14 @@ static void gfar_schedule_cleanup(struct net_device *dev) spin_lock(&rx_queue->rxlock); if (napi_schedule_prep(&rx_queue->napi)) { - gfar_write(&priv->regs->imask, IMASK_RTX_DISABLED); + gfar_write(&gfargrp->regs->imask, IMASK_RTX_DISABLED); __napi_schedule(&rx_queue->napi); } else { /* * Clear IEVENT, so interrupts aren't called again * because of the packets that have already arrived. */ - gfar_write(&priv->regs->ievent, IEVENT_RTX_MASK); + gfar_write(&gfargrp->regs->ievent, IEVENT_RTX_MASK); } spin_unlock(&rx_queue->rxlock); @@ -1815,9 +1838,9 @@ static void gfar_schedule_cleanup(struct net_device *dev) } /* Interrupt Handler for Transmit complete */ -static irqreturn_t gfar_transmit(int irq, void *dev_id) +static irqreturn_t gfar_transmit(int irq, void *grp_id) { - gfar_schedule_cleanup((struct net_device *)dev_id); + gfar_schedule_cleanup((struct gfar_priv_grp *)grp_id); return IRQ_HANDLED; } @@ -1897,9 +1920,9 @@ static inline void count_errors(unsigned short status, struct net_device *dev) } } -irqreturn_t gfar_receive(int irq, void *dev_id) +irqreturn_t gfar_receive(int irq, void *grp_id) { - gfar_schedule_cleanup((struct net_device *)dev_id); + gfar_schedule_cleanup((struct gfar_priv_grp *)grp_id); return IRQ_HANDLED; } @@ -2053,6 +2076,7 @@ static int gfar_poll(struct napi_struct *napi, int budget) struct gfar_priv_rx_q, napi); struct net_device *dev = rx_queue->dev; struct gfar_private *priv = netdev_priv(dev); + struct gfar __iomem *regs = priv->gfargrp.regs; struct gfar_priv_tx_q *tx_queue = NULL; int tx_cleaned = 0; int rx_cleaned = 0; @@ -2060,7 +2084,7 @@ static int gfar_poll(struct napi_struct *napi, int budget) /* Clear IEVENT, so interrupts aren't called again * because of the packets that have already arrived */ - gfar_write(&priv->regs->ievent, IEVENT_RTX_MASK); + gfar_write(®s->ievent, IEVENT_RTX_MASK); tx_queue = priv->tx_queue; /* If we fail to get the lock, don't bother with the TX BDs */ @@ -2078,19 +2102,19 @@ static int gfar_poll(struct napi_struct *napi, int budget) napi_complete(napi); /* Clear the halt bit in RSTAT */ - gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT); + gfar_write(®s->rstat, RSTAT_CLEAR_RHALT); - gfar_write(&priv->regs->imask, IMASK_DEFAULT); + gfar_write(®s->imask, IMASK_DEFAULT); /* If we are coalescing interrupts, update the timer */ /* Otherwise, clear it */ if (likely(rx_queue->rxcoalescing)) { - gfar_write(&priv->regs->rxic, 0); - gfar_write(&priv->regs->rxic, rx_queue->rxic); + gfar_write(®s->rxic, 0); + gfar_write(®s->rxic, rx_queue->rxic); } if (likely(tx_queue->txcoalescing)) { - gfar_write(&priv->regs->txic, 0); - gfar_write(&priv->regs->txic, tx_queue->txic); + gfar_write(®s->txic, 0); + gfar_write(®s->txic, tx_queue->txic); } } @@ -2109,41 +2133,40 @@ static void gfar_netpoll(struct net_device *dev) /* If the device has multiple interrupts, run tx/rx */ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { - disable_irq(priv->interruptTransmit); - disable_irq(priv->interruptReceive); - disable_irq(priv->interruptError); - gfar_interrupt(priv->interruptTransmit, dev); - enable_irq(priv->interruptError); - enable_irq(priv->interruptReceive); - enable_irq(priv->interruptTransmit); + disable_irq(priv->gfargrp.interruptTransmit); + disable_irq(priv->gfargrp.interruptReceive); + disable_irq(priv->gfargrp.interruptError); + gfar_interrupt(priv->gfargrp.interruptTransmit, &priv->gfargrp); + enable_irq(priv->gfargrp.interruptError); + enable_irq(priv->gfargrp.interruptReceive); + enable_irq(priv->gfargrp.interruptTransmit); } else { - disable_irq(priv->interruptTransmit); - gfar_interrupt(priv->interruptTransmit, dev); - enable_irq(priv->interruptTransmit); + disable_irq(priv->gfargrp.interruptTransmit); + gfar_interrupt(priv->gfargrp.interruptTransmit, &priv->gfargrp); + enable_irq(priv->gfargrp.interruptTransmit); } } #endif /* The interrupt handler for devices with one interrupt */ -static irqreturn_t gfar_interrupt(int irq, void *dev_id) +static irqreturn_t gfar_interrupt(int irq, void *grp_id) { - struct net_device *dev = dev_id; - struct gfar_private *priv = netdev_priv(dev); + struct gfar_priv_grp *gfargrp = grp_id; /* Save ievent for future reference */ - u32 events = gfar_read(&priv->regs->ievent); + u32 events = gfar_read(&gfargrp->regs->ievent); /* Check for reception */ if (events & IEVENT_RX_MASK) - gfar_receive(irq, dev_id); + gfar_receive(irq, grp_id); /* Check for transmit completion */ if (events & IEVENT_TX_MASK) - gfar_transmit(irq, dev_id); + gfar_transmit(irq, grp_id); /* Check for errors */ if (events & IEVENT_ERR_MASK) - gfar_error(irq, dev_id); + gfar_error(irq, grp_id); return IRQ_HANDLED; } @@ -2158,7 +2181,7 @@ static void adjust_link(struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); struct gfar_priv_tx_q *tx_queue = NULL; - struct gfar __iomem *regs = priv->regs; + struct gfar __iomem *regs = priv->gfargrp.regs; unsigned long flags; struct phy_device *phydev = priv->phydev; int new_state = 0; @@ -2241,7 +2264,7 @@ static void gfar_set_multi(struct net_device *dev) { struct dev_mc_list *mc_ptr; struct gfar_private *priv = netdev_priv(dev); - struct gfar __iomem *regs = priv->regs; + struct gfar __iomem *regs = priv->gfargrp.regs; u32 tempval; if (dev->flags & IFF_PROMISC) { @@ -2374,10 +2397,11 @@ static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr) static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr) { struct gfar_private *priv = netdev_priv(dev); + struct gfar __iomem *regs = priv->gfargrp.regs; int idx; char tmpbuf[MAC_ADDR_LEN]; u32 tempval; - u32 __iomem *macptr = &priv->regs->macstnaddr1; + u32 __iomem *macptr = ®s->macstnaddr1; macptr += num*2; @@ -2394,16 +2418,18 @@ static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr) } /* GFAR error interrupt handler */ -static irqreturn_t gfar_error(int irq, void *dev_id) +static irqreturn_t gfar_error(int irq, void *grp_id) { - struct net_device *dev = dev_id; - struct gfar_private *priv = netdev_priv(dev); + struct gfar_priv_grp *gfargrp = grp_id; + struct gfar __iomem *regs = gfargrp->regs; + struct gfar_private *priv= gfargrp->priv; + struct net_device *dev = priv->ndev; /* Save ievent for future reference */ - u32 events = gfar_read(&priv->regs->ievent); + u32 events = gfar_read(®s->ievent); /* Clear IEVENT */ - gfar_write(&priv->regs->ievent, events & IEVENT_ERR_MASK); + gfar_write(®s->ievent, events & IEVENT_ERR_MASK); /* Magic Packet is not an error. */ if ((priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) && @@ -2413,7 +2439,7 @@ static irqreturn_t gfar_error(int irq, void *dev_id) /* Hmm... */ if (netif_msg_rx_err(priv) || netif_msg_tx_err(priv)) printk(KERN_DEBUG "%s: error interrupt (ievent=0x%08x imask=0x%08x)\n", - dev->name, events, gfar_read(&priv->regs->imask)); + dev->name, events, gfar_read(®s->imask)); /* Update the error counters */ if (events & IEVENT_TXE) { @@ -2431,7 +2457,7 @@ static irqreturn_t gfar_error(int irq, void *dev_id) priv->extra_stats.tx_underrun++; /* Reactivate the Tx Queues */ - gfar_write(&priv->regs->tstat, TSTAT_CLEAR_THALT); + gfar_write(®s->tstat, TSTAT_CLEAR_THALT); } if (netif_msg_tx_err(priv)) printk(KERN_DEBUG "%s: Transmit Error\n", dev->name); @@ -2440,11 +2466,11 @@ static irqreturn_t gfar_error(int irq, void *dev_id) dev->stats.rx_errors++; priv->extra_stats.rx_bsy++; - gfar_receive(irq, dev_id); + gfar_receive(irq, grp_id); if (netif_msg_rx_err(priv)) printk(KERN_DEBUG "%s: busy error (rstat: %x)\n", - dev->name, gfar_read(&priv->regs->rstat)); + dev->name, gfar_read(®s->rstat)); } if (events & IEVENT_BABR) { dev->stats.rx_errors++; diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index a60f93f1ae07..79e8471584ea 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -770,6 +770,32 @@ struct gfar_priv_rx_q { unsigned long rxic; }; +/** + * struct gfar_priv_grp - per group structure + * @priv: back pointer to the priv structure + * @regs: the ioremapped register space for this group + * @grp_id: group id for this group + * @interruptTransmit: The TX interrupt number for this group + * @interruptReceive: The RX interrupt number for this group + * @interruptError: The ERROR interrupt number for this group + * @int_name_tx: tx interrupt name for this group + * @int_name_rx: rx interrupt name for this group + * @int_name_er: er interrupt name for this group + */ + +struct gfar_priv_grp { + spinlock_t grplock __attribute__ ((aligned (SMP_CACHE_BYTES))); + struct gfar_private *priv; + struct gfar __iomem *regs; + unsigned int interruptTransmit; + unsigned int interruptReceive; + unsigned int interruptError; + + char int_name_tx[GFAR_INT_NAME_MAX]; + char int_name_rx[GFAR_INT_NAME_MAX]; + char int_name_er[GFAR_INT_NAME_MAX]; +}; + /* Struct stolen almost completely (and shamelessly) from the FCC enet source * (Ok, that's not so true anymore, but there is a family resemblence) * The GFAR buffer descriptors track the ring buffers. The rx_bd_base @@ -785,6 +811,7 @@ struct gfar_private { struct net_device *ndev; struct of_device *ofdev; + struct gfar_priv_grp gfargrp; struct gfar_priv_tx_q *tx_queue; struct gfar_priv_rx_q *rx_queue; @@ -797,9 +824,6 @@ struct gfar_private { struct vlan_group *vlgrp; - /* Unprotected fields */ - /* Pointer to the GFAR memory mapped Registers */ - struct gfar __iomem *regs; /* Hash registers and their width */ u32 __iomem *hash_regs[16]; @@ -823,10 +847,6 @@ struct gfar_private { wol_en:1; /* Wake-on-LAN enabled */ unsigned short padding; - unsigned int interruptTransmit; - unsigned int interruptReceive; - unsigned int interruptError; - /* PHY stuff */ struct phy_device *phydev; struct mii_bus *mii_bus; @@ -838,10 +858,6 @@ struct gfar_private { struct work_struct reset_task; - char int_name_tx[GFAR_INT_NAME_MAX]; - char int_name_rx[GFAR_INT_NAME_MAX]; - char int_name_er[GFAR_INT_NAME_MAX]; - /* Network Statistics */ struct gfar_extra_stats extra_stats; }; diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c index 6d0d1714c2f2..c681b414767a 100644 --- a/drivers/net/gianfar_ethtool.c +++ b/drivers/net/gianfar_ethtool.c @@ -137,10 +137,11 @@ static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, { int i; struct gfar_private *priv = netdev_priv(dev); + struct gfar __iomem *regs = priv->gfargrp.regs; u64 *extra = (u64 *) & priv->extra_stats; if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { - u32 __iomem *rmon = (u32 __iomem *) & priv->regs->rmon; + u32 __iomem *rmon = (u32 __iomem *) ®s->rmon; struct gfar_stats *stats = (struct gfar_stats *) buf; for (i = 0; i < GFAR_RMON_LEN; i++) @@ -223,7 +224,7 @@ static void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, voi { int i; struct gfar_private *priv = netdev_priv(dev); - u32 __iomem *theregs = (u32 __iomem *) priv->regs; + u32 __iomem *theregs = (u32 __iomem *) priv->gfargrp.regs; u32 *buf = (u32 *) regbuf; for (i = 0; i < sizeof (struct gfar) / sizeof (u32); i++) @@ -349,6 +350,7 @@ static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) { struct gfar_private *priv = netdev_priv(dev); + struct gfar __iomem *regs = priv->gfargrp.regs; struct gfar_priv_tx_q *tx_queue = NULL; struct gfar_priv_rx_q *rx_queue = NULL; @@ -407,13 +409,13 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals tx_queue->txic = mk_ic_value(cvals->tx_max_coalesced_frames, gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs)); - gfar_write(&priv->regs->rxic, 0); + gfar_write(®s->rxic, 0); if (rx_queue->rxcoalescing) - gfar_write(&priv->regs->rxic, rx_queue->rxic); + gfar_write(®s->rxic, rx_queue->rxic); - gfar_write(&priv->regs->txic, 0); + gfar_write(®s->txic, 0); if (tx_queue->txcoalescing) - gfar_write(&priv->regs->txic, tx_queue->txic); + gfar_write(®s->txic, tx_queue->txic); return 0; } diff --git a/drivers/net/gianfar_sysfs.c b/drivers/net/gianfar_sysfs.c index 9c664f85705c..adea11ea4038 100644 --- a/drivers/net/gianfar_sysfs.c +++ b/drivers/net/gianfar_sysfs.c @@ -50,6 +50,7 @@ static ssize_t gfar_set_bd_stash(struct device *dev, const char *buf, size_t count) { struct gfar_private *priv = netdev_priv(to_net_dev(dev)); + struct gfar __iomem *regs = priv->gfargrp.regs; struct gfar_priv_rx_q *rx_queue = NULL; int new_setting = 0; u32 temp; @@ -74,14 +75,14 @@ static ssize_t gfar_set_bd_stash(struct device *dev, /* Set the new stashing value */ priv->bd_stash_en = new_setting; - temp = gfar_read(&priv->regs->attr); + temp = gfar_read(®s->attr); if (new_setting) temp |= ATTR_BDSTASH; else temp &= ~(ATTR_BDSTASH); - gfar_write(&priv->regs->attr, temp); + gfar_write(®s->attr, temp); spin_unlock_irqrestore(&rx_queue->rxlock, flags); @@ -103,6 +104,7 @@ static ssize_t gfar_set_rx_stash_size(struct device *dev, const char *buf, size_t count) { struct gfar_private *priv = netdev_priv(to_net_dev(dev)); + struct gfar __iomem *regs = priv->gfargrp.regs; struct gfar_priv_rx_q *rx_queue = NULL; unsigned int length = simple_strtoul(buf, NULL, 0); u32 temp; @@ -122,20 +124,20 @@ static ssize_t gfar_set_rx_stash_size(struct device *dev, priv->rx_stash_size = length; - temp = gfar_read(&priv->regs->attreli); + temp = gfar_read(®s->attreli); temp &= ~ATTRELI_EL_MASK; temp |= ATTRELI_EL(length); - gfar_write(&priv->regs->attreli, temp); + gfar_write(®s->attreli, temp); /* Turn stashing on/off as appropriate */ - temp = gfar_read(&priv->regs->attr); + temp = gfar_read(®s->attr); if (length) temp |= ATTR_BUFSTASH; else temp &= ~(ATTR_BUFSTASH); - gfar_write(&priv->regs->attr, temp); + gfar_write(®s->attr, temp); out: spin_unlock_irqrestore(&rx_queue->rxlock, flags); @@ -161,6 +163,7 @@ static ssize_t gfar_set_rx_stash_index(struct device *dev, const char *buf, size_t count) { struct gfar_private *priv = netdev_priv(to_net_dev(dev)); + struct gfar __iomem *regs = priv->gfargrp.regs; struct gfar_priv_rx_q *rx_queue = NULL; unsigned short index = simple_strtoul(buf, NULL, 0); u32 temp; @@ -180,10 +183,10 @@ static ssize_t gfar_set_rx_stash_index(struct device *dev, priv->rx_stash_index = index; - temp = gfar_read(&priv->regs->attreli); + temp = gfar_read(®s->attreli); temp &= ~ATTRELI_EI_MASK; temp |= ATTRELI_EI(index); - gfar_write(&priv->regs->attreli, flags); + gfar_write(®s->attreli, flags); out: spin_unlock_irqrestore(&rx_queue->rxlock, flags); @@ -208,6 +211,7 @@ static ssize_t gfar_set_fifo_threshold(struct device *dev, const char *buf, size_t count) { struct gfar_private *priv = netdev_priv(to_net_dev(dev)); + struct gfar __iomem *regs = priv->gfargrp.regs; struct gfar_priv_tx_q *tx_queue = NULL; unsigned int length = simple_strtoul(buf, NULL, 0); u32 temp; @@ -222,10 +226,10 @@ static ssize_t gfar_set_fifo_threshold(struct device *dev, priv->fifo_threshold = length; - temp = gfar_read(&priv->regs->fifo_tx_thr); + temp = gfar_read(®s->fifo_tx_thr); temp &= ~FIFO_TX_THR_MASK; temp |= length; - gfar_write(&priv->regs->fifo_tx_thr, temp); + gfar_write(®s->fifo_tx_thr, temp); spin_unlock_irqrestore(&tx_queue->txlock, flags); @@ -248,6 +252,7 @@ static ssize_t gfar_set_fifo_starve(struct device *dev, const char *buf, size_t count) { struct gfar_private *priv = netdev_priv(to_net_dev(dev)); + struct gfar __iomem *regs = priv->gfargrp.regs; struct gfar_priv_tx_q *tx_queue = NULL; unsigned int num = simple_strtoul(buf, NULL, 0); u32 temp; @@ -261,10 +266,10 @@ static ssize_t gfar_set_fifo_starve(struct device *dev, priv->fifo_starve = num; - temp = gfar_read(&priv->regs->fifo_tx_starve); + temp = gfar_read(®s->fifo_tx_starve); temp &= ~FIFO_TX_STARVE_MASK; temp |= num; - gfar_write(&priv->regs->fifo_tx_starve, temp); + gfar_write(®s->fifo_tx_starve, temp); spin_unlock_irqrestore(&tx_queue->txlock, flags); @@ -288,6 +293,7 @@ static ssize_t gfar_set_fifo_starve_off(struct device *dev, const char *buf, size_t count) { struct gfar_private *priv = netdev_priv(to_net_dev(dev)); + struct gfar __iomem *regs = priv->gfargrp.regs; struct gfar_priv_tx_q *tx_queue = NULL; unsigned int num = simple_strtoul(buf, NULL, 0); u32 temp; @@ -301,10 +307,10 @@ static ssize_t gfar_set_fifo_starve_off(struct device *dev, priv->fifo_starve_off = num; - temp = gfar_read(&priv->regs->fifo_tx_starve_shutoff); + temp = gfar_read(®s->fifo_tx_starve_shutoff); temp &= ~FIFO_TX_STARVE_OFF_MASK; temp |= num; - gfar_write(&priv->regs->fifo_tx_starve_shutoff, temp); + gfar_write(®s->fifo_tx_starve_shutoff, temp); spin_unlock_irqrestore(&tx_queue->txlock, flags); -- GitLab