diff options
author | dhananjay@netxen.com <dhananjay@netxen.com> | 2007-12-26 13:23:58 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2008-01-12 17:35:38 -0500 |
commit | 53a01e00f8c78bc5875e09aca7749ea54bb09798 (patch) | |
tree | 00e5edaaf2d51d406bea63afd26dc41748c193f2 | |
parent | 72b0a7a8a40a50cf2eab42fd6a56e04b05090434 (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>
-rw-r--r-- | drivers/net/netxen/netxen_nic_init.c | 10 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_main.c | 52 |
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 | |||
1182 | out_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 | ||
1200 | static void netxen_watchdog(unsigned long v) | 1190 | static void netxen_watchdog(unsigned long v) |