diff options
author | Dhananjay Phadke <dhananjay@netxen.com> | 2008-03-17 22:59:49 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2008-03-25 23:16:16 -0400 |
commit | 05aaa02d799e8e9548d57ac92fcb05e783027341 (patch) | |
tree | becfc839727f798364c13549e332de0830d7676f /drivers/net | |
parent | 443be7960be77f3345b44491c700ae4471b0fe57 (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>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/netxen/netxen_nic.h | 5 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_init.c | 76 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_isr.c | 17 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_main.c | 113 |
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); |
1077 | int netxen_nic_hw_resources(struct netxen_adapter *adapter); | 1076 | int netxen_nic_hw_resources(struct netxen_adapter *adapter); |
1078 | void netxen_nic_clear_stats(struct netxen_adapter *adapter); | 1077 | void netxen_nic_clear_stats(struct netxen_adapter *adapter); |
1079 | int netxen_nic_rx_has_work(struct netxen_adapter *adapter); | ||
1080 | int netxen_nic_tx_has_work(struct netxen_adapter *adapter); | ||
1081 | void netxen_watchdog_task(struct work_struct *work); | 1078 | void netxen_watchdog_task(struct work_struct *work); |
1082 | void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, | 1079 | void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, |
1083 | u32 ringid); | 1080 | u32 ringid); |
1084 | int netxen_process_cmd_ring(unsigned long data); | 1081 | int netxen_process_cmd_ring(struct netxen_adapter *adapter); |
1085 | u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctx, int max); | 1082 | u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctx, int max); |
1086 | void netxen_nic_set_multi(struct net_device *netdev); | 1083 | void netxen_nic_set_multi(struct net_device *netdev); |
1087 | int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu); | 1084 | int 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 | ||
979 | int 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 | |||
1001 | static int netxen_nic_check_temp(struct netxen_adapter *adapter) | 978 | static 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 | ||
1041 | void netxen_watchdog_task(struct work_struct *work) | 1018 | void 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 */ |
1247 | int netxen_process_cmd_ring(unsigned long data) | 1198 | int 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 | ||
1543 | int 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 | |||
1554 | void netxen_nic_clear_stats(struct netxen_adapter *adapter) | 1486 | void 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) | |||
193 | void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter) | 193 | void 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 *); | |||
63 | static void netxen_tx_timeout(struct net_device *netdev); | 63 | static void netxen_tx_timeout(struct net_device *netdev); |
64 | static void netxen_tx_timeout_task(struct work_struct *work); | 64 | static void netxen_tx_timeout_task(struct work_struct *work); |
65 | static void netxen_watchdog(unsigned long); | 65 | static void netxen_watchdog(unsigned long); |
66 | static int netxen_handle_int(struct netxen_adapter *, struct net_device *); | ||
67 | static int netxen_nic_poll(struct napi_struct *napi, int budget); | 66 | static int netxen_nic_poll(struct napi_struct *napi, int budget); |
68 | #ifdef CONFIG_NET_POLL_CONTROLLER | 67 | #ifdef CONFIG_NET_POLL_CONTROLLER |
69 | static void netxen_nic_poll_controller(struct net_device *netdev); | 68 | static void netxen_nic_poll_controller(struct net_device *netdev); |
70 | #endif | 69 | #endif |
71 | static irqreturn_t netxen_intr(int irq, void *data); | 70 | static irqreturn_t netxen_intr(int irq, void *data); |
71 | static irqreturn_t netxen_msi_intr(int irq, void *data); | ||
72 | 72 | ||
73 | int physical_port[] = {0, 1, 2, 3}; | 73 | int 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 | ||
1199 | static int | 1203 | static inline void |
1200 | netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev) | 1204 | netxen_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 | */ | ||
1238 | irqreturn_t netxen_intr(int irq, void *data) | 1210 | irqreturn_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 | ||
1231 | irqreturn_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 | |||
1265 | static int netxen_nic_poll(struct napi_struct *napi, int budget) | 1239 | static 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 | ||