lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:   Tue, 22 Sep 2020 00:31:13 +0200
From:   Hauke Mehrtens <hauke@...ke-m.de>
To:     davem@...emloft.net
Cc:     kuba@...nel.org, netdev@...r.kernel.org,
        martin.blumenstingl@...glemail.com,
        Hauke Mehrtens <hauke@...ke-m.de>
Subject: [PATCH] net: lantiq: Add locking for TX DMA channel

The TX DMA channel data is accessed by the xrx200_start_xmit() and the
xrx200_tx_housekeeping() function from different threads. Make sure the
accesses are synchronized by using locking around the accesses.

Signed-off-by: Hauke Mehrtens <hauke@...ke-m.de>
---
 drivers/net/ethernet/lantiq_xrx200.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/lantiq_xrx200.c b/drivers/net/ethernet/lantiq_xrx200.c
index 635ff3a5dcfb..f4de09d1f582 100644
--- a/drivers/net/ethernet/lantiq_xrx200.c
+++ b/drivers/net/ethernet/lantiq_xrx200.c
@@ -59,6 +59,7 @@ struct xrx200_chan {
 	struct ltq_dma_channel dma;
 	struct sk_buff *skb[LTQ_DESC_NUM];
 
+	spinlock_t lock;
 	struct xrx200_priv *priv;
 };
 
@@ -242,9 +243,11 @@ static int xrx200_tx_housekeeping(struct napi_struct *napi, int budget)
 	struct xrx200_chan *ch = container_of(napi,
 				struct xrx200_chan, napi);
 	struct net_device *net_dev = ch->priv->net_dev;
+	unsigned long flags;
 	int pkts = 0;
 	int bytes = 0;
 
+	spin_lock_irqsave(&ch->lock, flags);
 	while (pkts < budget) {
 		struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->tx_free];
 
@@ -268,6 +271,8 @@ static int xrx200_tx_housekeeping(struct napi_struct *napi, int budget)
 	net_dev->stats.tx_bytes += bytes;
 	netdev_completed_queue(ch->priv->net_dev, pkts, bytes);
 
+	spin_unlock_irqrestore(&ch->lock, flags);
+
 	if (netif_queue_stopped(net_dev))
 		netif_wake_queue(net_dev);
 
@@ -284,7 +289,8 @@ static netdev_tx_t xrx200_start_xmit(struct sk_buff *skb,
 {
 	struct xrx200_priv *priv = netdev_priv(net_dev);
 	struct xrx200_chan *ch = &priv->chan_tx;
-	struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
+	struct ltq_dma_desc *desc;
+	unsigned long flags;
 	u32 byte_offset;
 	dma_addr_t mapping;
 	int len;
@@ -297,8 +303,11 @@ static netdev_tx_t xrx200_start_xmit(struct sk_buff *skb,
 
 	len = skb->len;
 
+	spin_lock_irqsave(&ch->lock, flags);
+	desc = &ch->dma.desc_base[ch->dma.desc];
 	if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) || ch->skb[ch->dma.desc]) {
 		netdev_err(net_dev, "tx ring full\n");
+		spin_unlock_irqrestore(&ch->lock, flags);
 		netif_stop_queue(net_dev);
 		return NETDEV_TX_BUSY;
 	}
@@ -306,8 +315,10 @@ static netdev_tx_t xrx200_start_xmit(struct sk_buff *skb,
 	ch->skb[ch->dma.desc] = skb;
 
 	mapping = dma_map_single(priv->dev, skb->data, len, DMA_TO_DEVICE);
-	if (unlikely(dma_mapping_error(priv->dev, mapping)))
+	if (unlikely(dma_mapping_error(priv->dev, mapping))) {
+		spin_unlock_irqrestore(&ch->lock, flags);
 		goto err_drop;
+	}
 
 	/* dma needs to start on a 16 byte aligned address */
 	byte_offset = mapping % 16;
@@ -324,6 +335,8 @@ static netdev_tx_t xrx200_start_xmit(struct sk_buff *skb,
 
 	netdev_sent_queue(net_dev, len);
 
+	spin_unlock_irqrestore(&ch->lock, flags);
+
 	return NETDEV_TX_OK;
 
 err_drop:
@@ -367,6 +380,7 @@ static int xrx200_dma_init(struct xrx200_priv *priv)
 	ch_rx->dma.nr = XRX200_DMA_RX;
 	ch_rx->dma.dev = priv->dev;
 	ch_rx->priv = priv;
+	spin_lock_init(&ch_rx->lock);
 
 	ltq_dma_alloc_rx(&ch_rx->dma);
 	for (ch_rx->dma.desc = 0; ch_rx->dma.desc < LTQ_DESC_NUM;
@@ -387,6 +401,7 @@ static int xrx200_dma_init(struct xrx200_priv *priv)
 	ch_tx->dma.nr = XRX200_DMA_TX;
 	ch_tx->dma.dev = priv->dev;
 	ch_tx->priv = priv;
+	spin_lock_init(&ch_tx->lock);
 
 	ltq_dma_alloc_tx(&ch_tx->dma);
 	ret = devm_request_irq(priv->dev, ch_tx->dma.irq, xrx200_dma_irq, 0,
-- 
2.20.1

Powered by blists - more mailing lists