Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 3020

kernel-2.6.18-238.el5.src.rpm

From: Chad Dupuis <cdupuis@redhat.com>
Date: Fri, 6 Aug 2010 14:22:27 -0400
Subject: [net] qlge: fix pktgen issue reported by Cisco
Message-id: <20100806141914.2774.87405.sendpatchset@localhost.localdomain>
Patchwork-id: 27444
O-Subject: [RHEL 5.6 PATCH 2/10] qlge: Fixed pktgen, issue reported by Cisco.
Bugzilla: 567402

Bugzilla
========

567402

Upstream Status
===============

RHEL 5 specific

Description
===========

>From 6418d44cb9b04f03bc2039c6eac5d523d2449b0b Mon Sep 17 00:00:00 2001
From: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
Date: Wed, 4 Aug 2010 16:28:55 -0700
Subject: [PATCH 2/8] 	qlge: Fixed pktgen, issue reported by Cisco.

Signed-off-by: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>

diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h
index d1221b0..bf215a7 100644
--- a/drivers/net/qlge/qlge.h
+++ b/drivers/net/qlge/qlge.h
@@ -1310,7 +1310,6 @@ struct tx_ring {
 	struct tx_ring_desc *q;	/* descriptor list for the queue */
 	spinlock_t lock;
 	atomic_t tx_count;	/* counts down for every outstanding IO */
-	atomic_t queue_stopped;	/* Turns queue off when full. */
 	struct work_struct tx_work;
 	struct ql_adapter *qdev;
 	struct timer_list txq_clean_timer;
@@ -2030,6 +2029,8 @@ struct ql_adapter {
 	uint32_t *config_space;
 	/* Saving mac addr */
 	char current_mac_addr[6];
+	spinlock_t tx_lock;
+	u32 queue_stopped;	/* Bitfield of queues that are full. */
 };
 
 /*
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
index f66f617..96483b0 100644
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/qlge/qlge_main.c
@@ -1920,17 +1920,6 @@ static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring)
 		return count;
 
 	ql_write_cq_idx(rx_ring);
-	if (netif_queue_stopped(qdev->ndev) && net_rsp != NULL) {
-		struct tx_ring *tx_ring = &qdev->tx_ring[net_rsp->txq_idx];
-		if (atomic_read(&tx_ring->queue_stopped) &&
-			(atomic_read(&tx_ring->tx_count) >
-					(tx_ring->wq_len / 4)))
-			/*
-			 * The queue got stopped because the tx_ring was full.
-			 * Wake it up, because it's now at least 25% empty.
-			 */
-			netif_wake_queue(qdev->ndev);
-	}
 	rx_ring->bytes += bytes;
 	rx_ring->packets += (unsigned long) count;
 	return count;
@@ -1947,6 +1936,17 @@ static void ql_txq_clean_timer(unsigned long data)
 	ql_clean_outbound_rx_ring(rx_ring);
 
 	spin_unlock(&tx_ring->lock);
+	if (netif_queue_stopped(qdev->ndev)) {
+		spin_lock(&qdev->tx_lock);
+		if (qdev->queue_stopped & (1 << tx_ring->wq_id)) {
+			if (atomic_read(&tx_ring->tx_count) > 64) {
+				qdev->queue_stopped &= ~(1 << tx_ring->wq_id);
+				if (!qdev->queue_stopped)
+					netif_wake_queue(qdev->ndev);
+			}
+		}
+		spin_unlock(&qdev->tx_lock);
+	}
 exit:
 	mod_timer(&tx_ring->txq_clean_timer, jiffies + TXQ_CLEAN_TIME);
 
@@ -2279,11 +2279,16 @@ int qlge_send(struct sk_buff *skb, struct net_device *ndev)
 		ql_clean_outbound_rx_ring(&qdev->rx_ring[tx_ring->cq_id]);
 	if (unlikely(atomic_read(&tx_ring->tx_count) < 2)) {
 		spin_unlock(&tx_ring->lock);
+		del_timer_sync(&tx_ring->txq_clean_timer);
 		QPRINTK_DBG(qdev, TX_QUEUED, INFO,
-			"shutting down tx queue %d du to lack of resources.\n",
+			"shutting down tx queue %d due to lack of resources.\n",
 			tx_ring_idx);
-		netif_stop_queue(ndev);
-		atomic_inc(&tx_ring->queue_stopped);
+		spin_lock(&qdev->tx_lock);
+		if (!qdev->queue_stopped)
+			netif_stop_queue(ndev);
+		qdev->queue_stopped |= (1 << tx_ring->wq_id);
+		spin_unlock(&qdev->tx_lock);
+		mod_timer(&tx_ring->txq_clean_timer, jiffies);
 		return NETDEV_TX_BUSY;
 	}
 	tx_ring_desc = &tx_ring->q[tx_ring->prod_idx];
@@ -2410,7 +2415,6 @@ static void ql_init_tx_ring(struct ql_adapter *qdev, struct tx_ring *tx_ring)
 		tx_ring_desc++;
 	}
 	atomic_set(&tx_ring->tx_count, tx_ring->wq_len);
-	atomic_set(&tx_ring->queue_stopped, 0);
 }
 
 static void ql_free_tx_resources(struct ql_adapter *qdev,
@@ -3668,6 +3672,7 @@ static int ql_adapter_up(struct ql_adapter *qdev)
 	set_bit(QL_ADAPTER_UP, &qdev->flags);
 	ql_enable_napi(qdev);
 	ql_alloc_rx_buffers(qdev);
+	qdev->queue_stopped = 0;
 	ql_enable_all_completion_interrupts(qdev);
 	
 	/* trigger link work function*/
@@ -4306,6 +4311,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev,
 	qdev->msg_enable = netif_msg_init(debug, default_msg);
 	spin_lock_init(&qdev->hw_lock);
 	spin_lock_init(&qdev->stats_lock);
+	spin_lock_init(&qdev->tx_lock);
 
 	qdev->mpi_coredump = vmalloc(sizeof(struct ql_mpi_coredump));
 	if ((qdev->mpi_coredump == NULL) && qlge_mpi_coredump) {