netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 2.6.25 1/1]S2io: Multiqueue network device support implementation
@ 2007-12-26 23:33 Sreenivasa Honnur
  0 siblings, 0 replies; 9+ messages in thread
From: Sreenivasa Honnur @ 2007-12-26 23:33 UTC (permalink / raw)
  To: netdev, jeff; +Cc: support

Multiqueue netwrok device support implementation.
- Added a loadable parameter "multiq" to enable/disable multiqueue support,
  by default it is disabled.
- skb->queue_mapping is not used for queue/fifo selection. FIFO iselection is
  based on IP-TOS value, 0x0-0xF TOS values are mapped to 8 FIFOs.
- Added per FIFO flags FIFO_QUEUE_START and FIFO_QUEUE_STOP. Check this flag
  for starting and stopping netif queue and update the flags accordingly.
- In tx_intr_handler added a check to ensure that we have free TXDs before wak-
  ing up the queue.
- Added helper functions for queue manipulation(start/stop/wakeup) to invoke
  appropriate netif_ functions.
- Calling netif_start/stop for link up/down case respectively.

Signed-off-by: Surjit Reang <surjit.reang@neterion.com>
Signed-off-by: Sreenivasa Honnur <sreenivasa.honnur@neterion.com>
---
diff -Nurp orig/drivers/net/s2io.c patch1/drivers/net/s2io.c
--- orig/drivers/net/s2io.c	2007-12-21 12:10:29.000000000 -0800
+++ patch1/drivers/net/s2io.c	2007-12-21 13:36:59.000000000 -0800
@@ -50,6 +50,8 @@
  *                 Possible values '1' for enable , '0' for disable.
  *                 Default is '2' - which means disable in promisc mode
  *                 and enable in non-promiscuous mode.
+ * multiq: This parameter used to enable/disable MULTIQUEUE support.          *
+ *      Possible values '1' for enable and '0' for disable. Default is '0'    *
  ************************************************************************/
 
 #include <linux/module.h>
@@ -84,7 +86,7 @@
 #include "s2io.h"
 #include "s2io-regs.h"
 
-#define DRV_VERSION "2.0.26.15-2"
+#define DRV_VERSION "2.0.26.16"
 
 /* S2io Driver name & version. */
 static char s2io_driver_name[] = "Neterion";
