netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: dhananjay@netxen.com
To: netdev@vger.kernel.org
Cc: jeff@garzik.org
Subject: [patch 5/7] netxen: fix race in interrupt / napi
Date: Wed, 26 Dec 2007 10:23:57 -0800	[thread overview]
Message-ID: <20071226182927.778015972@netxen.com> (raw)
In-Reply-To: 20071226182352.704678179@netxen.com

[-- Attachment #1: poll.patch --]
[-- Type: text/plain, Size: 8709 bytes --]

This patch simplifies netxen ISR and poll() routine. Interrupts are not
unmasked in interrupt routine based on a racy has_work() checks, but
left to the napi poll function to enable them. 

This also fixes crash in netif_rx_action(), when work_done == budget.

Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>

Index: upstream/drivers/net/netxen/netxen_nic_main.c
===================================================================
--- upstream.orig/drivers/net/netxen/netxen_nic_main.c
+++ upstream/drivers/net/netxen/netxen_nic_main.c
@@ -63,7 +63,6 @@ static int netxen_nic_xmit_frame(struct 
 static void netxen_tx_timeout(struct net_device *netdev);
 static void netxen_tx_timeout_task(struct work_struct *work);
 static void netxen_watchdog(unsigned long);
-static int netxen_handle_int(struct netxen_adapter *, struct net_device *);
 static int netxen_nic_poll(struct napi_struct *napi, int budget);
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void netxen_nic_poll_controller(struct net_device *netdev);
@@ -1218,40 +1217,6 @@ static void netxen_tx_timeout_task(struc
 	netif_wake_queue(adapter->netdev);
 }
 
-static int
-netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev)
-{
-	u32 ret = 0;
-
-	DPRINTK(INFO, "Entered handle ISR\n");
-	adapter->stats.ints++;
-
-	netxen_nic_disable_int(adapter);
-
-	if (netxen_nic_rx_has_work(adapter) || netxen_nic_tx_has_work(adapter)) {
-		if (netif_rx_schedule_prep(netdev, &adapter->napi)) {
-			/*
-			 * Interrupts are already disabled.
-			 */
-			__netif_rx_schedule(netdev, &adapter->napi);
-		} else {
-			static unsigned int intcount = 0;
-			if ((++intcount & 0xfff) == 0xfff)
-				DPRINTK(KERN_ERR
-				       "%s: %s interrupt %d while in poll\n",
-				       netxen_nic_driver_name, netdev->name,
-				       intcount);
-		}
-		ret = 1;
-	}
-
-	if (ret == 0) {
-		netxen_nic_enable_int(adapter);
-	}
-
-	return ret;
-}
-
 /*
  * netxen_intr - Interrupt Handler
  * @irq: interrupt number
@@ -1278,8 +1243,12 @@ irqreturn_t netxen_intr(int irq, void *d
 		}
 	}
 
-	if (netif_running(netdev))
-		netxen_handle_int(adapter, netdev);
+	adapter->stats.ints++;
+
+	if (netif_rx_schedule_prep(netdev, &adapter->napi)) {
+		netxen_nic_disable_int(adapter);
+		__netif_rx_schedule(netdev, &adapter->napi);
+	}
 
 	return IRQ_HANDLED;
 }
@@ -1287,12 +1256,11 @@ irqreturn_t netxen_intr(int irq, void *d
 static int netxen_nic_poll(struct napi_struct *napi, int budget)
 {
 	struct netxen_adapter *adapter = container_of(napi, struct netxen_adapter, napi);
-	struct net_device *netdev = adapter->netdev;
-	int done = 1;
+	int tx_complete;
 	int ctx;
 	int work_done;
 
-	DPRINTK(INFO, "polling for %d descriptors\n", *budget);
+	tx_complete = netxen_process_cmd_ring(adapter);
 
 	work_done = 0;
 	for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
@@ -1312,16 +1280,8 @@ static int netxen_nic_poll(struct napi_s
 						     budget / MAX_RCV_CTX);
 	}
 
-	if (work_done >= budget && netxen_nic_rx_has_work(adapter) != 0)
-		done = 0;
-
-	if (netxen_process_cmd_ring((unsigned long)adapter) == 0)
-		done = 0;
-
-	DPRINTK(INFO, "new work_done: %d work_to_do: %d\n",
-		work_done, work_to_do);
-	if (done) {
-		netif_rx_complete(netdev, napi);
+	if ((work_done < budget) && tx_complete) {
+		netif_rx_complete(adapter->netdev, &adapter->napi);
 		netxen_nic_enable_int(adapter);
 	}
 
Index: upstream/drivers/net/netxen/netxen_nic.h
===================================================================
--- upstream.orig/drivers/net/netxen/netxen_nic.h
+++ upstream/drivers/net/netxen/netxen_nic.h
@@ -839,7 +839,6 @@ struct netxen_rcv_desc_ctx {
 	u32 flags;
 	u32 producer;
 	u32 rcv_pending;	/* Num of bufs posted in phantom */
-	u32 rcv_free;		/* Num of bufs in free list */
 	dma_addr_t phys_addr;
 	struct pci_dev *phys_pdev;
 	struct rcv_desc *desc_head;	/* address of rx ring in Phantom */
@@ -1073,12 +1072,10 @@ void netxen_tso_check(struct netxen_adap
 		      struct cmd_desc_type0 *desc, struct sk_buff *skb);
 int netxen_nic_hw_resources(struct netxen_adapter *adapter);
 void netxen_nic_clear_stats(struct netxen_adapter *adapter);
-int netxen_nic_rx_has_work(struct netxen_adapter *adapter);
-int netxen_nic_tx_has_work(struct netxen_adapter *adapter);
 void netxen_watchdog_task(struct work_struct *work);
 void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx,
 			    u32 ringid);
