From 888d0584afb884b3c402c5d01aa8c0006c25bc52 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 16 Feb 2020 08:03:32 +1100 Subject: [PATCH 1/7] net/sonic: Remove obsolete comment The comment is meaningless since mark_bh() was removed a long time ago. Tested-by: Stan Johnson Signed-off-by: Finn Thain Signed-off-by: David S. Miller --- drivers/net/ethernet/natsemi/sonic.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/net/ethernet/natsemi/sonic.c b/drivers/net/ethernet/natsemi/sonic.c index 31be3ba66877..e01273654f81 100644 --- a/drivers/net/ethernet/natsemi/sonic.c +++ b/drivers/net/ethernet/natsemi/sonic.c @@ -594,11 +594,6 @@ static void sonic_rx(struct net_device *dev) if (rbe) SONIC_WRITE(SONIC_ISR, SONIC_INT_RBE); - /* - * If any worth-while packets have been received, netif_rx() - * has done a mark_bh(NET_BH) for us and will work on them - * when we get to the bottom-half routine. - */ } From 5d58c21c1030d8aaebeafd068304d12bc9c6bff7 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 16 Feb 2020 08:03:32 +1100 Subject: [PATCH 2/7] net/sonic: Refactor duplicated code No functional change. Tested-by: Stan Johnson Signed-off-by: Finn Thain Signed-off-by: David S. Miller --- drivers/net/ethernet/natsemi/jazzsonic.c | 31 ++---------------- drivers/net/ethernet/natsemi/macsonic.c | 29 ++--------------- drivers/net/ethernet/natsemi/sonic.c | 36 +++++++++++++++++++++ drivers/net/ethernet/natsemi/sonic.h | 1 + drivers/net/ethernet/natsemi/xtsonic.c | 40 ++---------------------- 5 files changed, 44 insertions(+), 93 deletions(-) diff --git a/drivers/net/ethernet/natsemi/jazzsonic.c b/drivers/net/ethernet/natsemi/jazzsonic.c index 51fa82b429a3..bfa0c0d39600 100644 --- a/drivers/net/ethernet/natsemi/jazzsonic.c +++ b/drivers/net/ethernet/natsemi/jazzsonic.c @@ -147,39 +147,12 @@ static int sonic_probe1(struct net_device *dev) dev->dev_addr[i*2+1] = val >> 8; } - err = -ENOMEM; - - /* Initialize the device structure. */ - lp->dma_bitmode = SONIC_BITMODE32; - /* Allocate the entire chunk of memory for the descriptors. - Note that this cannot cross a 64K boundary. */ - lp->descriptors = dma_alloc_coherent(lp->device, - SIZEOF_SONIC_DESC * - SONIC_BUS_SCALE(lp->dma_bitmode), - &lp->descriptors_laddr, - GFP_KERNEL); - if (lp->descriptors == NULL) + err = sonic_alloc_descriptors(dev); + if (err) goto out; - /* Now set up the pointers to point to the appropriate places */ - lp->cda = lp->descriptors; - lp->tda = lp->cda + (SIZEOF_SONIC_CDA - * SONIC_BUS_SCALE(lp->dma_bitmode)); - lp->rda = lp->tda + (SIZEOF_SONIC_TD * SONIC_NUM_TDS - * SONIC_BUS_SCALE(lp->dma_bitmode)); - lp->rra = lp->rda + (SIZEOF_SONIC_RD * SONIC_NUM_RDS - * SONIC_BUS_SCALE(lp->dma_bitmode)); - - lp->cda_laddr = lp->descriptors_laddr; - lp->tda_laddr = lp->cda_laddr + (SIZEOF_SONIC_CDA - * SONIC_BUS_SCALE(lp->dma_bitmode)); - lp->rda_laddr = lp->tda_laddr + (SIZEOF_SONIC_TD * SONIC_NUM_TDS - * SONIC_BUS_SCALE(lp->dma_bitmode)); - lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS - * SONIC_BUS_SCALE(lp->dma_bitmode)); - dev->netdev_ops = &sonic_netdev_ops; dev->watchdog_timeo = TX_TIMEOUT; diff --git a/drivers/net/ethernet/natsemi/macsonic.c b/drivers/net/ethernet/natsemi/macsonic.c index 0937fc2a928e..0f4d0c25d626 100644 --- a/drivers/net/ethernet/natsemi/macsonic.c +++ b/drivers/net/ethernet/natsemi/macsonic.c @@ -186,33 +186,10 @@ static const struct net_device_ops macsonic_netdev_ops = { static int macsonic_init(struct net_device *dev) { struct sonic_local* lp = netdev_priv(dev); + int err = sonic_alloc_descriptors(dev); - /* Allocate the entire chunk of memory for the descriptors. - Note that this cannot cross a 64K boundary. */ - lp->descriptors = dma_alloc_coherent(lp->device, - SIZEOF_SONIC_DESC * - SONIC_BUS_SCALE(lp->dma_bitmode), - &lp->descriptors_laddr, - GFP_KERNEL); - if (lp->descriptors == NULL) - return -ENOMEM; - - /* Now set up the pointers to point to the appropriate places */ - lp->cda = lp->descriptors; - lp->tda = lp->cda + (SIZEOF_SONIC_CDA - * SONIC_BUS_SCALE(lp->dma_bitmode)); - lp->rda = lp->tda + (SIZEOF_SONIC_TD * SONIC_NUM_TDS - * SONIC_BUS_SCALE(lp->dma_bitmode)); - lp->rra = lp->rda + (SIZEOF_SONIC_RD * SONIC_NUM_RDS - * SONIC_BUS_SCALE(lp->dma_bitmode)); - - lp->cda_laddr = lp->descriptors_laddr; - lp->tda_laddr = lp->cda_laddr + (SIZEOF_SONIC_CDA - * SONIC_BUS_SCALE(lp->dma_bitmode)); - lp->rda_laddr = lp->tda_laddr + (SIZEOF_SONIC_TD * SONIC_NUM_TDS - * SONIC_BUS_SCALE(lp->dma_bitmode)); - lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS - * SONIC_BUS_SCALE(lp->dma_bitmode)); + if (err) + return err; dev->netdev_ops = &macsonic_netdev_ops; dev->watchdog_timeo = TX_TIMEOUT; diff --git a/drivers/net/ethernet/natsemi/sonic.c b/drivers/net/ethernet/natsemi/sonic.c index e01273654f81..c066510b348e 100644 --- a/drivers/net/ethernet/natsemi/sonic.c +++ b/drivers/net/ethernet/natsemi/sonic.c @@ -50,6 +50,42 @@ static void sonic_msg_init(struct net_device *dev) netif_dbg(lp, drv, dev, "%s", version); } +static int sonic_alloc_descriptors(struct net_device *dev) +{ + struct sonic_local *lp = netdev_priv(dev); + + /* Allocate a chunk of memory for the descriptors. Note that this + * must not cross a 64K boundary. It is smaller than one page which + * means that page alignment is a sufficient condition. + */ + lp->descriptors = + dma_alloc_coherent(lp->device, + SIZEOF_SONIC_DESC * + SONIC_BUS_SCALE(lp->dma_bitmode), + &lp->descriptors_laddr, GFP_KERNEL); + + if (!lp->descriptors) + return -ENOMEM; + + lp->cda = lp->descriptors; + lp->tda = lp->cda + SIZEOF_SONIC_CDA * + SONIC_BUS_SCALE(lp->dma_bitmode); + lp->rda = lp->tda + SIZEOF_SONIC_TD * SONIC_NUM_TDS * + SONIC_BUS_SCALE(lp->dma_bitmode); + lp->rra = lp->rda + SIZEOF_SONIC_RD * SONIC_NUM_RDS * + SONIC_BUS_SCALE(lp->dma_bitmode); + + lp->cda_laddr = lp->descriptors_laddr; + lp->tda_laddr = lp->cda_laddr + SIZEOF_SONIC_CDA * + SONIC_BUS_SCALE(lp->dma_bitmode); + lp->rda_laddr = lp->tda_laddr + SIZEOF_SONIC_TD * SONIC_NUM_TDS * + SONIC_BUS_SCALE(lp->dma_bitmode); + lp->rra_laddr = lp->rda_laddr + SIZEOF_SONIC_RD * SONIC_NUM_RDS * + SONIC_BUS_SCALE(lp->dma_bitmode); + + return 0; +} + /* * Open/initialize the SONIC controller. * diff --git a/drivers/net/ethernet/natsemi/sonic.h b/drivers/net/ethernet/natsemi/sonic.h index e0e4cba6f6f6..053f12f5cf4a 100644 --- a/drivers/net/ethernet/natsemi/sonic.h +++ b/drivers/net/ethernet/natsemi/sonic.h @@ -342,6 +342,7 @@ static void sonic_multicast_list(struct net_device *dev); static int sonic_init(struct net_device *dev); static void sonic_tx_timeout(struct net_device *dev, unsigned int txqueue); static void sonic_msg_init(struct net_device *dev); +static int sonic_alloc_descriptors(struct net_device *dev); /* Internal inlines for reading/writing DMA buffers. Note that bus size and endianness matter here, whereas they don't for registers, diff --git a/drivers/net/ethernet/natsemi/xtsonic.c b/drivers/net/ethernet/natsemi/xtsonic.c index e1b886e87a76..dda9ec7d9cee 100644 --- a/drivers/net/ethernet/natsemi/xtsonic.c +++ b/drivers/net/ethernet/natsemi/xtsonic.c @@ -167,47 +167,11 @@ static int __init sonic_probe1(struct net_device *dev) dev->dev_addr[i*2+1] = val >> 8; } - /* Initialize the device structure. */ - lp->dma_bitmode = SONIC_BITMODE32; - /* - * Allocate local private descriptor areas in uncached space. - * The entire structure must be located within the same 64kb segment. - * A simple way to ensure this is to allocate twice the - * size of the structure -- given that the structure is - * much less than 64 kB, at least one of the halves of - * the allocated area will be contained entirely in 64 kB. - * We also allocate extra space for a pointer to allow freeing - * this structure later on (in xtsonic_cleanup_module()). - */ - lp->descriptors = dma_alloc_coherent(lp->device, - SIZEOF_SONIC_DESC * - SONIC_BUS_SCALE(lp->dma_bitmode), - &lp->descriptors_laddr, - GFP_KERNEL); - if (lp->descriptors == NULL) { - err = -ENOMEM; + err = sonic_alloc_descriptors(dev); + if (err) goto out; - } - - lp->cda = lp->descriptors; - lp->tda = lp->cda + (SIZEOF_SONIC_CDA - * SONIC_BUS_SCALE(lp->dma_bitmode)); - lp->rda = lp->tda + (SIZEOF_SONIC_TD * SONIC_NUM_TDS - * SONIC_BUS_SCALE(lp->dma_bitmode)); - lp->rra = lp->rda + (SIZEOF_SONIC_RD * SONIC_NUM_RDS - * SONIC_BUS_SCALE(lp->dma_bitmode)); - - /* get the virtual dma address */ - - lp->cda_laddr = lp->descriptors_laddr; - lp->tda_laddr = lp->cda_laddr + (SIZEOF_SONIC_CDA - * SONIC_BUS_SCALE(lp->dma_bitmode)); - lp->rda_laddr = lp->tda_laddr + (SIZEOF_SONIC_TD * SONIC_NUM_TDS - * SONIC_BUS_SCALE(lp->dma_bitmode)); - lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS - * SONIC_BUS_SCALE(lp->dma_bitmode)); dev->netdev_ops = &xtsonic_netdev_ops; dev->watchdog_timeo = TX_TIMEOUT; From 29660d50a9e3a88c2c930994ac59ba5e4e74f344 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 16 Feb 2020 08:03:32 +1100 Subject: [PATCH 3/7] net/sonic: Remove redundant next_tx variable The eol_tx variable is the one that matters to the tx algorithm because packets are always placed at the end of the list. The next_tx variable just confuses things so remove it. Tested-by: Stan Johnson Signed-off-by: Finn Thain Signed-off-by: David S. Miller --- drivers/net/ethernet/natsemi/sonic.c | 8 ++++---- drivers/net/ethernet/natsemi/sonic.h | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/natsemi/sonic.c b/drivers/net/ethernet/natsemi/sonic.c index c066510b348e..9ecdd67e1410 100644 --- a/drivers/net/ethernet/natsemi/sonic.c +++ b/drivers/net/ethernet/natsemi/sonic.c @@ -300,7 +300,7 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev) spin_lock_irqsave(&lp->lock, flags); - entry = lp->next_tx; + entry = (lp->eol_tx + 1) & SONIC_TDS_MASK; sonic_tda_put(dev, entry, SONIC_TD_STATUS, 0); /* clear status */ sonic_tda_put(dev, entry, SONIC_TD_FRAG_COUNT, 1); /* single fragment */ @@ -321,8 +321,8 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev) sonic_tda_get(dev, lp->eol_tx, SONIC_TD_LINK) & ~SONIC_EOL); lp->eol_tx = entry; - lp->next_tx = (entry + 1) & SONIC_TDS_MASK; - if (lp->tx_skb[lp->next_tx] != NULL) { + entry = (entry + 1) & SONIC_TDS_MASK; + if (lp->tx_skb[entry]) { /* The ring is full, the ISR has yet to process the next TD. */ netif_dbg(lp, tx_queued, dev, "%s: stopping queue\n", __func__); netif_stop_queue(dev); @@ -811,7 +811,7 @@ static int sonic_init(struct net_device *dev) SONIC_WRITE(SONIC_UTDA, lp->tda_laddr >> 16); SONIC_WRITE(SONIC_CTDA, lp->tda_laddr & 0xffff); - lp->cur_tx = lp->next_tx = 0; + lp->cur_tx = 0; lp->eol_tx = SONIC_NUM_TDS - 1; /* diff --git a/drivers/net/ethernet/natsemi/sonic.h b/drivers/net/ethernet/natsemi/sonic.h index 053f12f5cf4a..3cbb62c860c8 100644 --- a/drivers/net/ethernet/natsemi/sonic.h +++ b/drivers/net/ethernet/natsemi/sonic.h @@ -321,7 +321,6 @@ struct sonic_local { unsigned int cur_tx; /* first unacked transmit packet */ unsigned int eol_rx; unsigned int eol_tx; /* last unacked transmit packet */ - unsigned int next_tx; /* next free TD */ int msg_enable; struct device *device; /* generic device */ struct net_device_stats stats; From d35bf9bc7d72a5e3055c808e5d5530a81a0c9a38 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 16 Feb 2020 08:03:32 +1100 Subject: [PATCH 4/7] net/sonic: Remove redundant netif_start_queue() call The transmit queue must be running already otherwise sonic_send_packet() would not have been called. If the queue was stopped by the interrupt handler, the interrupt handler will restart it again. Tested-by: Stan Johnson Signed-off-by: Finn Thain Signed-off-by: David S. Miller --- drivers/net/ethernet/natsemi/sonic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/natsemi/sonic.c b/drivers/net/ethernet/natsemi/sonic.c index 9ecdd67e1410..1d6de6706875 100644 --- a/drivers/net/ethernet/natsemi/sonic.c +++ b/drivers/net/ethernet/natsemi/sonic.c @@ -327,7 +327,7 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev) netif_dbg(lp, tx_queued, dev, "%s: stopping queue\n", __func__); netif_stop_queue(dev); /* after this packet, wait for ISR to free up some TDAs */ - } else netif_start_queue(dev); + } netif_dbg(lp, tx_queued, dev, "%s: issuing Tx command\n", __func__); From 13cfff1a902c647fc9d5ef9c090106097d7b7f79 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 16 Feb 2020 08:03:32 +1100 Subject: [PATCH 5/7] net/sonic: Remove explicit memory barriers The explicit memory barriers are redundant now that proper locking and MMIO accessors have been employed. Tested-by: Stan Johnson Signed-off-by: Finn Thain Signed-off-by: David S. Miller --- drivers/net/ethernet/natsemi/sonic.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/ethernet/natsemi/sonic.c b/drivers/net/ethernet/natsemi/sonic.c index 1d6de6706875..508c6a80fc6e 100644 --- a/drivers/net/ethernet/natsemi/sonic.c +++ b/drivers/net/ethernet/natsemi/sonic.c @@ -311,12 +311,10 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev) sonic_tda_put(dev, entry, SONIC_TD_LINK, sonic_tda_get(dev, entry, SONIC_TD_LINK) | SONIC_EOL); - wmb(); lp->tx_len[entry] = length; lp->tx_laddr[entry] = laddr; lp->tx_skb[entry] = skb; - wmb(); sonic_tda_put(dev, lp->eol_tx, SONIC_TD_LINK, sonic_tda_get(dev, lp->eol_tx, SONIC_TD_LINK) & ~SONIC_EOL); lp->eol_tx = entry; From 8fe676b3db7a94ae14e274e24395e96ab3f09e8b Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 16 Feb 2020 08:03:32 +1100 Subject: [PATCH 6/7] net/sonic: Start packet transmission immediately Give the transmit command as soon as the transmit descriptor is ready. Tested-by: Stan Johnson Signed-off-by: Finn Thain Signed-off-by: David S. Miller --- drivers/net/ethernet/natsemi/sonic.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/natsemi/sonic.c b/drivers/net/ethernet/natsemi/sonic.c index 508c6a80fc6e..dd3605aa5f23 100644 --- a/drivers/net/ethernet/natsemi/sonic.c +++ b/drivers/net/ethernet/natsemi/sonic.c @@ -311,12 +311,17 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev) sonic_tda_put(dev, entry, SONIC_TD_LINK, sonic_tda_get(dev, entry, SONIC_TD_LINK) | SONIC_EOL); + sonic_tda_put(dev, lp->eol_tx, SONIC_TD_LINK, ~SONIC_EOL & + sonic_tda_get(dev, lp->eol_tx, SONIC_TD_LINK)); + + netif_dbg(lp, tx_queued, dev, "%s: issuing Tx command\n", __func__); + + SONIC_WRITE(SONIC_CMD, SONIC_CR_TXP); + lp->tx_len[entry] = length; lp->tx_laddr[entry] = laddr; lp->tx_skb[entry] = skb; - sonic_tda_put(dev, lp->eol_tx, SONIC_TD_LINK, - sonic_tda_get(dev, lp->eol_tx, SONIC_TD_LINK) & ~SONIC_EOL); lp->eol_tx = entry; entry = (entry + 1) & SONIC_TDS_MASK; @@ -327,10 +332,6 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev) /* after this packet, wait for ISR to free up some TDAs */ } - netif_dbg(lp, tx_queued, dev, "%s: issuing Tx command\n", __func__); - - SONIC_WRITE(SONIC_CMD, SONIC_CR_TXP); - spin_unlock_irqrestore(&lp->lock, flags); return NETDEV_TX_OK; From d5f3889aca9f5516d0e86c06e040775c2a26c4fd Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 16 Feb 2020 08:03:32 +1100 Subject: [PATCH 7/7] net/macsonic: Remove interrupt handler wrapper On m68k, local irqs remain enabled while interrupt handlers execute. Therefore the macsonic driver has had to disable interrupts to avoid re-entering sonic_interrupt(). As of commit 865ad2f2201d ("net/sonic: Add mutual exclusion for accessing shared state"), sonic_interrupt() became re-entrant, and its wrapper became redundant. Tested-by: Stan Johnson Signed-off-by: Finn Thain Signed-off-by: David S. Miller --- drivers/net/ethernet/natsemi/macsonic.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/natsemi/macsonic.c b/drivers/net/ethernet/natsemi/macsonic.c index 0f4d0c25d626..1b5559aacb38 100644 --- a/drivers/net/ethernet/natsemi/macsonic.c +++ b/drivers/net/ethernet/natsemi/macsonic.c @@ -114,17 +114,6 @@ static inline void bit_reverse_addr(unsigned char addr[6]) addr[i] = bitrev8(addr[i]); } -static irqreturn_t macsonic_interrupt(int irq, void *dev_id) -{ - irqreturn_t result; - unsigned long flags; - - local_irq_save(flags); - result = sonic_interrupt(irq, dev_id); - local_irq_restore(flags); - return result; -} - static int macsonic_open(struct net_device* dev) { int retval; @@ -135,12 +124,12 @@ static int macsonic_open(struct net_device* dev) dev->name, dev->irq); goto err; } - /* Under the A/UX interrupt scheme, the onboard SONIC interrupt comes - * in at priority level 3. However, we sometimes get the level 2 inter- - * rupt as well, which must prevent re-entrance of the sonic handler. + /* Under the A/UX interrupt scheme, the onboard SONIC interrupt gets + * moved from level 2 to level 3. Unfortunately we still get some + * level 2 interrupts so register the handler for both. */ if (dev->irq == IRQ_AUTO_3) { - retval = request_irq(IRQ_NUBUS_9, macsonic_interrupt, 0, + retval = request_irq(IRQ_NUBUS_9, sonic_interrupt, 0, "sonic", dev); if (retval) { printk(KERN_ERR "%s: unable to get IRQ %d.\n",