aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDhananjay Phadke <dhananjay@netxen.com>2008-03-17 22:59:49 -0400
committerJeff Garzik <jeff@garzik.org>2008-03-25 23:16:16 -0400
commit05aaa02d799e8e9548d57ac92fcb05e783027341 (patch)
treebecfc839727f798364c13549e332de0830d7676f
parent443be7960be77f3345b44491c700ae4471b0fe57 (diff)
netxen: napi and irq cleanup
o separate and simpler irq handler for msi interrupts, avoids few checks than legacy mode. o avoid redudant tx_has_work() and rx_has_work() checks in interrupt and napi, which can uncork irq based on racy (lockless) access to tx and rx ring indices. If we get interrupt, there's sufficient reason to schedule napi. o replenish rx ring more often, remove self-imposed threshold rcv_free that prevents posting rx desc to card. This improves performance in low memory. Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com> Tested-by: Vernon Mauery <mauery@us.ibm.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r--drivers/net/netxen/netxen_nic.h5
-rw-r--r--drivers/net/netxen/netxen_nic_init.c76
-rw-r--r--drivers/net/netxen/netxen_nic_isr.c17
-rw-r--r--drivers/net/netxen/netxen_nic_main.c113
4 files changed, 48 insertions, 163 deletions
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index 876cd0635f2e..8b6546ccb47b 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -842,7 +842,6 @@ struct netxen_rcv_desc_ctx {
842 u32 flags; 842 u32 flags;
843 u32 producer; 843 u32 producer;
844 u32 rcv_pending; /* Num of bufs posted in phantom */ 844 u32 rcv_pending; /* Num of bufs posted in phantom */
845 u32 rcv_free; /* Num of bufs in free list */
846 dma_addr_t phys_addr; 845 dma_addr_t phys_addr;
847 struct pci_dev *phys_pdev; 846 struct pci_dev *phys_pdev;
848 struct rcv_desc *desc_head; /* address of rx ring in Phantom */ 847 struct rcv_desc *desc_head; /* address of rx ring in Phantom */
@@ -1076,12 +1075,10 @@ void netxen_tso_check(struct netxen_adapter *adapter,
1076 struct cmd_desc_type0 *desc, struct sk_buff *skb); 1075 struct cmd_desc_type0 *desc, struct sk_buff *skb);
1077int netxen_nic_hw_resources(struct netxen_adapter *adapter); 1076int netxen_nic_hw_resources(struct netxen_adapter *adapter);
1078void netxen_nic_clear_stats(struct netxen_adapter *adapter); 1077void netxen_nic_clear_stats(struct netxen_adapter *adapter);
1079int netxen_nic_rx_has_work(struct netxen_adapter *adapter);
1080int netxen_nic_tx_has_work(struct netxen_adapter *adapter);
1081void netxen_watchdog_task(struct work_struct *work); 1078void netxen_watchdog_task(struct work_struct *work);
1082void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, 1079void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx,
1083 u32 ringid); 1080 u32 ringid);
1084int netxen_process_cmd_ring(unsigned long data); 1081int netxen_process_cmd_ring(struct netxen_adapter *adapter);
1085u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctx, int max); 1082u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctx, int max);
1086void netxen_nic_set_multi(struct net_device *netdev); 1083void netxen_nic_set_multi(struct net_device *netdev);
1087int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu); 1084int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu);
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index 43eb1f65152d..64fc18d4afb6 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -185,7 +185,6 @@ void netxen_initialize_adapter_sw(struct netxen_adapter *adapter)
185 for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) { 185 for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
186 struct netxen_rx_buffer *rx_buf; 186 struct netxen_rx_buffer *rx_buf;
187 rcv_desc = &adapter->recv_ctx[ctxid].rcv_desc[ring]; 187 rcv_desc = &adapter->recv_ctx[ctxid].rcv_desc[ring];
188 rcv_desc->rcv_free = rcv_desc->max_rx_desc_count;
189 rcv_desc->begin_alloc = 0; 188 rcv_desc->begin_alloc = 0;
190 rx_buf = rcv_desc->rx_buf_arr; 189 rx_buf = rcv_desc->rx_buf_arr;
191 num_rx_bufs = rcv_desc->max_rx_desc_count; 190 num_rx_bufs = rcv_desc->max_rx_desc_count;
@@ -976,28 +975,6 @@ int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val)
976 return 0; 975 return 0;
977} 976}
978 977
979int netxen_nic_rx_has_work(struct netxen_adapter *adapter)
980{
981 int ctx;
982
983 for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
984 struct netxen_recv_context *recv_ctx =
985 &(adapter->recv_ctx[ctx]);
986 u32 consumer;
987 struct status_desc *desc_head;
988 struct status_desc *desc;
989
990 consumer = recv_ctx->status_rx_consumer;
991 desc_head = recv_ctx->rcv_status_desc_head;
992 desc = &desc_head[consumer];
993
994 if (netxen_get_sts_owner(desc) & STATUS_OWNER_HOST)
995 return 1;
996 }
997
998 return 0;
999}
1000
1001static int netxen_nic_check_temp(struct netxen_adapter *adapter) 978static int netxen_nic_check_temp(struct netxen_adapter *adapter)
1002{ 979{
1003 struct net_device *netdev = adapter->netdev; 980 struct net_device *netdev = adapter->netdev;
@@ -1040,7 +1017,6 @@ static int netxen_nic_check_temp(struct netxen_adapter *adapter)
1040 1017
1041void netxen_watchdog_task(struct work_struct *work) 1018void netxen_watchdog_task(struct work_struct *work)
1042{ 1019{
1043 struct net_device *netdev;
1044 struct netxen_adapter *adapter = 1020 struct netxen_adapter *adapter =
1045 container_of(work, struct netxen_adapter, watchdog_task); 1021 container_of(work, struct netxen_adapter, watchdog_task);
1046 1022
@@ -1050,20 +1026,6 @@ void netxen_watchdog_task(struct work_struct *work)
1050 if (adapter->handle_phy_intr) 1026 if (adapter->handle_phy_intr)
1051 adapter->handle_phy_intr(adapter); 1027 adapter->handle_phy_intr(adapter);
1052 1028
1053 netdev = adapter->netdev;
1054 if ((netif_running(netdev)) && !netif_carrier_ok(netdev) &&
1055 netxen_nic_link_ok(adapter) ) {
1056 printk(KERN_INFO "%s %s (port %d), Link is up\n",
1057 netxen_nic_driver_name, netdev->name, adapter->portnum);
1058 netif_carrier_on(netdev);
1059 netif_wake_queue(netdev);
1060 } else if(!(netif_running(netdev)) && netif_carrier_ok(netdev)) {
1061 printk(KERN_ERR "%s %s Link is Down\n",
1062 netxen_nic_driver_name, netdev->name);
1063 netif_carrier_off(netdev);
1064 netif_stop_queue(netdev);
1065 }
1066
1067 mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); 1029 mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
1068} 1030}
1069 1031
@@ -1177,7 +1139,6 @@ static void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
1177 1139
1178 netdev->last_rx = jiffies; 1140 netdev->last_rx = jiffies;
1179 1141
1180 rcv_desc->rcv_free++;
1181 rcv_desc->rcv_pending--; 1142 rcv_desc->rcv_pending--;
1182 1143
1183 /* 1144 /*
@@ -1202,13 +1163,6 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max)
1202 u32 producer = 0; 1163 u32 producer = 0;
1203 int count = 0, ring; 1164 int count = 0, ring;
1204 1165
1205 DPRINTK(INFO, "procesing receive\n");
1206 /*
1207 * we assume in this case that there is only one port and that is
1208 * port #1...changes need to be done in firmware to indicate port
1209 * number as part of the descriptor. This way we will be able to get
1210 * the netdev which is associated with that device.
1211 */
1212 while (count < max) { 1166 while (count < max) {
1213 desc = &desc_head[consumer]; 1167 desc = &desc_head[consumer];
1214 if (!(netxen_get_sts_owner(desc) & STATUS_OWNER_HOST)) { 1168 if (!(netxen_get_sts_owner(desc) & STATUS_OWNER_HOST)) {
@@ -1221,10 +1175,8 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max)
1221 consumer = (consumer + 1) & (adapter->max_rx_desc_count - 1); 1175 consumer = (consumer + 1) & (adapter->max_rx_desc_count - 1);
1222 count++; 1176 count++;
1223 } 1177 }
1224 if (count) { 1178 for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
1225 for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) { 1179 netxen_post_rx_buffers_nodb(adapter, ctxid, ring);
1226 netxen_post_rx_buffers_nodb(adapter, ctxid, ring);
1227 }
1228 } 1180 }
1229 1181
1230 /* update the consumer index in phantom */ 1182 /* update the consumer index in phantom */
@@ -1235,20 +1187,18 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max)
1235 /* Window = 1 */ 1187 /* Window = 1 */
1236 writel(consumer, 1188 writel(consumer,
1237 NETXEN_CRB_NORMALIZE(adapter, 1189 NETXEN_CRB_NORMALIZE(adapter,
1238 recv_crb_registers[adapter->portnum]. 1190 recv_crb_registers[adapter->portnum].
1239 crb_rcv_status_consumer)); 1191 crb_rcv_status_consumer));
1240 wmb();
1241 } 1192 }
1242 1193
1243 return count; 1194 return count;
1244} 1195}
1245 1196
1246/* Process Command status ring */ 1197/* Process Command status ring */
1247int netxen_process_cmd_ring(unsigned long data) 1198int netxen_process_cmd_ring(struct netxen_adapter *adapter)
1248{ 1199{
1249 u32 last_consumer; 1200 u32 last_consumer;
1250 u32 consumer; 1201 u32 consumer;
1251 struct netxen_adapter *adapter = (struct netxen_adapter *)data;
1252 int count1 = 0; 1202 int count1 = 0;
1253 int count2 = 0; 1203 int count2 = 0;
1254 struct netxen_cmd_buffer *buffer; 1204 struct netxen_cmd_buffer *buffer;
@@ -1435,8 +1385,6 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
1435 rcv_desc->begin_alloc = index; 1385 rcv_desc->begin_alloc = index;
1436 rcv_desc->rcv_pending += count; 1386 rcv_desc->rcv_pending += count;
1437 rcv_desc->producer = producer; 1387 rcv_desc->producer = producer;
1438 if (rcv_desc->rcv_free >= 32) {
1439 rcv_desc->rcv_free = 0;
1440 /* Window = 1 */ 1388 /* Window = 1 */
1441 writel((producer - 1) & 1389 writel((producer - 1) &
1442 (rcv_desc->max_rx_desc_count - 1), 1390 (rcv_desc->max_rx_desc_count - 1),
@@ -1460,8 +1408,6 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
1460 writel(msg, 1408 writel(msg,
1461 DB_NORMALIZE(adapter, 1409 DB_NORMALIZE(adapter,
1462 NETXEN_RCV_PRODUCER_OFFSET)); 1410 NETXEN_RCV_PRODUCER_OFFSET));
1463 wmb();
1464 }
1465 } 1411 }
1466} 1412}
1467 1413
@@ -1525,8 +1471,6 @@ static void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter,
1525 rcv_desc->begin_alloc = index; 1471 rcv_desc->begin_alloc = index;
1526 rcv_desc->rcv_pending += count; 1472 rcv_desc->rcv_pending += count;
1527 rcv_desc->producer = producer; 1473 rcv_desc->producer = producer;
1528 if (rcv_desc->rcv_free >= 32) {
1529 rcv_desc->rcv_free = 0;
1530 /* Window = 1 */ 1474 /* Window = 1 */
1531 writel((producer - 1) & 1475 writel((producer - 1) &
1532 (rcv_desc->max_rx_desc_count - 1), 1476 (rcv_desc->max_rx_desc_count - 1),
@@ -1536,21 +1480,9 @@ static void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter,
1536 rcv_desc_crb[ringid]. 1480 rcv_desc_crb[ringid].
1537 crb_rcv_producer_offset)); 1481 crb_rcv_producer_offset));
1538 wmb(); 1482 wmb();
1539 }
1540 } 1483 }
1541} 1484}
1542 1485
1543int netxen_nic_tx_has_work(struct netxen_adapter *adapter)
1544{
1545 if (find_diff_among(adapter->last_cmd_consumer,
1546 adapter->cmd_producer,
1547 adapter->max_tx_desc_count) > 0)
1548 return 1;
1549
1550 return 0;
1551}
1552
1553
1554void netxen_nic_clear_stats(struct netxen_adapter *adapter) 1486void netxen_nic_clear_stats(struct netxen_adapter *adapter)
1555{ 1487{
1556 memset(&adapter->stats, 0, sizeof(adapter->stats)); 1488 memset(&adapter->stats, 0, sizeof(adapter->stats));
diff --git a/drivers/net/netxen/netxen_nic_isr.c b/drivers/net/netxen/netxen_nic_isr.c
index 48a404aa66ce..1a2333a52b5d 100644
--- a/drivers/net/netxen/netxen_nic_isr.c
+++ b/drivers/net/netxen/netxen_nic_isr.c
@@ -193,14 +193,14 @@ int netxen_nic_link_ok(struct netxen_adapter *adapter)
193void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter) 193void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter)
194{ 194{
195 struct net_device *netdev = adapter->netdev; 195 struct net_device *netdev = adapter->netdev;
196 u32 val, val1; 196 u32 val;
197 197
198 /* WINDOW = 1 */ 198 /* WINDOW = 1 */
199 val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE)); 199 val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE));
200 val >>= (physical_port[adapter->portnum] * 8); 200 val >>= (physical_port[adapter->portnum] * 8);
201 val1 = val & 0xff; 201 val &= 0xff;
202 202
203 if (adapter->ahw.xg_linkup == 1 && val1 != XG_LINK_UP) { 203 if (adapter->ahw.xg_linkup == 1 && val != XG_LINK_UP) {
204 printk(KERN_INFO "%s: %s NIC Link is down\n", 204 printk(KERN_INFO "%s: %s NIC Link is down\n",
205 netxen_nic_driver_name, netdev->name); 205 netxen_nic_driver_name, netdev->name);
206 adapter->ahw.xg_linkup = 0; 206 adapter->ahw.xg_linkup = 0;
@@ -208,16 +208,7 @@ void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter)
208 netif_carrier_off(netdev); 208 netif_carrier_off(netdev);
209 netif_stop_queue(netdev); 209 netif_stop_queue(netdev);
210 } 210 }
211 /* read twice to clear sticky bits */ 211 } else if (adapter->ahw.xg_linkup == 0 && val == XG_LINK_UP) {
212 /* WINDOW = 0 */
213 netxen_nic_read_w0(adapter, NETXEN_NIU_XG_STATUS, &val1);
214 netxen_nic_read_w0(adapter, NETXEN_NIU_XG_STATUS, &val1);
215
216 if ((val & 0xffb) != 0xffb) {
217 printk(KERN_INFO "%s ISR: Sync/Align BAD: 0x%08x\n",
218 netxen_nic_driver_name, val1);
219 }
220 } else if (adapter->ahw.xg_linkup == 0 && val1 == XG_LINK_UP) {
221 printk(KERN_INFO "%s: %s NIC Link is up\n", 212 printk(KERN_INFO "%s: %s NIC Link is up\n",
222 netxen_nic_driver_name, netdev->name); 213 netxen_nic_driver_name, netdev->name);
223 adapter->ahw.xg_linkup = 1; 214 adapter->ahw.xg_linkup = 1;
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index cd665da85c7f..95955204ef59 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -63,12 +63,12 @@ static int netxen_nic_xmit_frame(struct sk_buff *, struct net_device *);
63static void netxen_tx_timeout(struct net_device *netdev); 63static void netxen_tx_timeout(struct net_device *netdev);
64static void netxen_tx_timeout_task(struct work_struct *work); 64static void netxen_tx_timeout_task(struct work_struct *work);
65static void netxen_watchdog(unsigned long); 65static void netxen_watchdog(unsigned long);
66static int netxen_handle_int(struct netxen_adapter *, struct net_device *);
67static int netxen_nic_poll(struct napi_struct *napi, int budget); 66static int netxen_nic_poll(struct napi_struct *napi, int budget);
68#ifdef CONFIG_NET_POLL_CONTROLLER 67#ifdef CONFIG_NET_POLL_CONTROLLER
69static void netxen_nic_poll_controller(struct net_device *netdev); 68static void netxen_nic_poll_controller(struct net_device *netdev);
70#endif 69#endif
71static irqreturn_t netxen_intr(int irq, void *data); 70static irqreturn_t netxen_intr(int irq, void *data);
71static irqreturn_t netxen_msi_intr(int irq, void *data);
72 72
73int physical_port[] = {0, 1, 2, 3}; 73int physical_port[] = {0, 1, 2, 3};
74 74
@@ -405,7 +405,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
405 netdev->set_mac_address = netxen_nic_set_mac; 405 netdev->set_mac_address = netxen_nic_set_mac;
406 netdev->change_mtu = netxen_nic_change_mtu; 406 netdev->change_mtu = netxen_nic_change_mtu;
407 netdev->tx_timeout = netxen_tx_timeout; 407 netdev->tx_timeout = netxen_tx_timeout;
408 netdev->watchdog_timeo = HZ; 408 netdev->watchdog_timeo = 2*HZ;
409 409
410 netxen_nic_change_mtu(netdev, netdev->mtu); 410 netxen_nic_change_mtu(netdev, netdev->mtu);
411 411
@@ -823,6 +823,8 @@ static int netxen_nic_open(struct net_device *netdev)
823 struct netxen_adapter *adapter = (struct netxen_adapter *)netdev->priv; 823 struct netxen_adapter *adapter = (struct netxen_adapter *)netdev->priv;
824 int err = 0; 824 int err = 0;
825 int ctx, ring; 825 int ctx, ring;
826 irq_handler_t handler;
827 unsigned long flags = IRQF_SAMPLE_RANDOM;
826 828
827 if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) { 829 if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) {
828 err = netxen_init_firmware(adapter); 830 err = netxen_init_firmware(adapter);
@@ -846,9 +848,14 @@ static int netxen_nic_open(struct net_device *netdev)
846 netxen_post_rx_buffers(adapter, ctx, ring); 848 netxen_post_rx_buffers(adapter, ctx, ring);
847 } 849 }
848 adapter->irq = adapter->ahw.pdev->irq; 850 adapter->irq = adapter->ahw.pdev->irq;
849 err = request_irq(adapter->ahw.pdev->irq, netxen_intr, 851 if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
850 IRQF_SHARED|IRQF_SAMPLE_RANDOM, netdev->name, 852 handler = netxen_msi_intr;
851 adapter); 853 else {
854 flags |= IRQF_SHARED;
855 handler = netxen_intr;
856 }
857 err = request_irq(adapter->irq, handler,
858 flags, netdev->name, adapter);
852 if (err) { 859 if (err) {
853 printk(KERN_ERR "request_irq failed with: %d\n", err); 860 printk(KERN_ERR "request_irq failed with: %d\n", err);
854 netxen_free_hw_resources(adapter); 861 netxen_free_hw_resources(adapter);
@@ -857,21 +864,12 @@ static int netxen_nic_open(struct net_device *netdev)
857 864
858 adapter->is_up = NETXEN_ADAPTER_UP_MAGIC; 865 adapter->is_up = NETXEN_ADAPTER_UP_MAGIC;
859 } 866 }
860 if (!adapter->driver_mismatch)
861 mod_timer(&adapter->watchdog_timer, jiffies);
862
863 napi_enable(&adapter->napi);
864
865 netxen_nic_enable_int(adapter);
866
867 /* Done here again so that even if phantom sw overwrote it, 867 /* Done here again so that even if phantom sw overwrote it,
868 * we set it */ 868 * we set it */
869 if (adapter->init_port 869 if (adapter->init_port
870 && adapter->init_port(adapter, adapter->portnum) != 0) { 870 && adapter->init_port(adapter, adapter->portnum) != 0) {
871 del_timer_sync(&adapter->watchdog_timer);
872 printk(KERN_ERR "%s: Failed to initialize port %d\n", 871 printk(KERN_ERR "%s: Failed to initialize port %d\n",
873 netxen_nic_driver_name, adapter->portnum); 872 netxen_nic_driver_name, adapter->portnum);
874 napi_disable(&adapter->napi);
875 return -EIO; 873 return -EIO;
876 } 874 }
877 if (adapter->macaddr_set) 875 if (adapter->macaddr_set)
@@ -884,6 +882,12 @@ static int netxen_nic_open(struct net_device *netdev)
884 adapter->set_mtu(adapter, netdev->mtu); 882 adapter->set_mtu(adapter, netdev->mtu);
885 883
886 if (!adapter->driver_mismatch) 884 if (!adapter->driver_mismatch)
885 mod_timer(&adapter->watchdog_timer, jiffies);
886
887 napi_enable(&adapter->napi);
888 netxen_nic_enable_int(adapter);
889
890 if (!adapter->driver_mismatch)
887 netif_start_queue(netdev); 891 netif_start_queue(netdev);
888 892
889 return 0; 893 return 0;
@@ -1196,81 +1200,50 @@ static void netxen_tx_timeout_task(struct work_struct *work)
1196 netif_wake_queue(adapter->netdev); 1200 netif_wake_queue(adapter->netdev);
1197} 1201}
1198 1202
1199static int 1203static inline void
1200netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev) 1204netxen_handle_int(struct netxen_adapter *adapter)
1201{ 1205{
1202 u32 ret = 0;
1203
1204 DPRINTK(INFO, "Entered handle ISR\n");
1205 adapter->stats.ints++;
1206
1207 netxen_nic_disable_int(adapter); 1206 netxen_nic_disable_int(adapter);
1208 1207 napi_schedule(&adapter->napi);
1209 if (netxen_nic_rx_has_work(adapter) || netxen_nic_tx_has_work(adapter)) {
1210 if (netif_rx_schedule_prep(netdev, &adapter->napi)) {
1211 /*
1212 * Interrupts are already disabled.
1213 */
1214 __netif_rx_schedule(netdev, &adapter->napi);
1215 } else {
1216 static unsigned int intcount = 0;
1217 if ((++intcount & 0xfff) == 0xfff)
1218 DPRINTK(KERN_ERR
1219 "%s: %s interrupt %d while in poll\n",
1220 netxen_nic_driver_name, netdev->name,
1221 intcount);
1222 }
1223 ret = 1;
1224 }
1225
1226 if (ret == 0) {
1227 netxen_nic_enable_int(adapter);
1228 }
1229
1230 return ret;
1231} 1208}
1232 1209
1233/*
1234 * netxen_intr - Interrupt Handler
1235 * @irq: interrupt number
1236 * data points to adapter stucture (which may be handling more than 1 port
1237 */
1238irqreturn_t netxen_intr(int irq, void *data) 1210irqreturn_t netxen_intr(int irq, void *data)
1239{ 1211{
1240 struct netxen_adapter *adapter = data; 1212 struct netxen_adapter *adapter = data;
1241 struct net_device *netdev = adapter->netdev;
1242 u32 our_int = 0; 1213 u32 our_int = 0;
1243 1214
1244 if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { 1215 our_int = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
1245 our_int = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR)); 1216 /* not our interrupt */
1246 /* not our interrupt */ 1217 if ((our_int & (0x80 << adapter->portnum)) == 0)
1247 if ((our_int & (0x80 << adapter->portnum)) == 0) 1218 return IRQ_NONE;
1248 return IRQ_NONE;
1249 }
1250 1219
1251 if (adapter->intr_scheme == INTR_SCHEME_PERPORT) { 1220 if (adapter->intr_scheme == INTR_SCHEME_PERPORT) {
1252 /* claim interrupt */ 1221 /* claim interrupt */
1253 if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { 1222 writel(our_int & ~((u32)(0x80 << adapter->portnum)),
1254 writel(our_int & ~((u32)(0x80 << adapter->portnum)),
1255 NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR)); 1223 NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
1256 }
1257 } 1224 }
1258 1225
1259 if (netif_running(netdev)) 1226 netxen_handle_int(adapter);
1260 netxen_handle_int(adapter, netdev);
1261 1227
1262 return IRQ_HANDLED; 1228 return IRQ_HANDLED;
1263} 1229}
1264 1230
1231irqreturn_t netxen_msi_intr(int irq, void *data)
1232{
1233 struct netxen_adapter *adapter = data;
1234
1235 netxen_handle_int(adapter);
1236 return IRQ_HANDLED;
1237}
1238
1265static int netxen_nic_poll(struct napi_struct *napi, int budget) 1239static int netxen_nic_poll(struct napi_struct *napi, int budget)
1266{ 1240{
1267 struct netxen_adapter *adapter = container_of(napi, struct netxen_adapter, napi); 1241 struct netxen_adapter *adapter = container_of(napi, struct netxen_adapter, napi);
1268 struct net_device *netdev = adapter->netdev; 1242 int tx_complete;
1269 int done = 1;
1270 int ctx; 1243 int ctx;
1271 int work_done; 1244 int work_done;
1272 1245
1273 DPRINTK(INFO, "polling for %d descriptors\n", *budget); 1246 tx_complete = netxen_process_cmd_ring(adapter);
1274 1247
1275 work_done = 0; 1248 work_done = 0;
1276 for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { 1249 for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
@@ -1290,16 +1263,8 @@ static int netxen_nic_poll(struct napi_struct *napi, int budget)
1290 budget / MAX_RCV_CTX); 1263 budget / MAX_RCV_CTX);
1291 } 1264 }
1292 1265
1293 if (work_done >= budget) 1266 if ((work_done < budget) && tx_complete) {
1294 done = 0; 1267 netif_rx_complete(adapter->netdev, &adapter->napi);
1295
1296 if (netxen_process_cmd_ring((unsigned long)adapter) == 0)
1297 done = 0;
1298
1299 DPRINTK(INFO, "new work_done: %d work_to_do: %d\n",
1300 work_done, work_to_do);
1301 if (done) {
1302 netif_rx_complete(netdev, napi);
1303 netxen_nic_enable_int(adapter); 1268 netxen_nic_enable_int(adapter);
1304 } 1269 }
1305 1270