-int netxen_process_cmd_ring(unsigned long data);
+int netxen_process_cmd_ring(struct netxen_adapter *adapter);
 u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctx, int max);
 void netxen_nic_set_multi(struct net_device *netdev);
 int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu);
Index: upstream/drivers/net/netxen/netxen_nic_init.c
===================================================================
--- upstream.orig/drivers/net/netxen/netxen_nic_init.c
+++ upstream/drivers/net/netxen/netxen_nic_init.c
@@ -185,7 +185,6 @@ void netxen_initialize_adapter_sw(struct
 		for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
 			struct netxen_rx_buffer *rx_buf;
 			rcv_desc = &adapter->recv_ctx[ctxid].rcv_desc[ring];
-			rcv_desc->rcv_free = rcv_desc->max_rx_desc_count;
 			rcv_desc->begin_alloc = 0;
 			rx_buf = rcv_desc->rx_buf_arr;
 			num_rx_bufs = rcv_desc->max_rx_desc_count;
@@ -975,28 +974,6 @@ int netxen_phantom_init(struct netxen_ad
 	return 0;
 }
 
-int netxen_nic_rx_has_work(struct netxen_adapter *adapter)
-{
-	int ctx;
-
-	for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
-		struct netxen_recv_context *recv_ctx =
-		    &(adapter->recv_ctx[ctx]);
-		u32 consumer;
-		struct status_desc *desc_head;
-		struct status_desc *desc;
-
-		consumer = recv_ctx->status_rx_consumer;
-		desc_head = recv_ctx->rcv_status_desc_head;
-		desc = &desc_head[consumer];
-
-		if (netxen_get_sts_owner(desc) & STATUS_OWNER_HOST)
-			return 1;
-	}
-
-	return 0;
-}
-
 static int netxen_nic_check_temp(struct netxen_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
@@ -1175,7 +1152,6 @@ static void netxen_process_rcv(struct ne
 
 	netdev->last_rx = jiffies;
 
-	rcv_desc->rcv_free++;
 	rcv_desc->rcv_pending--;
 
 	/*
@@ -1231,23 +1207,22 @@ u32 netxen_process_rcv_ring(struct netxe
 		recv_ctx->status_rx_consumer = consumer;
 		recv_ctx->status_rx_producer = producer;
 
+		smp_wmb();
 		/* Window = 1 */
 		writel(consumer,
 		       NETXEN_CRB_NORMALIZE(adapter,
 					    recv_crb_registers[adapter->portnum].
 					    crb_rcv_status_consumer));
-		wmb();
 	}
 
 	return count;
 }
 
 /* Process Command status ring */
