aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authordhananjay@netxen.com <dhananjay@netxen.com>2007-12-26 13:23:58 -0500
committerJeff Garzik <jeff@garzik.org>2008-01-12 17:35:38 -0500
commit53a01e00f8c78bc5875e09aca7749ea54bb09798 (patch)
tree00e5edaaf2d51d406bea63afd26dc41748c193f2 /drivers/net
parent72b0a7a8a40a50cf2eab42fd6a56e04b05090434 (diff)
netxen: optimize tx handling
netxen driver allows limited number of threads simultaneously posting skb's in tx ring. If transmit slot is unavailable, driver calls schedule() or loops in xmit_frame(). This patch returns TX_BUSY and lets the stack reschedule the packet if transmit slot is unavailable. Also removes unnecessary check for tx timeout in the driver itself, the network stack does that anyway. Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/netxen/netxen_nic_init.c10
-rw-r--r--drivers/net/netxen/netxen_nic_main.c52
2 files changed, 25 insertions, 37 deletions
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index 37589265297e..5f85ad686c98 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -1248,7 +1248,6 @@ int netxen_process_cmd_ring(unsigned long data)
1248 struct pci_dev *pdev; 1248 struct pci_dev *pdev;
1249 struct netxen_skb_frag *frag; 1249 struct netxen_skb_frag *frag;
1250 u32 i; 1250 u32 i;
1251 struct sk_buff *skb = NULL;
1252 int done; 1251 int done;
1253 1252
1254 spin_lock(&adapter->tx_lock); 1253 spin_lock(&adapter->tx_lock);
@@ -1278,9 +1277,8 @@ int netxen_process_cmd_ring(unsigned long data)
1278 while ((last_consumer != consumer) && (count1 < MAX_STATUS_HANDLE)) { 1277 while ((last_consumer != consumer) && (count1 < MAX_STATUS_HANDLE)) {
1279 buffer = &adapter->cmd_buf_arr[last_consumer]; 1278 buffer = &adapter->cmd_buf_arr[last_consumer];
1280 pdev = adapter->pdev; 1279 pdev = adapter->pdev;
1281 frag = &buffer->frag_array[0]; 1280 if (buffer->skb) {
1282 skb = buffer->skb; 1281 frag = &buffer->frag_array[0];
1283 if (skb && (cmpxchg(&buffer->skb, skb, 0) == skb)) {
1284 pci_unmap_single(pdev, frag->dma, frag->length, 1282 pci_unmap_single(pdev, frag->dma, frag->length,
1285 PCI_DMA_TODEVICE); 1283 PCI_DMA_TODEVICE);
1286 frag->dma = 0ULL; 1284 frag->dma = 0ULL;
@@ -1293,8 +1291,8 @@ int netxen_process_cmd_ring(unsigned long data)
1293 } 1291 }
1294 1292
1295 adapter->stats.skbfreed++; 1293 adapter->stats.skbfreed++;
1296 dev_kfree_skb_any(skb); 1294 dev_kfree_skb_any(buffer->skb);
1297 skb = NULL; 1295 buffer->skb = NULL;
1298 } else if (adapter->proc_cmd_buf_counter == 1) { 1296 } else if (adapter->proc_cmd_buf_counter == 1) {
1299 adapter->stats.txnullskb++; 1297 adapter->stats.txnullskb++;
1300 } 1298 }
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 2d75c710f62a..cec9e04f51ea 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -994,28 +994,6 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
994 return NETDEV_TX_OK; 994 return NETDEV_TX_OK;
995 } 995 }
996 996
997 /*
998 * Everything is set up. Now, we just need to transmit it out.
999 * Note that we have to copy the contents of buffer over to
1000 * right place. Later on, this can be optimized out by de-coupling the
1001 * producer index from the buffer index.
1002 */
1003 retry_getting_window:
1004 spin_lock_bh(&adapter->tx_lock);
1005 if (adapter->total_threads >= MAX_XMIT_PRODUCERS) {
1006 spin_unlock_bh(&adapter->tx_lock);
1007 /*
1008 * Yield CPU
1009 */
1010 if (!in_atomic())
1011 schedule();
1012 else {
1013 for (i = 0; i < 20; i++)
1014 cpu_relax(); /*This a nop instr on i386 */
1015 }
1016 goto retry_getting_window;
1017 }
1018 local_producer = adapter->cmd_producer;
1019 /* There 4 fragments per descriptor */ 997 /* There 4 fragments per descriptor */
1020 no_of_desc = (frag_count + 3) >> 2; 998 no_of_desc = (frag_count + 3) >> 2;
1021 if (netdev->features & NETIF_F_TSO) { 999 if (netdev->features & NETIF_F_TSO) {
@@ -1029,16 +1007,19 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
1029 } 1007 }
1030 } 1008 }
1031 } 1009 }
1010
1011 spin_lock_bh(&adapter->tx_lock);
1012 if (adapter->total_threads >= MAX_XMIT_PRODUCERS) {
1013 goto out_requeue;
1014 }
1015 local_producer = adapter->cmd_producer;
1032 k = adapter->cmd_producer; 1016 k = adapter->cmd_producer;
1033 max_tx_desc_count = adapter->max_tx_desc_count; 1017 max_tx_desc_count = adapter->max_tx_desc_count;
1034 last_cmd_consumer = adapter->last_cmd_consumer; 1018 last_cmd_consumer = adapter->last_cmd_consumer;
1035 if ((k + no_of_desc) >= 1019 if ((k + no_of_desc) >=
1036 ((last_cmd_consumer <= k) ? last_cmd_consumer + max_tx_desc_count : 1020 ((last_cmd_consumer <= k) ? last_cmd_consumer + max_tx_desc_count :
1037 last_cmd_consumer)) { 1021 last_cmd_consumer)) {
1038 netif_stop_queue(netdev); 1022 goto out_requeue;
1039 adapter->flags |= NETXEN_NETDEV_STATUS;
1040 spin_unlock_bh(&adapter->tx_lock);
1041 return NETDEV_TX_BUSY;
1042 } 1023 }
1043 k = get_index_range(k, max_tx_desc_count, no_of_desc); 1024 k = get_index_range(k, max_tx_desc_count, no_of_desc);
1044 adapter->cmd_producer = k; 1025 adapter->cmd_producer = k;
@@ -1091,6 +1072,8 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
1091 adapter->max_tx_desc_count); 1072 adapter->max_tx_desc_count);
1092 hwdesc = &hw->cmd_desc_head[producer]; 1073 hwdesc = &hw->cmd_desc_head[producer];
1093 memset(hwdesc, 0, sizeof(struct cmd_desc_type0)); 1074 memset(hwdesc, 0, sizeof(struct cmd_desc_type0));
1075 pbuf = &adapter->cmd_buf_arr[producer];
1076 pbuf->skb = NULL;
1094 } 1077 }
1095 frag = &skb_shinfo(skb)->frags[i - 1]; 1078 frag = &skb_shinfo(skb)->frags[i - 1];
1096 len = frag->size; 1079 len = frag->size;
@@ -1146,6 +1129,8 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
1146 } 1129 }
1147 /* copy the MAC/IP/TCP headers to the cmd descriptor list */ 1130 /* copy the MAC/IP/TCP headers to the cmd descriptor list */
1148 hwdesc = &hw->cmd_desc_head[producer]; 1131 hwdesc = &hw->cmd_desc_head[producer];
1132 pbuf = &adapter->cmd_buf_arr[producer];
1133 pbuf->skb = NULL;
1149 1134
1150 /* copy the first 64 bytes */ 1135 /* copy the first 64 bytes */
1151 memcpy(((void *)hwdesc) + 2, 1136 memcpy(((void *)hwdesc) + 2,
@@ -1154,6 +1139,8 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
1154 1139
1155 if (more_hdr) { 1140 if (more_hdr) {
1156 hwdesc = &hw->cmd_desc_head[producer]; 1141 hwdesc = &hw->cmd_desc_head[producer];
1142 pbuf = &adapter->cmd_buf_arr[producer];
1143 pbuf->skb = NULL;
1157 /* copy the next 64 bytes - should be enough except 1144 /* copy the next 64 bytes - should be enough except
1158 * for pathological case 1145 * for pathological case
1159 */ 1146 */
@@ -1187,14 +1174,17 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
1187 } 1174 }
1188 1175
1189 adapter->stats.xmitfinished++; 1176 adapter->stats.xmitfinished++;
1190 spin_unlock_bh(&adapter->tx_lock);
1191
1192 netdev->trans_start = jiffies; 1177 netdev->trans_start = jiffies;
1193 1178
1194 DPRINTK(INFO, "wrote CMD producer %x to phantom\n", producer); 1179 spin_unlock_bh(&adapter->tx_lock);
1195
1196 DPRINTK(INFO, "Done. Send\n");
1197 return NETDEV_TX_OK; 1180 return NETDEV_TX_OK;
1181
1182out_requeue:
1183 netif_stop_queue(netdev);
1184 adapter->flags |= NETXEN_NETDEV_STATUS;
1185
1186 spin_unlock_bh(&adapter->tx_lock);
1187 return NETDEV_TX_BUSY;
1198} 1188}
1199 1189
1200static void netxen_watchdog(unsigned long v) 1190static void netxen_watchdog(unsigned long v)