@@ -93,6 +95,12 @@ static char s2io_driver_version[] = DRV_
 static int rxd_size[2] = {32,48};
 static int rxd_count[2] = {127,85};
 
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+/* mapping from tos value to fifo number
+ * 0x0-0xF TOS values are mapped to 8 FIFOs */
+static int tos_map[] = {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7};
+#endif
+
 static inline int RXD_IS_UP2DT(struct RxD_t *rxdp)
 {
 	int ret;
@@ -458,6 +466,7 @@ MODULE_VERSION(DRV_VERSION);
 /* Module Loadable parameters. */
 S2IO_PARM_INT(tx_fifo_num, 1);
 S2IO_PARM_INT(rx_ring_num, 1);
+S2IO_PARM_INT(multiq, 0);
 
 
 S2IO_PARM_INT(rx_ring_mode, 1);
@@ -533,6 +542,101 @@ static struct pci_driver s2io_driver = {
 /* A simplifier macro used both by init and free shared_mem Fns(). */
 #define TXD_MEM_PAGE_CNT(len, per_each) ((len+per_each - 1) / per_each)
 
+/* netqueue manipulation helper functions */
+static inline void s2io_stop_all_tx_queue(struct s2io_nic *sp)
+{
+	int i;
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	if (sp->config.multiq) {
+		for (i = 0; i < sp->config.tx_fifo_num; i++)
+			netif_stop_subqueue(sp->dev, i);
+	} else
+#endif
+	{
+		for (i = 0; i < sp->config.tx_fifo_num; i++)
+			sp->mac_control.fifos[i].queue_state = FIFO_QUEUE_STOP;
+		netif_stop_queue(sp->dev);
+	}
+}
+
+static inline void s2io_stop_tx_queue(struct s2io_nic *sp, int fifo_no)
+{
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	if (sp->config.multiq)
+		netif_stop_subqueue(sp->dev, fifo_no);
+	else
+#endif
+	{
+		sp->mac_control.fifos[fifo_no].queue_state =
+			FIFO_QUEUE_STOP;
+		netif_stop_queue(sp->dev);
+	}
+}
+
+static inline void s2io_start_all_tx_queue(struct s2io_nic *sp)
+{
+	int i;
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	if (sp->config.multiq) {
+		for (i = 0; i < sp->config.tx_fifo_num; i++)
+			netif_start_subqueue(sp->dev, i);
+	} else
+#endif
+	{
+		for (i = 0; i < sp->config.tx_fifo_num; i++)
+			sp->mac_control.fifos[i].queue_state = FIFO_QUEUE_START;
+		netif_start_queue(sp->dev);
+	}
+}
+
+static inline void s2io_start_tx_queue(struct s2io_nic *sp, int fifo_no)
+{
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	if (multiq)
+		netif_start_subqueue(sp->dev, fifo_no);
+	else
+#endif
+	{
+		sp->mac_control.fifos[fifo_no].queue_state =
+			FIFO_QUEUE_START;
+		netif_start_queue(sp->dev);
+	}
+}
+
+static inline void s2io_wake_all_tx_queue(struct s2io_nic *sp)
+{
+	int i;
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	if (sp->config.multiq) {
+			for (i = 0; i < sp->config.tx_fifo_num; i++)
+				netif_wake_subqueue(sp->dev, i);
+	} else
+#endif
+	{
+		for (i = 0; i < sp->config.tx_fifo_num; i++)
+			sp->mac_control.fifos[i].queue_state = FIFO_QUEUE_START;
+		netif_wake_queue(sp->dev);
+	}
+}
+
+static inline void s2io_wake_tx_queue(
+	struct fifo_info *fifo, int cnt, u8 multiq)
+{
+
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	if (multiq) {
+		if (cnt && __netif_subqueue_stopped(fifo->dev, fifo->fifo_no))
+			netif_wake_subqueue(fifo->dev, fifo->fifo_no);
+	} else
+#endif
+	if (cnt && (fifo->queue_state == FIFO_QUEUE_STOP)) {
+		if (netif_queue_stopped(fifo->dev)) {
+			fifo->queue_state = FIFO_QUEUE_START;
+			netif_wake_queue(fifo->dev);
+		}
+	}
+}
+
 /**
  * init_shared_mem - Allocation and Initialization of Memory
  * @nic: Device private variable.
@@ -614,6 +718,7 @@ static int init_shared_mem(struct s2io_n
 		mac_control->fifos[i].fifo_no = i;
 		mac_control->fifos[i].nic = nic;
 		mac_control->fifos[i].max_txds = MAX_SKB_FRAGS + 2;
+		mac_control->fifos[i].dev = dev;
 
 		for (j = 0; j < page_num; j++) {
 			int k = 0;
@@ -2975,10 +3080,10 @@ static void rx_intr_handler(struct ring_
 static void tx_intr_handler(struct fifo_info *fifo_data)
 {
 	struct s2io_nic *nic = fifo_data->nic;
-	struct net_device *dev = (struct net_device *) nic->dev;
 	struct tx_curr_get_info get_info, put_info;
-	struct sk_buff *skb;
+	struct sk_buff *skb = NULL;
 	struct TxD *txdlp;
+	int pkt_cnt = 0;
 	unsigned long flags = 0;
 	u8 err_mask;
 
@@ -3040,6 +3145,8 @@ static void tx_intr_handler(struct fifo_
 			return;
 		}
 
+		pkt_cnt++;
+
 		/* Updating the statistics block */
 		nic->stats.tx_bytes += skb->len;
 		nic->mac_control.stats_info->sw_stat.mem_freed += skb->truesize;
@@ -3054,8 +3161,7 @@ static void tx_intr_handler(struct fifo_
 		    get_info.offset;
 	}
 
-	if (netif_queue_stopped(dev))
-		netif_wake_queue(dev);
+	s2io_wake_tx_queue(fifo_data, pkt_cnt, nic->config.multiq);
 
 	spin_unlock_irqrestore(&fifo_data->tx_lock, flags);
 }
@@ -3939,7 +4045,7 @@ static int s2io_open(struct net_device *
 		goto hw_init_failed;
 	}
 
-	netif_start_queue(dev);
+	s2io_start_all_tx_queue(sp);
 	return 0;
 
 hw_init_failed:
@@ -3985,7 +4091,7 @@ static int s2io_close(struct net_device 
 	if (!is_s2io_card_up(sp))
 		return 0;
 
-	netif_stop_queue(dev);
+	s2io_stop_all_tx_queue(sp);
 
 	/* delete all populated mac entries */
 	for (offset = 1; offset < config->max_mc_addr; offset++) {
@@ -4055,9 +4161,34 @@ static int s2io_xmit(struct sk_buff *skb
 		vlan_priority = vlan_tag >> 13;
 		queue = config->fifo_mapping[vlan_priority];
 	}
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	else if (skb->protocol == htons(ETH_P_IP) && sp->config.multiq) {
+		struct iphdr *ip;
+		ip = ip_hdr(skb);
+
+		/* get fifo number based on TOS value */
+		queue = tos_map[IPTOS_TOS(ip->tos) >> 1];
+	}
+#endif
 
 	fifo = &mac_control->fifos[queue];
 	spin_lock_irqsave(&fifo->tx_lock, flags);
+
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	if (sp->config.multiq) {
+		if (__netif_subqueue_stopped(dev, fifo->fifo_no)) {
+			spin_unlock_irqrestore(&fifo->tx_lock, flags);
+			return NETDEV_TX_BUSY;
+		}
+	} else
+#endif
+	if (unlikely(fifo->queue_state == FIFO_QUEUE_STOP)) {
+		if (netif_queue_stopped(dev)) {
+			spin_unlock_irqrestore(&fifo->tx_lock, flags);
+			return NETDEV_TX_BUSY;
+		}
+	}
+
 	put_off = (u16) fifo->tx_curr_put_info.offset;
 	get_off = (u16) fifo->tx_curr_get_info.offset;
 	txdp = (struct TxD *) fifo->list_info[put_off].list_virt_addr;
@@ -4067,7 +4198,7 @@ static int s2io_xmit(struct sk_buff *skb
 	if (txdp->Host_Control ||
 		   ((put_off+1) == queue_len ? 0 : (put_off+1)) == get_off) {
 		DBG_PRINT(TX_DBG, "Error in xmit, No free TXDs.\n");
-		netif_stop_queue(dev);
+		s2io_stop_tx_queue(sp, fifo->fifo_no);
 		dev_kfree_skb(skb);
 		spin_unlock_irqrestore(&fifo->tx_lock, flags);
 		return 0;
@@ -4173,7 +4304,7 @@ static int s2io_xmit(struct sk_buff *skb
 		DBG_PRINT(TX_DBG,
 			  "No free TxDs for xmit, Put: 0x%x Get:0x%x\n",
 			  put_off, get_off);
-		netif_stop_queue(dev);
+		s2io_stop_tx_queue(sp, fifo->fifo_no);
 	}
 	mac_control->stats_info->sw_stat.mem_allocated += skb->truesize;
 	dev->trans_start = jiffies;
@@ -4182,7 +4313,7 @@ static int s2io_xmit(struct sk_buff *skb
 	return 0;
 pci_map_failed:
 	stats->pci_map_fail_cnt++;
-	netif_stop_queue(dev);
+	s2io_stop_tx_queue(sp, fifo->fifo_no);
 	stats->mem_freed += skb->truesize;
 	dev_kfree_skb(skb);
 	spin_unlock_irqrestore(&fifo->tx_lock, flags);
@@ -4594,7 +4725,7 @@ static void s2io_handle_errors(void * de
 	return;
 
 reset:
-	netif_stop_queue(dev);
+	s2io_stop_all_tx_queue(sp);
 	schedule_work(&sp->rst_timer_task);
 	sw_stat->soft_reset_cnt++;
 	return;
@@ -6581,16 +6712,16 @@ static int s2io_change_mtu(struct net_de
 
 	dev->mtu = new_mtu;
 	if (netif_running(dev)) {
+		s2io_stop_all_tx_queue(sp);
 		s2io_card_down(sp);
-		netif_stop_queue(dev);
+
 		ret = s2io_card_up(sp);
 		if (ret) {
 			DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
 				  __FUNCTION__);
 			return ret;
 		}
-		if (netif_queue_stopped(dev))
-			netif_wake_queue(dev);
+		s2io_wake_all_tx_queue(sp);
 	} else { /* Device is down */
 		struct XENA_dev_config __iomem *bar0 = sp->bar0;
 		u64 val64 = new_mtu;
@@ -6698,7 +6829,7 @@ static void s2io_set_link(struct work_st
 			} else {
 				DBG_PRINT(ERR_DBG, "%s: Error: ", dev->name);
 				DBG_PRINT(ERR_DBG, "device is not Quiescent\n");
-				netif_stop_queue(dev);
+				s2io_stop_all_tx_queue(nic);
 			}
 		}
 		val64 = readq(&bar0->adapter_control);
@@ -7177,7 +7308,8 @@ static void s2io_restart_nic(struct work
 		DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
 			  dev->name);
 	}
-	netif_wake_queue(dev);
+	s2io_wake_all_tx_queue(sp);
+
 	DBG_PRINT(ERR_DBG, "%s: was reset by Tx watchdog timer\n",
 		  dev->name);
 out_unlock:
@@ -7456,6 +7588,7 @@ static void s2io_link(struct s2io_nic * 
 		init_tti(sp, link);
 		if (link == LINK_DOWN) {
 			DBG_PRINT(ERR_DBG, "%s: Link down\n", dev->name);
+			s2io_stop_all_tx_queue(sp);
 			netif_carrier_off(dev);
 			if(sp->mac_control.stats_info->sw_stat.link_up_cnt)
 			sp->mac_control.stats_info->sw_stat.link_up_time =
@@ -7468,6 +7601,7 @@ static void s2io_link(struct s2io_nic * 
 				jiffies - sp->start_time;
 			sp->mac_control.stats_info->sw_stat.link_up_cnt++;
 			netif_carrier_on(dev);
+			s2io_wake_all_tx_queue(sp);
 		}
 	}
 	sp->last_link_state = link;
@@ -7504,7 +7638,8 @@ static void s2io_init_pci(struct s2io_ni
 	pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd);
 }
 
-static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type)
+static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type,
+	u8 *dev_multiq)
 {
 	if ((tx_fifo_num > MAX_TX_FIFOS) ||
 		(tx_fifo_num < FIFO_DEFAULT_NUM)) {
@@ -7518,6 +7653,19 @@ static int s2io_verify_parm(struct pci_d
 		DBG_PRINT(ERR_DBG, "tx fifos\n");
 	}
 
+#ifndef CONFIG_NETDEVICES_MULTIQUEUE
+	if (multiq) {
+		DBG_PRINT(ERR_DBG, "s2io: Multiqueue support not enabled\n");
+		multiq = 0;
+	}
+#endif
+
+	/* if multiqueue is enabled configure all fifos	*/
+	if (multiq) {
+		tx_fifo_num = MAX_TX_FIFOS;
+		*dev_multiq = multiq;
+	}
+
 	if ( rx_ring_num > 8) {
 		DBG_PRINT(ERR_DBG, "s2io: Requested number of Rx rings not "
 			 "supported\n");
@@ -7609,9 +7757,11 @@ s2io_init_nic(struct pci_dev *pdev, cons
 	struct config_param *config;
 	int mode;
 	u8 dev_intr_type = intr_type;
+	u8 dev_multiq = 0;
 	DECLARE_MAC_BUF(mac);
 
-	if ((ret = s2io_verify_parm(pdev, &dev_intr_type)))
+	ret = s2io_verify_parm(pdev, &dev_intr_type, &dev_multiq);
+	if (ret)
 		return ret;
 
 	if ((ret = pci_enable_device(pdev))) {
@@ -7643,7 +7793,13 @@ s2io_init_nic(struct pci_dev *pdev, cons
 		return -ENODEV;
 	}
 
-	dev = alloc_etherdev(sizeof(struct s2io_nic));
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	if (dev_multiq)
+		dev = alloc_etherdev_mq(sizeof(struct s2io_nic), MAX_TX_FIFOS);
+	else
+#endif
+		dev = alloc_etherdev(sizeof(struct s2io_nic));
+
 	if (dev == NULL) {
 		DBG_PRINT(ERR_DBG, "Device allocation failed\n");
 		pci_disable_device(pdev);
@@ -7694,6 +7850,7 @@ s2io_init_nic(struct pci_dev *pdev, cons
 
 	/* Tx side parameters. */
 	config->tx_fifo_num = tx_fifo_num;
+	config->multiq = dev_multiq;
 	for (i = 0; i < MAX_TX_FIFOS; i++) {
 		config->tx_cfg[i].fifo_len = tx_fifo_len[i];
 		config->tx_cfg[i].fifo_priority = i;
@@ -7807,6 +7964,11 @@ s2io_init_nic(struct pci_dev *pdev, cons
 		dev->features |= NETIF_F_HW_CSUM;
 	}
 
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	if (config->multiq)
+		dev->features |= NETIF_F_MULTI_QUEUE;
+#endif
+
 	dev->tx_timeout = &s2io_tx_watchdog;
 	dev->watchdog_timeo = WATCH_DOG_TIMEOUT;
 	INIT_WORK(&sp->rst_timer_task, s2io_restart_nic);
@@ -7963,6 +8125,16 @@ s2io_init_nic(struct pci_dev *pdev, cons
 		    DBG_PRINT(ERR_DBG, "%s: Interrupt type MSI-X\n", dev->name);
 		    break;
 	}
+
+	if (sp->config.multiq) {
+		for (i = 0; i < sp->config.tx_fifo_num; i++)
+			mac_control->fifos[i].multiq = config->multiq;
+		DBG_PRINT(ERR_DBG, "%s: Multiqueue support enabled\n",
+			dev->name);
+	} else
+		DBG_PRINT(ERR_DBG, "%s: Multiqueue support disabled\n",
+			dev->name);
+
 	if (sp->lro)
 		DBG_PRINT(ERR_DBG, "%s: Large receive offload enabled\n",
 			  dev->name);
diff -Nurp orig/drivers/net/s2io.h patch1/drivers/net/s2io.h
--- orig/drivers/net/s2io.h	2007-12-21 12:10:29.000000000 -0800
+++ patch1/drivers/net/s2io.h	2007-12-21 13:36:28.000000000 -0800
@@ -464,6 +464,7 @@ struct config_param {
 	int max_mc_addr;	/* xena=64 herc=256 */
 	int max_mac_addr;	/* xena=16 herc=64 */
 	int mc_start_offset;	/* xena=16 herc=64 */
+	u8 multiq;
 };
 
 /* Structure representing MAC Addrs */
@@ -721,6 +722,17 @@ struct fifo_info {
 	 */
 	struct tx_curr_get_info tx_curr_get_info;
 
+
+#define FIFO_QUEUE_START 0
+#define FIFO_QUEUE_STOP 1
+	int queue_state;
+
+	/* copy of sp->dev pointer */
+	struct net_device *dev;
+
+	/* copy of multiq status */
+	u8 multiq;
+
 	/* Per fifo lock */
 	spinlock_t tx_lock;
 
@@ -756,7 +768,7 @@ struct mac_info {
 	dma_addr_t stats_mem_phy;	/* Physical address of the stat block */
 	u32 stats_mem_sz;
 	struct stat_block *stats_info;	/* Logical address of the stat block */
-};
+} ____cacheline_aligned;
 
 /* structure representing the user defined MAC addresses */
 struct usr_addr {


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 2.6.25 1/1]S2io: Multiqueue network device support implementation
@ 2008-01-23  0:45 Sreenivasa Honnur
  2008-01-23  0:55 ` Jeff Garzik
  2008-01-23 10:58 ` Andi Kleen
  0 siblings, 2 replies; 9+ messages in thread
From: Sreenivasa Honnur @ 2008-01-23  0:45 UTC (permalink / raw)
  To: netdev, jeff; +Cc: support

Multiqueue netwrok device support implementation.
- Added a loadable parameter "multiq" to enable/disable multiqueue support,
  by default it is disabled.
- skb->queue_mapping is not used for queue/fifo selection. FIFO iselection is
  based on IP-TOS value, 0x0-0xF TOS values are mapped to 8 FIFOs.
- Added per FIFO flags FIFO_QUEUE_START and FIFO_QUEUE_STOP. Check this flag
  for starting and stopping netif queue and update the flags accordingly.
- In tx_intr_handler added a check to ensure that we have free TXDs before wak-
  ing up the queue.
- Added helper functions for queue manipulation(start/stop/wakeup) to invoke
  appropriate netif_ functions.
- Calling netif_start/stop for link up/down case respectively.

Signed-off-by: Surjit Reang <surjit.reang@neterion.com>
Signed-off-by: Sreenivasa Honnur <sreenivasa.honnur@neterion.com>
---
diff -Nurp orig/drivers/net/s2io.c patch1/drivers/net/s2io.c
--- orig/drivers/net/s2io.c	2007-12-21 12:10:29.000000000 -0800
+++ patch1/drivers/net/s2io.c	2007-12-21 13:36:59.000000000 -0800
@@ -50,6 +50,8 @@
  *                 Possible values '1' for enable , '0' for disable.
  *                 Default is '2' - which means disable in promisc mode
  *                 and enable in non-promiscuous mode.
+ * multiq: This parameter used to enable/disable MULTIQUEUE support.          *
+ *      Possible values '1' for enable and '0' for disable. Default is '0'    *
  ************************************************************************/
 
 #include <linux/module.h>
@@ -84,7 +86,7 @@
 #include "s2io.h"
 #include "s2io-regs.h"
 
-#define DRV_VERSION "2.0.26.15-2"
+#define DRV_VERSION "2.0.26.16"
 
 /* S2io Driver name & version. */
 static char s2io_driver_name[] = "Neterion";
@@ -93,6 +95,12 @@ static char s2io_driver_version[] = DRV_
 static int rxd_size[2] = {32,48};
 static int rxd_count[2] = {127,85};
 
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+/* mapping from tos value to fifo number
+ * 0x0-0xF TOS values are mapped to 8 FIFOs */
+static int tos_map[] = {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7};
+#endif
+
 static inline int RXD_IS_UP2DT(struct RxD_t *rxdp)
 {
 	int ret;
@@ -458,6 +466,7 @@ MODULE_VERSION(DRV_VERSION);
 /* Module Loadable parameters. */
 S2IO_PARM_INT(tx_fifo_num, 1);
 S2IO_PARM_INT(rx_ring_num, 1);
+S2IO_PARM_INT(multiq, 0);
 
 
 S2IO_PARM_INT(rx_ring_mode, 1);
@@ -533,6 +542,101 @@ static struct pci_driver s2io_driver = {
 /* A simplifier macro used both by init and free shared_mem Fns(). */
 #define TXD_MEM_PAGE_CNT(len, per_each) ((len+per_each - 1) / per_each)
 
+/* netqueue manipulation helper functions */
+static inline void s2io_stop_all_tx_queue(struct s2io_nic *sp)
+{
+	int i;
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	if (sp->config.multiq) {
+		for (i = 0; i < sp->config.tx_fifo_num; i++)
+			netif_stop_subqueue(sp->dev, i);
+	} else
+#endif
+	{
+		for (i = 0; i < sp->config.tx_fifo_num; i++)
+			sp->mac_control.fifos[i].queue_state = FIFO_QUEUE_STOP;
+		netif_stop_queue(sp->dev);
+	}
+}
+
+static inline void s2io_stop_tx_queue(struct s2io_nic *sp, int fifo_no)
+{
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	if (sp->config.multiq)
+		netif_stop_subqueue(sp->dev, fifo_no);
+	else
+#endif
+	{
+		sp->mac_control.fifos[fifo_no].queue_state =
+			FIFO_QUEUE_STOP;
+		netif_stop_queue(sp->dev);
+	}
+}
+
+static inline void s2io_start_all_tx_queue(struct s2io_nic *sp)
+{
+	int i;
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	if (sp->config.multiq) {
+		for (i = 0; i < sp->config.tx_fifo_num; i++)
+			netif_start_subqueue(sp->dev, i);
+	} else
+#endif
+	{
+		for (i = 0; i < sp->config.tx_fifo_num; i++)
+			sp->mac_control.fifos[i].queue_state = FIFO_QUEUE_START;
+		netif_start_queue(sp->dev);
+	}
+}
+
+static inline void s2io_start_tx_queue(struct s2io_nic *sp, int fifo_no)
+{
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	if (multiq)
+		netif_start_subqueue(sp->dev, fifo_no);
+	else
+#endif
+	{
+		sp->mac_control.fifos[fifo_no].queue_state =
+			FIFO_QUEUE_START;
+		netif_start_queue(sp->dev);
+	}
+}
+
+static inline void s2io_wake_all_tx_queue(struct s2io_nic *sp)
+{
+	int i;
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	if (sp->config.multiq) {
+			for (i = 0; i < sp->config.tx_fifo_num; i++)
+				netif_wake_subqueue(sp->dev, i);
+	} else
+#endif
+	{
+		for (i = 0; i < sp->config.tx_fifo_num; i++)
+			sp->mac_control.fifos[i].queue_state = FIFO_QUEUE_START;
+		netif_wake_queue(sp->dev);
+	}
+}
+
+static inline void s2io_wake_tx_queue(
+	struct fifo_info *fifo, int cnt, u8 multiq)
+{
+
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	if (multiq) {
+		if (cnt && __netif_subqueue_stopped(fifo->dev, fifo->fifo_no))
+			netif_wake_subqueue(fifo->dev, fifo->fifo_no);
+	} else
+#endif
+	if (cnt && (fifo->queue_state == FIFO_QUEUE_STOP)) {
+		if (netif_queue_stopped(fifo->dev)) {
+			fifo->queue_state = FIFO_QUEUE_START;
+			netif_wake_queue(fifo->dev);
+		}
+	}
+}
+
 /**
  * init_shared_mem - Allocation and Initialization of Memory
  * @nic: Device private variable.
@@ -614,6 +718,7 @@ static int init_shared_mem(struct s2io_n
 		mac_control->fifos[i].fifo_no = i;
 		mac_control->fifos[i].nic = nic;
 		mac_control->fifos[i].max_txds = MAX_SKB_FRAGS + 2;
+		mac_control->fifos[i].dev = dev;
 
 		for (j = 0; j < page_num; j++) {
 			int k = 0;
@@ -2975,10 +3080,10 @@ static void rx_intr_handler(struct ring_
 static void tx_intr_handler(struct fifo_info *fifo_data)
 {
 	struct s2io_nic *nic = fifo_data->nic;
-	struct net_device *dev = (struct net_device *) nic->dev;
 	struct tx_curr_get_info get_info, put_info;
-	struct sk_buff *skb;
+	struct sk_buff *skb = NULL;
 	struct TxD *txdlp;
+	int pkt_cnt = 0;
 	unsigned long flags = 0;
 	u8 err_mask;
 
@@ -3040,6 +3145,8 @@ static void tx_intr_handler(struct fifo_
 			return;
 		}
 
+		pkt_cnt++;
+
 		/* Updating the statistics block */
 		nic->stats.tx_bytes += skb->len;
 		nic->mac_control.stats_info->sw_stat.mem_freed += skb->truesize;
@@ -3054,8 +3161,7 @@ static void tx_intr_handler(struct fifo_
 		    get_info.offset;
 	}
 
-	if (netif_queue_stopped(dev))
-		netif_wake_queue(dev);
+	s2io_wake_tx_queue(fifo_data, pkt_cnt, nic->config.multiq);
 
 	spin_unlock_irqrestore(&fifo_data->tx_lock, flags);
 }
@@ -3939,7 +4045,7 @@ static int s2io_open(struct net_device *
 		goto hw_init_failed;
 	}
 
-	netif_start_queue(dev);
+	s2io_start_all_tx_queue(sp);
 	return 0;
 
 hw_init_failed:
@@ -3985,7 +4091,7 @@ static int s2io_close(struct net_device 
 	if (!is_s2io_card_up(sp))
 		return 0;
 
-	netif_stop_queue(dev);
+	s2io_stop_all_tx_queue(sp);
 
 	/* delete all populated mac entries */
 	for (offset = 1; offset < config->max_mc_addr; offset++) {
@@ -4055,9 +4161,34 @@ static int s2io_xmit(struct sk_buff *skb
 		vlan_priority = vlan_tag >> 13;
 		queue = config->fifo_mapping[vlan_priority];
 	}
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	else if (skb->protocol == htons(ETH_P_IP) && sp->config.multiq) {
+		struct iphdr *ip;
+		ip = ip_hdr(skb);
+
+		/* get fifo number based on TOS value */
+		queue = tos_map[IPTOS_TOS(ip->tos) >> 1];
+	}
+#endif
 
 	fifo = &mac_control->fifos[queue];
 	spin_lock_irqsave(&fifo->tx_lock, flags);
+
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	if (sp->config.multiq) {
+		if (__netif_subqueue_stopped(dev, fifo->fifo_no)) {
+			spin_unlock_irqrestore(&fifo->tx_lock, flags);
+			return NETDEV_TX_BUSY;
+		}
+	} else
+#endif
+	if (unlikely(fifo->queue_state == FIFO_QUEUE_STOP)) {
+		if (netif_queue_stopped(dev)) {
+			spin_unlock_irqrestore(&fifo->tx_lock, flags);
+			return NETDEV_TX_BUSY;
+		}
+	}
+
 	put_off = (u16) fifo->tx_curr_put_info.offset;
 	get_off = (u16) fifo->tx_curr_get_info.offset;
 	txdp = (struct TxD *) fifo->list_info[put_off].list_virt_addr;
@@ -4067,7 +4198,7 @@ static int s2io_xmit(struct sk_buff *skb
 	if (txdp->Host_Control ||
 		   ((put_off+1) == queue_len ? 0 : (put_off+1)) == get_off) {
 		DBG_PRINT(TX_DBG, "Error in xmit, No free TXDs.\n");
-		netif_stop_queue(dev);
+		s2io_stop_tx_queue(sp, fifo->fifo_no);
 		dev_kfree_skb(skb);
 		spin_unlock_irqrestore(&fifo->tx_lock, flags);
 		return 0;
@@ -4173,7 +4304,7 @@ static int s2io_xmit(struct sk_buff *skb
 		DBG_PRINT(TX_DBG,
 			  "No free TxDs for xmit, Put: 0x%x Get:0x%x\n",
 			  put_off, get_off);
-		netif_stop_queue(dev);
+		s2io_stop_tx_queue(sp, fifo->fifo_no);
 	}
 	mac_control->stats_info->sw_stat.mem_allocated += skb->truesize;
 	dev->trans_start = jiffies;
@@ -4182,7 +4313,7 @@ static int s2io_xmit(struct sk_buff *skb
 	return 0;
 pci_map_failed:
 	stats->pci_map_fail_cnt++;
-	netif_stop_queue(dev);
+	s2io_stop_tx_queue(sp, fifo->fifo_no);
 	stats->mem_freed += skb->truesize;
 	dev_kfree_skb(skb);
 	spin_unlock_irqrestore(&fifo->tx_lock, flags);
@@ -4594,7 +4725,7 @@ static void s2io_handle_errors(void * de
 	return;
 
 reset:
-	netif_stop_queue(dev);
+	s2io_stop_all_tx_queue(sp);
 	schedule_work(&sp->rst_timer_task);
 	sw_stat->soft_reset_cnt++;
 	return;
@@ -6581,16 +6712,16 @@ static int s2io_change_mtu(struct net_de
 
 	dev->mtu = new_mtu;
 	if (netif_running(dev)) {
+		s2io_stop_all_tx_queue(sp);
 		s2io_card_down(sp);
-		netif_stop_queue(dev);
+
 		ret = s2io_card_up(sp);
 		if (ret) {
 			DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
 				  __FUNCTION__);
 			return ret;
 		}
-		if (netif_queue_stopped(dev))
-			netif_wake_queue(dev);
+		s2io_wake_all_tx_queue(sp);
 	} else { /* Device is down */
 		struct XENA_dev_config __iomem *bar0 = sp->bar0;
 		u64 val64 = new_mtu;
@@ -6698,7 +6829,7 @@ static void s2io_set_link(struct work_st
 			} else {
 				DBG_PRINT(ERR_DBG, "%s: Error: ", dev->name);
 				DBG_PRINT(ERR_DBG, "device is not Quiescent\n");
-				netif_stop_queue(dev);
+				s2io_stop_all_tx_queue(nic);
 			}
 		}
 		val64 = readq(&bar0->adapter_control);
@@ -7177,7 +7308,8 @@ static void s2io_restart_nic(struct work
 		DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
 			  dev->name);
 	}
-	netif_wake_queue(dev);
+	s2io_wake_all_tx_queue(sp);
+
 	DBG_PRINT(ERR_DBG, "%s: was reset by Tx watchdog timer\n",
 		  dev->name);
 out_unlock:
@@ -7456,6 +7588,7 @@ static void s2io_link(struct s2io_nic * 
 		init_tti(sp, link);
 		if (link == LINK_DOWN) {
 			DBG_PRINT(ERR_DBG, "%s: Link down\n", dev->name);
+			s2io_stop_all_tx_queue(sp);
 			netif_carrier_off(dev);
 			if(sp->mac_control.stats_info->sw_stat.link_up_cnt)
 			sp->mac_control.stats_info->sw_stat.link_up_time =
@@ -7468,6 +7601,7 @@ static void s2io_link(struct s2io_nic * 
 				jiffies - sp->start_time;
 			sp->mac_control.stats_info->sw_stat.link_up_cnt++;
 			netif_carrier_on(dev);
+			s2io_wake_all_tx_queue(sp);
 		}
 	}
 	sp->last_link_state = link;
@@ -7504,7 +7638,8 @@ static void s2io_init_pci(struct s2io_ni
 	pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd);
 }
 
-static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type)
+static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type,
+	u8 *dev_multiq)
 {
 	if ((tx_fifo_num > MAX_TX_FIFOS) ||
 		(tx_fifo_num < FIFO_DEFAULT_NUM)) {
@@ -7518,6 +7653,19 @@ static int s2io_verify_parm(struct pci_d
 		DBG_PRINT(ERR_DBG, "tx fifos\n");
 	}
 
+#ifndef CONFIG_NETDEVICES_MULTIQUEUE
+	if (multiq) {
+		DBG_PRINT(ERR_DBG, "s2io: Multiqueue support not enabled\n");
+		multiq = 0;
+	}
+#endif
+
+	/* if multiqueue is enabled configure all fifos	*/
+	if (multiq) {
+		tx_fifo_num = MAX_TX_FIFOS;
+		*dev_multiq = multiq;
+	}
+
 	if ( rx_ring_num > 8) {
 		DBG_PRINT(ERR_DBG, "s2io: Requested number of Rx rings not "
 			 "supported\n");
@@ -7609,9 +7757,11 @@ s2io_init_nic(struct pci_dev *pdev, cons
 	struct config_param *config;
 	int mode;
 	u8 dev_intr_type = intr_type;
+	u8 dev_multiq = 0;
 	DECLARE_MAC_BUF(mac);
 
-	if ((ret = s2io_verify_parm(pdev, &dev_intr_type)))
+	ret = s2io_verify_parm(pdev, &dev_intr_type, &dev_multiq);
+	if (ret)
 		return ret;
 
 	if ((ret = pci_enable_device(pdev))) {
@@ -7643,7 +7793,13 @@ s2io_init_nic(struct pci_dev *pdev, cons
 		return -ENODEV;
 	}
 
-	dev = alloc_etherdev(sizeof(struct s2io_nic));
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	if (dev_multiq)
+		dev = alloc_etherdev_mq(sizeof(struct s2io_nic), MAX_TX_FIFOS);
+	else
+#endif
+		dev = alloc_etherdev(sizeof(struct s2io_nic));
+
 	if (dev == NULL) {
 		DBG_PRINT(ERR_DBG, "Device allocation failed\n");
 		pci_disable_device(pdev);
@@ -7694,6 +7850,7 @@ s2io_init_nic(struct pci_dev *pdev, cons
 
 	/* Tx side parameters. */
 	config->tx_fifo_num = tx_fifo_num;
+	config->multiq = dev_multiq;
 	for (i = 0; i < MAX_TX_FIFOS; i++) {
 		config->tx_cfg[i].fifo_len = tx_fifo_len[i];
 		config->tx_cfg[i].fifo_priority = i;
@@ -7807,6 +7964,11 @@ s2io_init_nic(struct pci_dev *pdev, cons
 		dev->features |= NETIF_F_HW_CSUM;
 	}
 
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	if (config->multiq)
+		dev->features |= NETIF_F_MULTI_QUEUE;
+#endif
+
 	dev->tx_timeout = &s2io_tx_watchdog;
 	dev->watchdog_timeo = WATCH_DOG_TIMEOUT;
 	INIT_WORK(&sp->rst_timer_task, s2io_restart_nic);
@@ -7963,6 +8125,16 @@ s2io_init_nic(struct pci_dev *pdev, cons
 		    DBG_PRINT(ERR_DBG, "%s: Interrupt type MSI-X\n", dev->name);
 		    break;
 	}
+
+	if (sp->config.multiq) {
+		for (i = 0; i < sp->config.tx_fifo_num; i++)
+			mac_control->fifos[i].multiq = config->multiq;
+		DBG_PRINT(ERR_DBG, "%s: Multiqueue support enabled\n",
+			dev->name);
+	} else
+		DBG_PRINT(ERR_DBG, "%s: Multiqueue support disabled\n",
+			dev->name);
+
 	if (sp->lro)
 		DBG_PRINT(ERR_DBG, "%s: Large receive offload enabled\n",
 			  dev->name);
diff -Nurp orig/drivers/net/s2io.h patch1/drivers/net/s2io.h
--- orig/drivers/net/s2io.h	2007-12-21 12:10:29.000000000 -0800
+++ patch1/drivers/net/s2io.h	2007-12-21 13:36:28.000000000 -0800
@@ -464,6 +464,7 @@ struct config_param {
 	int max_mc_addr;	/* xena=64 herc=256 */
 	int max_mac_addr;	/* xena=16 herc=64 */
 	int mc_start_offset;	/* xena=16 herc=64 */
+	u8 multiq;
 };
 
 /* Structure representing MAC Addrs */
@@ -721,6 +722,17 @@ struct fifo_info {
 	 */
 	struct tx_curr_get_info tx_curr_get_info;
 
+
+#define FIFO_QUEUE_START 0
+#define FIFO_QUEUE_STOP 1
+	int queue_state;
+
+	/* copy of sp->dev pointer */
+	struct net_device *dev;
+
+	/* copy of multiq status */
+	u8 multiq;
+
 	/* Per fifo lock */
 	spinlock_t tx_lock;
 
@@ -756,7 +768,7 @@ struct mac_info {
 	dma_addr_t stats_mem_phy;	/* Physical address of the stat block */
 	u32 stats_mem_sz;
 	struct stat_block *stats_info;	/* Logical address of the stat block */
-};
+} ____cacheline_aligned;
 
 /* structure representing the user defined MAC addresses */
 struct usr_addr {


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2.6.25 1/1]S2io: Multiqueue network device support implementation
  2008-01-23  0:45 [PATCH 2.6.25 1/1]S2io: Multiqueue network device support implementation Sreenivasa Honnur
@ 2008-01-23  0:55 ` Jeff Garzik
  2008-01-23 10:58 ` Andi Kleen
  1 sibling, 0 replies; 9+ messages in thread
From: Jeff Garzik @ 2008-01-23  0:55 UTC (permalink / raw)
  To: Sreenivasa Honnur; +Cc: netdev, support

Sreenivasa Honnur wrote:
> Multiqueue netwrok device support implementation.
> - Added a loadable parameter "multiq" to enable/disable multiqueue support,
>   by default it is disabled.
> - skb->queue_mapping is not used for queue/fifo selection. FIFO iselection is
>   based on IP-TOS value, 0x0-0xF TOS values are mapped to 8 FIFOs.
> - Added per FIFO flags FIFO_QUEUE_START and FIFO_QUEUE_STOP. Check this flag
>   for starting and stopping netif queue and update the flags accordingly.
> - In tx_intr_handler added a check to ensure that we have free TXDs before wak-
>   ing up the queue.
> - Added helper functions for queue manipulation(start/stop/wakeup) to invoke
>   appropriate netif_ functions.
> - Calling netif_start/stop for link up/down case respectively.
> 
> Signed-off-by: Surjit Reang <surjit.reang@neterion.com>
> Signed-off-by: Sreenivasa Honnur <sreenivasa.honnur@neterion.com>

thanks, at a quick glance, the use of the new multi-queue APIs look ok. 
  I'll give it another in-depth look and merge it.



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2.6.25 1/1]S2io: Multiqueue network device support implementation
  2008-01-23  0:45 [PATCH 2.6.25 1/1]S2io: Multiqueue network device support implementation Sreenivasa Honnur
  2008-01-23  0:55 ` Jeff Garzik
@ 2008-01-23 10:58 ` Andi Kleen
  2008-01-23 20:48   ` Ramkrishna Vepa
  1 sibling, 1 reply; 9+ messages in thread
From: Andi Kleen @ 2008-01-23 10:58 UTC (permalink / raw)
  To: Sreenivasa Honnur; +Cc: netdev, jeff, support

Sreenivasa Honnur <Sreenivasa.Honnur@neterion.com> writes:

> Multiqueue netwrok device support implementation.
> - Added a loadable parameter "multiq" to enable/disable multiqueue support,
>   by default it is disabled.
> - skb->queue_mapping is not used for queue/fifo selection. FIFO iselection is
>   based on IP-TOS value, 0x0-0xF TOS values are mapped to 8 FIFOs.

Standard way to use that would be using skb->priority

But I'm surprised you bother with TOS for multi queues at all. TOS
isn't a too important mechanism.

I would have thought the primary use case would be per CPU TX completion
interrupts. With that the queue should be selected based on
the the current CPU.

-Andi

^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [PATCH 2.6.25 1/1]S2io: Multiqueue network device support implementation
  2008-01-23 10:58 ` Andi Kleen
@ 2008-01-23 20:48   ` Ramkrishna Vepa
  2008-01-24  7:25     ` Andi Kleen
  0 siblings, 1 reply; 9+ messages in thread
From: Ramkrishna Vepa @ 2008-01-23 20:48 UTC (permalink / raw)
  To: Andi Kleen, Sreenivasa Honnur; +Cc: netdev, jeff, support

> Sreenivasa Honnur <Sreenivasa.Honnur@neterion.com> writes:
> 
> > Multiqueue netwrok device support implementation.
> > - Added a loadable parameter "multiq" to enable/disable multiqueue
> support,
> >   by default it is disabled.
> > - skb->queue_mapping is not used for queue/fifo selection. FIFO
> iselection is
> >   based on IP-TOS value, 0x0-0xF TOS values are mapped to 8 FIFOs.
> 
> Standard way to use that would be using skb->priority
[Ram] Thanks. We can use this field to determine the priority. It should
simplify the code.

> 
> But I'm surprised you bother with TOS for multi queues at all. TOS
> isn't a too important mechanism.
[Ram] Agreed TOS is not too important. The purpose of this patch was to
add the multiqueue functionality with a feature that can use it. With
multiple transmit fifos enabled, a whole new set of features that can be
enabled.

> 
> I would have thought the primary use case would be per CPU TX
completion
> interrupts. With that the queue should be selected based on
> the the current CPU.
> 
[Ram] I am assuming that this is with regards to msi-x interrupts. We
have done away with handling tx completion in the interrupt handler, and
are instead handling them in the context of the transmit. The slow path,
straggling transmit completions will be handled in the timer context.
This patch (along with other new features) will be sent soon.

Ram
> -Andi

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2.6.25 1/1]S2io: Multiqueue network device support implementation
  2008-01-23 20:48   ` Ramkrishna Vepa
@ 2008-01-24  7:25     ` Andi Kleen
  2008-01-24  7:30       ` David Miller
  2008-01-25  3:19       ` Ramkrishna Vepa
  0 siblings, 2 replies; 9+ messages in thread
From: Andi Kleen @ 2008-01-24  7:25 UTC (permalink / raw)
  To: Ramkrishna Vepa; +Cc: Andi Kleen, Sreenivasa Honnur, netdev, jeff, support

> [Ram] I am assuming that this is with regards to msi-x interrupts. We

Yes. 

And avoiding bouncing locks for device state between CPUs.

> have done away with handling tx completion in the interrupt handler, and
> are instead handling them in the context of the transmit. The slow path,
> straggling transmit completions will be handled in the timer context.

Ok -- hopefully you don't have bad corner cases from this when the pipe
is not fully filled and then causing longer latencies on completion. 
Old NAPI sometimes suffered from such problems. 

-Andi

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2.6.25 1/1]S2io: Multiqueue network device support implementation
  2008-01-24  7:25     ` Andi Kleen
@ 2008-01-24  7:30       ` David Miller
  2008-01-25  3:19         ` Ramkrishna Vepa
  2008-01-25  3:19       ` Ramkrishna Vepa
  1 sibling, 1 reply; 9+ messages in thread
From: David Miller @ 2008-01-24  7:30 UTC (permalink / raw)
  To: andi; +Cc: Ramkrishna.Vepa, Sreenivasa.Honnur, netdev, jeff, support

From: Andi Kleen <andi@firstfloor.org>
Date: Thu, 24 Jan 2008 08:25:49 +0100

> > have done away with handling tx completion in the interrupt handler, and
> > are instead handling them in the context of the transmit. The slow path,
> > straggling transmit completions will be handled in the timer context.
> 
> Ok -- hopefully you don't have bad corner cases from this when the pipe
> is not fully filled and then causing longer latencies on completion. 
> Old NAPI sometimes suffered from such problems. 

BTW, such a TX completion timer will stall TCP sockets when the TX
queue of the device is partially filled and then sending stops.

TX ring SKB liberation really must be done in a very small finite
amount of time in order to avoid this problem properly.

Deferring it to HZ granular timers doesn't give a quick enough
response, especially at high packet rates.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [PATCH 2.6.25 1/1]S2io: Multiqueue network device support implementation
  2008-01-24  7:25     ` Andi Kleen
  2008-01-24  7:30       ` David Miller
@ 2008-01-25  3:19       ` Ramkrishna Vepa
  1 sibling, 0 replies; 9+ messages in thread
From: Ramkrishna Vepa @ 2008-01-25  3:19 UTC (permalink / raw)
  To: Andi Kleen; +Cc: Sreenivasa Honnur, netdev, jeff, support

> > [Ram] I am assuming that this is with regards to msi-x interrupts.
We
> 
> Yes.
> 
> And avoiding bouncing locks for device state between CPUs.
> 
> > have done away with handling tx completion in the interrupt handler,
and
> > are instead handling them in the context of the transmit. The slow
path,
> > straggling transmit completions will be handled in the timer
context.
> 
> Ok -- hopefully you don't have bad corner cases from this when the
pipe
> is not fully filled and then causing longer latencies on completion.
> Old NAPI sometimes suffered from such problems.
[Ram] We have hit the driver pretty hard during testing and have not
encountered any problems either on the network or host.

Ram
> 
> -Andi

^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [PATCH 2.6.25 1/1]S2io: Multiqueue network device support implementation
  2008-01-24  7:30       ` David Miller
@ 2008-01-25  3:19         ` Ramkrishna Vepa
  0 siblings, 0 replies; 9+ messages in thread
From: Ramkrishna Vepa @ 2008-01-25  3:19 UTC (permalink / raw)
  To: David Miller, andi; +Cc: Sreenivasa Honnur, netdev, jeff, support

> From: netdev-owner@vger.kernel.org
[mailto:netdev-owner@vger.kernel.org]
> On Behalf Of David Miller
> Sent: Wednesday, January 23, 2008 11:30 PM
> 
> From: Andi Kleen <andi@firstfloor.org>
> Date: Thu, 24 Jan 2008 08:25:49 +0100
> 
> > > have done away with handling tx completion in the interrupt
handler,
> and
> > > are instead handling them in the context of the transmit. The slow
> path,
> > > straggling transmit completions will be handled in the timer
context.
> >
> > Ok -- hopefully you don't have bad corner cases from this when the
pipe
> > is not fully filled and then causing longer latencies on completion.
> > Old NAPI sometimes suffered from such problems.
> 
> BTW, such a TX completion timer will stall TCP sockets when the TX
> queue of the device is partially filled and then sending stops.
> 
> TX ring SKB liberation really must be done in a very small finite
> amount of time in order to avoid this problem properly.
> 
> Deferring it to HZ granular timers doesn't give a quick enough
> response, especially at high packet rates.
[Ram] We could add a lower granular tx completion interrupt instead, to
handle all the transmit fifos. But this will be a fall back in the event
the completions do not happen in the context of the transmit.

Ram

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2008-01-25  3:21 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-01-23  0:45 [PATCH 2.6.25 1/1]S2io: Multiqueue network device support implementation Sreenivasa Honnur
2008-01-23  0:55 ` Jeff Garzik
2008-01-23 10:58 ` Andi Kleen
2008-01-23 20:48   ` Ramkrishna Vepa
2008-01-24  7:25     ` Andi Kleen
2008-01-24  7:30       ` David Miller
2008-01-25  3:19         ` Ramkrishna Vepa
2008-01-25  3:19       ` Ramkrishna Vepa
  -- strict thread matches above, loose matches on Subject: below --
2007-12-26 23:33 Sreenivasa Honnur

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).