-int netxen_process_cmd_ring(unsigned long data)
+int netxen_process_cmd_ring(struct netxen_adapter *adapter)
 {
 	u32 last_consumer;
 	u32 consumer;
-	struct netxen_adapter *adapter = (struct netxen_adapter *)data;
 	int count1 = 0;
 	int count2 = 0;
 	struct netxen_cmd_buffer *buffer;
@@ -1353,11 +1328,7 @@ int netxen_process_cmd_ring(unsigned lon
 	 * There is still a possible race condition and the host could miss an
 	 * interrupt. The card has to take care of this.
 	 */
-	if (adapter->last_cmd_consumer == consumer &&
-	    (((adapter->cmd_producer + 1) %
-	      adapter->max_tx_desc_count) == adapter->last_cmd_consumer)) {
-		consumer = le32_to_cpu(*(adapter->cmd_consumer));
-	}
+	consumer = le32_to_cpu(*(adapter->cmd_consumer));
 	done = (adapter->last_cmd_consumer == consumer);
 
 	spin_unlock(&adapter->tx_lock);
@@ -1436,8 +1407,6 @@ void netxen_post_rx_buffers(struct netxe
 		rcv_desc->begin_alloc = index;
 		rcv_desc->rcv_pending += count;
 		rcv_desc->producer = producer;
-		if (rcv_desc->rcv_free >= 32) {
-			rcv_desc->rcv_free = 0;
 			/* Window = 1 */
 			writel((producer - 1) &
 			       (rcv_desc->max_rx_desc_count - 1),
@@ -1461,8 +1430,6 @@ void netxen_post_rx_buffers(struct netxe
 			writel(msg,
 			       DB_NORMALIZE(adapter,
 					    NETXEN_RCV_PRODUCER_OFFSET));
-			wmb();
-		}
 	}
 }
 
@@ -1526,8 +1493,6 @@ static void netxen_post_rx_buffers_nodb(
 		rcv_desc->begin_alloc = index;
 		rcv_desc->rcv_pending += count;
 		rcv_desc->producer = producer;
-		if (rcv_desc->rcv_free >= 32) {
-			rcv_desc->rcv_free = 0;
 			/* Window = 1 */
 			writel((producer - 1) &
 			       (rcv_desc->max_rx_desc_count - 1),
@@ -1537,21 +1502,9 @@ static void netxen_post_rx_buffers_nodb(
 						    rcv_desc_crb[ringid].
 						    crb_rcv_producer_offset));
 			wmb();
-		}
 	}
 }
 
-int netxen_nic_tx_has_work(struct netxen_adapter *adapter)
-{
-	if (find_diff_among(adapter->last_cmd_consumer,
-			    adapter->cmd_producer,
-			    adapter->max_tx_desc_count) > 0)
-		return 1;
-
-	return 0;
-}
-
-
 void netxen_nic_clear_stats(struct netxen_adapter *adapter)
 {
 	memset(&adapter->stats, 0, sizeof(adapter->stats));

-- 

  parent reply	other threads:[~2007-12-26 18:25 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-12-26 18:23 [patch 0/7] netxen bug fixes dhananjay
2007-12-26 18:23 ` [patch 1/7] netxen: update MAINTAINERS dhananjay
2008-01-12 22:36   ` Jeff Garzik
2007-12-26 18:23 ` [patch 2/7] netxen: update driver version dhananjay
2007-12-26 18:23 ` [patch 3/7] netxen: improve MSI interrupt handling dhananjay
2008-01-12 22:37   ` Jeff Garzik
2007-12-26 18:23 ` [patch 4/7] netxen: stop second phy correctly dhananjay
2008-01-12 22:37   ` Jeff Garzik
2007-12-26 18:23 ` dhananjay [this message]
2008-01-12 22:38   ` [patch 5/7] netxen: fix race in interrupt / napi Jeff Garzik
2008-01-14 18:00     ` Dhananjay Phadke
2007-12-26 18:23 ` [patch 6/7] netxen: optimize tx handling dhananjay
2008-01-12 22:38   ` Jeff Garzik
2007-12-26 18:23 ` [patch 7/7] netxen: fix byte-swapping in tx and rx dhananjay
2007-12-26 22:38   ` Al Viro
2007-12-26 23:29     ` Dhananjay Phadke
2007-12-26 23:53       ` Al Viro
2007-12-31 18:08         ` Dhananjay Phadke
2008-01-12 22:38           ` Jeff Garzik

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20071226182927.778015972@netxen.com \
    --to=dhananjay@netxen.com \
    --cc=jeff@garzik.org \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).