diff options
Diffstat (limited to 'drivers/net/netxen/netxen_nic_main.c')
-rw-r--r-- | drivers/net/netxen/netxen_nic_main.c | 265 |
1 files changed, 84 insertions, 181 deletions
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 9737eae5ef11..a8fb439a4d03 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 | ||
@@ -149,33 +149,30 @@ static void netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter, | |||
149 | 149 | ||
150 | #define ADAPTER_LIST_SIZE 12 | 150 | #define ADAPTER_LIST_SIZE 12 |
151 | 151 | ||
152 | static uint32_t msi_tgt_status[4] = { | ||
153 | ISR_INT_TARGET_STATUS, ISR_INT_TARGET_STATUS_F1, | ||
154 | ISR_INT_TARGET_STATUS_F2, ISR_INT_TARGET_STATUS_F3 | ||
155 | }; | ||
156 | |||
157 | static uint32_t sw_int_mask[4] = { | ||
158 | CRB_SW_INT_MASK_0, CRB_SW_INT_MASK_1, | ||
159 | CRB_SW_INT_MASK_2, CRB_SW_INT_MASK_3 | ||
160 | }; | ||
161 | |||
152 | static void netxen_nic_disable_int(struct netxen_adapter *adapter) | 162 | static void netxen_nic_disable_int(struct netxen_adapter *adapter) |
153 | { | 163 | { |
154 | uint32_t mask = 0x7ff; | 164 | u32 mask = 0x7ff; |
155 | int retries = 32; | 165 | int retries = 32; |
166 | int port = adapter->portnum; | ||
167 | int pci_fn = adapter->ahw.pci_func; | ||
156 | 168 | ||
157 | DPRINTK(1, INFO, "Entered ISR Disable \n"); | 169 | if (adapter->msi_mode != MSI_MODE_MULTIFUNC) |
158 | 170 | writel(0x0, NETXEN_CRB_NORMALIZE(adapter, sw_int_mask[port])); | |
159 | switch (adapter->portnum) { | ||
160 | case 0: | ||
161 | writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_0)); | ||
162 | break; | ||
163 | case 1: | ||
164 | writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_1)); | ||
165 | break; | ||
166 | case 2: | ||
167 | writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_2)); | ||
168 | break; | ||
169 | case 3: | ||
170 | writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_3)); | ||
171 | break; | ||
172 | } | ||
173 | 171 | ||
174 | if (adapter->intr_scheme != -1 && | 172 | if (adapter->intr_scheme != -1 && |
175 | adapter->intr_scheme != INTR_SCHEME_PERPORT) | 173 | adapter->intr_scheme != INTR_SCHEME_PERPORT) |
176 | writel(mask,PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK)); | 174 | writel(mask,PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK)); |
177 | 175 | ||
178 | /* Window = 0 or 1 */ | ||
179 | if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { | 176 | if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { |
180 | do { | 177 | do { |
181 | writel(0xffffffff, | 178 | writel(0xffffffff, |
@@ -190,14 +187,18 @@ static void netxen_nic_disable_int(struct netxen_adapter *adapter) | |||
190 | printk(KERN_NOTICE "%s: Failed to disable interrupt completely\n", | 187 | printk(KERN_NOTICE "%s: Failed to disable interrupt completely\n", |
191 | netxen_nic_driver_name); | 188 | netxen_nic_driver_name); |
192 | } | 189 | } |
190 | } else { | ||
191 | if (adapter->msi_mode == MSI_MODE_MULTIFUNC) { | ||
192 | writel(0xffffffff, PCI_OFFSET_SECOND_RANGE(adapter, | ||
193 | msi_tgt_status[pci_fn])); | ||
194 | } | ||
193 | } | 195 | } |
194 | |||
195 | DPRINTK(1, INFO, "Done with Disable Int\n"); | ||
196 | } | 196 | } |
197 | 197 | ||
198 | static void netxen_nic_enable_int(struct netxen_adapter *adapter) | 198 | static void netxen_nic_enable_int(struct netxen_adapter *adapter) |
199 | { | 199 | { |
200 | u32 mask; | 200 | u32 mask; |
201 | int port = adapter->portnum; | ||
201 | 202 | ||
202 | DPRINTK(1, INFO, "Entered ISR Enable \n"); | 203 | DPRINTK(1, INFO, "Entered ISR Enable \n"); |
203 | 204 | ||
@@ -218,20 +219,7 @@ static void netxen_nic_enable_int(struct netxen_adapter *adapter) | |||
218 | writel(mask, PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK)); | 219 | writel(mask, PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK)); |
219 | } | 220 | } |
220 | 221 | ||
221 | switch (adapter->portnum) { | 222 | writel(0x1, NETXEN_CRB_NORMALIZE(adapter, sw_int_mask[port])); |
222 | case 0: | ||
223 | writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_0)); | ||
224 | break; | ||
225 | case 1: | ||
226 | writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_1)); | ||
227 | break; | ||
228 | case 2: | ||
229 | writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_2)); | ||
230 | break; | ||
231 | case 3: | ||
232 | writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_3)); | ||
233 | break; | ||
234 | } | ||
235 | 223 | ||
236 | if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { | 224 | if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { |
237 | mask = 0xbff; | 225 | mask = 0xbff; |
@@ -328,7 +316,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
328 | 316 | ||
329 | adapter->ahw.pdev = pdev; | 317 | adapter->ahw.pdev = pdev; |
330 | adapter->ahw.pci_func = pci_func_id; | 318 | adapter->ahw.pci_func = pci_func_id; |
331 | spin_lock_init(&adapter->tx_lock); | ||
332 | 319 | ||
333 | /* remap phys address */ | 320 | /* remap phys address */ |
334 | mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */ | 321 | mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */ |
@@ -401,6 +388,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
401 | 388 | ||
402 | /* this will be read from FW later */ | 389 | /* this will be read from FW later */ |
403 | adapter->intr_scheme = -1; | 390 | adapter->intr_scheme = -1; |
391 | adapter->msi_mode = -1; | ||
404 | 392 | ||
405 | /* This will be reset for mezz cards */ | 393 | /* This will be reset for mezz cards */ |
406 | adapter->portnum = pci_func_id; | 394 | adapter->portnum = pci_func_id; |
@@ -415,7 +403,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
415 | netdev->set_mac_address = netxen_nic_set_mac; | 403 | netdev->set_mac_address = netxen_nic_set_mac; |
416 | netdev->change_mtu = netxen_nic_change_mtu; | 404 | netdev->change_mtu = netxen_nic_change_mtu; |
417 | netdev->tx_timeout = netxen_tx_timeout; | 405 | netdev->tx_timeout = netxen_tx_timeout; |
418 | netdev->watchdog_timeo = HZ; | 406 | netdev->watchdog_timeo = 2*HZ; |
419 | 407 | ||
420 | netxen_nic_change_mtu(netdev, netdev->mtu); | 408 | netxen_nic_change_mtu(netdev, netdev->mtu); |
421 | 409 | ||
@@ -543,7 +531,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
543 | adapter->watchdog_timer.data = (unsigned long)adapter; | 531 | adapter->watchdog_timer.data = (unsigned long)adapter; |
544 | INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task); | 532 | INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task); |
545 | adapter->ahw.pdev = pdev; | 533 | adapter->ahw.pdev = pdev; |
546 | adapter->proc_cmd_buf_counter = 0; | ||
547 | adapter->ahw.revision_id = pdev->revision; | 534 | adapter->ahw.revision_id = pdev->revision; |
548 | 535 | ||
549 | /* make sure Window == 1 */ | 536 | /* make sure Window == 1 */ |
@@ -833,6 +820,8 @@ static int netxen_nic_open(struct net_device *netdev) | |||
833 | struct netxen_adapter *adapter = (struct netxen_adapter *)netdev->priv; | 820 | struct netxen_adapter *adapter = (struct netxen_adapter *)netdev->priv; |
834 | int err = 0; | 821 | int err = 0; |
835 | int ctx, ring; | 822 | int ctx, ring; |
823 | irq_handler_t handler; | ||
824 | unsigned long flags = IRQF_SAMPLE_RANDOM; | ||
836 | 825 | ||
837 | if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) { | 826 | if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) { |
838 | err = netxen_init_firmware(adapter); | 827 | err = netxen_init_firmware(adapter); |
@@ -856,9 +845,14 @@ static int netxen_nic_open(struct net_device *netdev) | |||
856 | netxen_post_rx_buffers(adapter, ctx, ring); | 845 | netxen_post_rx_buffers(adapter, ctx, ring); |
857 | } | 846 | } |
858 | adapter->irq = adapter->ahw.pdev->irq; | 847 | adapter->irq = adapter->ahw.pdev->irq; |
859 | err = request_irq(adapter->ahw.pdev->irq, netxen_intr, | 848 | if (adapter->flags & NETXEN_NIC_MSI_ENABLED) |
860 | IRQF_SHARED|IRQF_SAMPLE_RANDOM, netdev->name, | 849 | handler = netxen_msi_intr; |
861 | adapter); | 850 | else { |
851 | flags |= IRQF_SHARED; | ||
852 | handler = netxen_intr; | ||
853 | } | ||
854 | err = request_irq(adapter->irq, handler, | ||
855 | flags, netdev->name, adapter); | ||
862 | if (err) { | 856 | if (err) { |
863 | printk(KERN_ERR "request_irq failed with: %d\n", err); | 857 | printk(KERN_ERR "request_irq failed with: %d\n", err); |
864 | netxen_free_hw_resources(adapter); | 858 | netxen_free_hw_resources(adapter); |
@@ -867,21 +861,12 @@ static int netxen_nic_open(struct net_device *netdev) | |||
867 | 861 | ||
868 | adapter->is_up = NETXEN_ADAPTER_UP_MAGIC; | 862 | adapter->is_up = NETXEN_ADAPTER_UP_MAGIC; |
869 | } | 863 | } |
870 | if (!adapter->driver_mismatch) | ||
871 | mod_timer(&adapter->watchdog_timer, jiffies); | ||
872 | |||
873 | napi_enable(&adapter->napi); | ||
874 | |||
875 | netxen_nic_enable_int(adapter); | ||
876 | |||
877 | /* Done here again so that even if phantom sw overwrote it, | 864 | /* Done here again so that even if phantom sw overwrote it, |
878 | * we set it */ | 865 | * we set it */ |
879 | if (adapter->init_port | 866 | if (adapter->init_port |
880 | && adapter->init_port(adapter, adapter->portnum) != 0) { | 867 | && adapter->init_port(adapter, adapter->portnum) != 0) { |
881 | del_timer_sync(&adapter->watchdog_timer); | ||
882 | printk(KERN_ERR "%s: Failed to initialize port %d\n", | 868 | printk(KERN_ERR "%s: Failed to initialize port %d\n", |
883 | netxen_nic_driver_name, adapter->portnum); | 869 | netxen_nic_driver_name, adapter->portnum); |
884 | napi_disable(&adapter->napi); | ||
885 | return -EIO; | 870 | return -EIO; |
886 | } | 871 | } |
887 | if (adapter->macaddr_set) | 872 | if (adapter->macaddr_set) |
@@ -894,6 +879,12 @@ static int netxen_nic_open(struct net_device *netdev) | |||
894 | adapter->set_mtu(adapter, netdev->mtu); | 879 | adapter->set_mtu(adapter, netdev->mtu); |
895 | 880 | ||
896 | if (!adapter->driver_mismatch) | 881 | if (!adapter->driver_mismatch) |
882 | mod_timer(&adapter->watchdog_timer, jiffies); | ||
883 | |||
884 | napi_enable(&adapter->napi); | ||
885 | netxen_nic_enable_int(adapter); | ||
886 | |||
887 | if (!adapter->driver_mismatch) | ||
897 | netif_start_queue(netdev); | 888 | netif_start_queue(netdev); |
898 | 889 | ||
899 | return 0; | 890 | return 0; |
@@ -958,41 +949,17 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
958 | struct netxen_skb_frag *buffrag; | 949 | struct netxen_skb_frag *buffrag; |
959 | unsigned int i; | 950 | unsigned int i; |
960 | 951 | ||
961 | u32 producer = 0; | 952 | u32 producer, consumer; |
962 | u32 saved_producer = 0; | 953 | u32 saved_producer = 0; |
963 | struct cmd_desc_type0 *hwdesc; | 954 | struct cmd_desc_type0 *hwdesc; |
964 | int k; | 955 | int k; |
965 | struct netxen_cmd_buffer *pbuf = NULL; | 956 | struct netxen_cmd_buffer *pbuf = NULL; |
966 | static int dropped_packet = 0; | ||
967 | int frag_count; | 957 | int frag_count; |
968 | u32 local_producer = 0; | ||
969 | u32 max_tx_desc_count = 0; | ||
970 | u32 last_cmd_consumer = 0; | ||
971 | int no_of_desc; | 958 | int no_of_desc; |
959 | u32 num_txd = adapter->max_tx_desc_count; | ||
972 | 960 | ||
973 | adapter->stats.xmitcalled++; | ||
974 | frag_count = skb_shinfo(skb)->nr_frags + 1; | 961 | frag_count = skb_shinfo(skb)->nr_frags + 1; |
975 | 962 | ||
976 | if (unlikely(skb->len <= 0)) { | ||
977 | dev_kfree_skb_any(skb); | ||
978 | adapter->stats.badskblen++; | ||
979 | return NETDEV_TX_OK; | ||
980 | } | ||
981 | |||
982 | if (frag_count > MAX_BUFFERS_PER_CMD) { | ||
983 | printk("%s: %s netxen_nic_xmit_frame: frag_count (%d) " | ||
984 | "too large, can handle only %d frags\n", | ||
985 | netxen_nic_driver_name, netdev->name, | ||
986 | frag_count, MAX_BUFFERS_PER_CMD); | ||
987 | adapter->stats.txdropped++; | ||
988 | if ((++dropped_packet & 0xff) == 0xff) | ||
989 | printk("%s: %s droppped packets = %d\n", | ||
990 | netxen_nic_driver_name, netdev->name, | ||
991 | dropped_packet); | ||
992 | |||
993 | return NETDEV_TX_OK; | ||
994 | } | ||
995 | |||
996 | /* There 4 fragments per descriptor */ | 963 | /* There 4 fragments per descriptor */ |
997 | no_of_desc = (frag_count + 3) >> 2; | 964 | no_of_desc = (frag_count + 3) >> 2; |
998 | if (netdev->features & NETIF_F_TSO) { | 965 | if (netdev->features & NETIF_F_TSO) { |
@@ -1007,27 +974,16 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
1007 | } | 974 | } |
1008 | } | 975 | } |
1009 | 976 | ||
1010 | spin_lock_bh(&adapter->tx_lock); | 977 | producer = adapter->cmd_producer; |
1011 | if (adapter->total_threads >= MAX_XMIT_PRODUCERS) { | 978 | smp_mb(); |
1012 | goto out_requeue; | 979 | consumer = adapter->last_cmd_consumer; |
1013 | } | 980 | if ((no_of_desc+2) > find_diff_among(producer, consumer, num_txd)) { |
1014 | local_producer = adapter->cmd_producer; | 981 | netif_stop_queue(netdev); |
1015 | k = adapter->cmd_producer; | 982 | smp_mb(); |
1016 | max_tx_desc_count = adapter->max_tx_desc_count; | 983 | return NETDEV_TX_BUSY; |
1017 | last_cmd_consumer = adapter->last_cmd_consumer; | ||
1018 | if ((k + no_of_desc) >= | ||
1019 | ((last_cmd_consumer <= k) ? last_cmd_consumer + max_tx_desc_count : | ||
1020 | last_cmd_consumer)) { | ||
1021 | goto out_requeue; | ||
1022 | } | 984 | } |
1023 | k = get_index_range(k, max_tx_desc_count, no_of_desc); | ||
1024 | adapter->cmd_producer = k; | ||
1025 | adapter->total_threads++; | ||
1026 | adapter->num_threads++; | ||
1027 | 985 | ||
1028 | spin_unlock_bh(&adapter->tx_lock); | ||
1029 | /* Copy the descriptors into the hardware */ | 986 | /* Copy the descriptors into the hardware */ |
1030 | producer = local_producer; | ||
1031 | saved_producer = producer; | 987 | saved_producer = producer; |
1032 | hwdesc = &hw->cmd_desc_head[producer]; | 988 | hwdesc = &hw->cmd_desc_head[producer]; |
1033 | memset(hwdesc, 0, sizeof(struct cmd_desc_type0)); | 989 | memset(hwdesc, 0, sizeof(struct cmd_desc_type0)); |
@@ -1067,8 +1023,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
1067 | /* move to next desc. if there is a need */ | 1023 | /* move to next desc. if there is a need */ |
1068 | if ((i & 0x3) == 0) { | 1024 | if ((i & 0x3) == 0) { |
1069 | k = 0; | 1025 | k = 0; |
1070 | producer = get_next_index(producer, | 1026 | producer = get_next_index(producer, num_txd); |
1071 | adapter->max_tx_desc_count); | ||
1072 | hwdesc = &hw->cmd_desc_head[producer]; | 1027 | hwdesc = &hw->cmd_desc_head[producer]; |
1073 | memset(hwdesc, 0, sizeof(struct cmd_desc_type0)); | 1028 | memset(hwdesc, 0, sizeof(struct cmd_desc_type0)); |
1074 | pbuf = &adapter->cmd_buf_arr[producer]; | 1029 | pbuf = &adapter->cmd_buf_arr[producer]; |
@@ -1086,7 +1041,6 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
1086 | buffrag->dma = temp_dma; | 1041 | buffrag->dma = temp_dma; |
1087 | buffrag->length = temp_len; | 1042 | buffrag->length = temp_len; |
1088 | 1043 | ||
1089 | DPRINTK(INFO, "for loop. i=%d k=%d\n", i, k); | ||
1090 | switch (k) { | 1044 | switch (k) { |
1091 | case 0: | 1045 | case 0: |
1092 | hwdesc->buffer1_length = cpu_to_le16(temp_len); | 1046 | hwdesc->buffer1_length = cpu_to_le16(temp_len); |
@@ -1107,7 +1061,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
1107 | } | 1061 | } |
1108 | frag++; | 1062 | frag++; |
1109 | } | 1063 | } |
1110 | producer = get_next_index(producer, adapter->max_tx_desc_count); | 1064 | producer = get_next_index(producer, num_txd); |
1111 | 1065 | ||
1112 | /* might change opcode to TX_TCP_LSO */ | 1066 | /* might change opcode to TX_TCP_LSO */ |
1113 | netxen_tso_check(adapter, &hw->cmd_desc_head[saved_producer], skb); | 1067 | netxen_tso_check(adapter, &hw->cmd_desc_head[saved_producer], skb); |
@@ -1134,7 +1088,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
1134 | /* copy the first 64 bytes */ | 1088 | /* copy the first 64 bytes */ |
1135 | memcpy(((void *)hwdesc) + 2, | 1089 | memcpy(((void *)hwdesc) + 2, |
1136 | (void *)(skb->data), first_hdr_len); | 1090 | (void *)(skb->data), first_hdr_len); |
1137 | producer = get_next_index(producer, max_tx_desc_count); | 1091 | producer = get_next_index(producer, num_txd); |
1138 | 1092 | ||
1139 | if (more_hdr) { | 1093 | if (more_hdr) { |
1140 | hwdesc = &hw->cmd_desc_head[producer]; | 1094 | hwdesc = &hw->cmd_desc_head[producer]; |
@@ -1147,35 +1101,19 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
1147 | hwdesc, | 1101 | hwdesc, |
1148 | (hdr_len - | 1102 | (hdr_len - |
1149 | first_hdr_len)); | 1103 | first_hdr_len)); |
1150 | producer = get_next_index(producer, max_tx_desc_count); | 1104 | producer = get_next_index(producer, num_txd); |
1151 | } | 1105 | } |
1152 | } | 1106 | } |
1153 | 1107 | ||
1154 | spin_lock_bh(&adapter->tx_lock); | 1108 | adapter->cmd_producer = producer; |
1155 | adapter->stats.txbytes += skb->len; | 1109 | adapter->stats.txbytes += skb->len; |
1156 | 1110 | ||
1157 | /* Code to update the adapter considering how many producer threads | 1111 | netxen_nic_update_cmd_producer(adapter, adapter->cmd_producer); |
1158 | are currently working */ | ||
1159 | if ((--adapter->num_threads) == 0) { | ||
1160 | /* This is the last thread */ | ||
1161 | u32 crb_producer = adapter->cmd_producer; | ||
1162 | netxen_nic_update_cmd_producer(adapter, crb_producer); | ||
1163 | wmb(); | ||
1164 | adapter->total_threads = 0; | ||
1165 | } | ||
1166 | 1112 | ||
1167 | adapter->stats.xmitfinished++; | 1113 | adapter->stats.xmitcalled++; |
1168 | netdev->trans_start = jiffies; | 1114 | netdev->trans_start = jiffies; |
1169 | 1115 | ||
1170 | spin_unlock_bh(&adapter->tx_lock); | ||
1171 | return NETDEV_TX_OK; | 1116 | return NETDEV_TX_OK; |
1172 | |||
1173 | out_requeue: | ||
1174 | netif_stop_queue(netdev); | ||
1175 | adapter->flags |= NETXEN_NETDEV_STATUS; | ||
1176 | |||
1177 | spin_unlock_bh(&adapter->tx_lock); | ||
1178 | return NETDEV_TX_BUSY; | ||
1179 | } | 1117 | } |
1180 | 1118 | ||
1181 | static void netxen_watchdog(unsigned long v) | 1119 | static void netxen_watchdog(unsigned long v) |
@@ -1200,87 +1138,60 @@ static void netxen_tx_timeout_task(struct work_struct *work) | |||
1200 | printk(KERN_ERR "%s %s: transmit timeout, resetting.\n", | 1138 | printk(KERN_ERR "%s %s: transmit timeout, resetting.\n", |
1201 | netxen_nic_driver_name, adapter->netdev->name); | 1139 | netxen_nic_driver_name, adapter->netdev->name); |
1202 | 1140 | ||
1203 | netxen_nic_close(adapter->netdev); | 1141 | netxen_nic_disable_int(adapter); |
1204 | netxen_nic_open(adapter->netdev); | 1142 | napi_disable(&adapter->napi); |
1143 | |||
1205 | adapter->netdev->trans_start = jiffies; | 1144 | adapter->netdev->trans_start = jiffies; |
1145 | |||
1146 | napi_enable(&adapter->napi); | ||
1147 | netxen_nic_enable_int(adapter); | ||
1206 | netif_wake_queue(adapter->netdev); | 1148 | netif_wake_queue(adapter->netdev); |
1207 | } | 1149 | } |
1208 | 1150 | ||
1209 | static int | 1151 | static inline void |
1210 | netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev) | 1152 | netxen_handle_int(struct netxen_adapter *adapter) |
1211 | { | 1153 | { |
1212 | u32 ret = 0; | ||
1213 | |||
1214 | DPRINTK(INFO, "Entered handle ISR\n"); | ||
1215 | adapter->stats.ints++; | ||
1216 | |||
1217 | netxen_nic_disable_int(adapter); | 1154 | netxen_nic_disable_int(adapter); |
1218 | 1155 | napi_schedule(&adapter->napi); | |
1219 | if (netxen_nic_rx_has_work(adapter) || netxen_nic_tx_has_work(adapter)) { | ||
1220 | if (netif_rx_schedule_prep(netdev, &adapter->napi)) { | ||
1221 | /* | ||
1222 | * Interrupts are already disabled. | ||
1223 | */ | ||
1224 | __netif_rx_schedule(netdev, &adapter->napi); | ||
1225 | } else { | ||
1226 | static unsigned int intcount = 0; | ||
1227 | if ((++intcount & 0xfff) == 0xfff) | ||
1228 | DPRINTK(KERN_ERR | ||
1229 | "%s: %s interrupt %d while in poll\n", | ||
1230 | netxen_nic_driver_name, netdev->name, | ||
1231 | intcount); | ||
1232 | } | ||
1233 | ret = 1; | ||
1234 | } | ||
1235 | |||
1236 | if (ret == 0) { | ||
1237 | netxen_nic_enable_int(adapter); | ||
1238 | } | ||
1239 | |||
1240 | return ret; | ||
1241 | } | 1156 | } |
1242 | 1157 | ||
1243 | /* | ||
1244 | * netxen_intr - Interrupt Handler | ||
1245 | * @irq: interrupt number | ||
1246 | * data points to adapter stucture (which may be handling more than 1 port | ||
1247 | */ | ||
1248 | irqreturn_t netxen_intr(int irq, void *data) | 1158 | irqreturn_t netxen_intr(int irq, void *data) |
1249 | { | 1159 | { |
1250 | struct netxen_adapter *adapter = data; | 1160 | struct netxen_adapter *adapter = data; |
1251 | struct net_device *netdev = adapter->netdev; | ||
1252 | u32 our_int = 0; | 1161 | u32 our_int = 0; |
1253 | 1162 | ||
1254 | if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { | 1163 | our_int = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR)); |
1255 | our_int = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR)); | 1164 | /* not our interrupt */ |
1256 | /* not our interrupt */ | 1165 | if ((our_int & (0x80 << adapter->portnum)) == 0) |
1257 | if ((our_int & (0x80 << adapter->portnum)) == 0) | 1166 | return IRQ_NONE; |
1258 | return IRQ_NONE; | ||
1259 | } | ||
1260 | 1167 | ||
1261 | if (adapter->intr_scheme == INTR_SCHEME_PERPORT) { | 1168 | if (adapter->intr_scheme == INTR_SCHEME_PERPORT) { |
1262 | /* claim interrupt */ | 1169 | /* claim interrupt */ |
1263 | if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { | 1170 | writel(our_int & ~((u32)(0x80 << adapter->portnum)), |
1264 | writel(our_int & ~((u32)(0x80 << adapter->portnum)), | ||
1265 | NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR)); | 1171 | NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR)); |
1266 | } | ||
1267 | } | 1172 | } |
1268 | 1173 | ||
1269 | if (netif_running(netdev)) | 1174 | netxen_handle_int(adapter); |
1270 | netxen_handle_int(adapter, netdev); | ||
1271 | 1175 | ||
1272 | return IRQ_HANDLED; | 1176 | return IRQ_HANDLED; |
1273 | } | 1177 | } |
1274 | 1178 | ||
1179 | irqreturn_t netxen_msi_intr(int irq, void *data) | ||
1180 | { | ||
1181 | struct netxen_adapter *adapter = data; | ||
1182 | |||
1183 | netxen_handle_int(adapter); | ||
1184 | return IRQ_HANDLED; | ||
1185 | } | ||
1186 | |||
1275 | static int netxen_nic_poll(struct napi_struct *napi, int budget) | 1187 | static int netxen_nic_poll(struct napi_struct *napi, int budget) |
1276 | { | 1188 | { |
1277 | struct netxen_adapter *adapter = container_of(napi, struct netxen_adapter, napi); | 1189 | struct netxen_adapter *adapter = container_of(napi, struct netxen_adapter, napi); |
1278 | struct net_device *netdev = adapter->netdev; | 1190 | int tx_complete; |
1279 | int done = 1; | ||
1280 | int ctx; | 1191 | int ctx; |
1281 | int work_done; | 1192 | int work_done; |
1282 | 1193 | ||
1283 | DPRINTK(INFO, "polling for %d descriptors\n", *budget); | 1194 | tx_complete = netxen_process_cmd_ring(adapter); |
1284 | 1195 | ||
1285 | work_done = 0; | 1196 | work_done = 0; |
1286 | for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { | 1197 | for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { |
@@ -1300,16 +1211,8 @@ static int netxen_nic_poll(struct napi_struct *napi, int budget) | |||
1300 | budget / MAX_RCV_CTX); | 1211 | budget / MAX_RCV_CTX); |
1301 | } | 1212 | } |
1302 | 1213 | ||
1303 | if (work_done >= budget) | 1214 | if ((work_done < budget) && tx_complete) { |
1304 | done = 0; | 1215 | netif_rx_complete(adapter->netdev, &adapter->napi); |
1305 | |||
1306 | if (netxen_process_cmd_ring((unsigned long)adapter) == 0) | ||
1307 | done = 0; | ||
1308 | |||
1309 | DPRINTK(INFO, "new work_done: %d work_to_do: %d\n", | ||
1310 | work_done, work_to_do); | ||
1311 | if (done) { | ||
1312 | netif_rx_complete(netdev, napi); | ||
1313 | netxen_nic_enable_int(adapter); | 1216 | netxen_nic_enable_int(adapter); |
1314 | } | 1217 | } |
1315 | 1218 | ||