blob: 3d9bbff4f7acdea2f4d0d37bbfb4c11eaec991d9 [file] [log] [blame]
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001/*
Chien Tungcd6853d2009-03-06 15:12:10 -08002 * Copyright (c) 2006 - 2009 Intel-NE, Inc. All rights reserved.
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003 *
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
9 *
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
12 * conditions are met:
13 *
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer.
17 *
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * SOFTWARE.
31 *
32 */
33
34#include <linux/module.h>
35#include <linux/moduleparam.h>
36#include <linux/netdevice.h>
37#include <linux/etherdevice.h>
38#include <linux/ip.h>
39#include <linux/tcp.h>
40#include <linux/if_vlan.h>
Faisal Latif37dab412008-04-29 13:46:54 -070041#include <linux/inet_lro.h>
Glenn Streiff3c2d7742008-02-04 20:20:45 -080042
43#include "nes.h"
44
Roland Dreierdd378182008-05-13 11:27:25 -070045static unsigned int nes_lro_max_aggr = NES_LRO_MAX_AGGR;
46module_param(nes_lro_max_aggr, uint, 0444);
47MODULE_PARM_DESC(nes_lro_max_aggr, "NIC LRO max packet aggregation");
48
Chien Tunga4849fc2009-04-08 14:27:18 -070049static int wide_ppm_offset;
50module_param(wide_ppm_offset, int, 0644);
51MODULE_PARM_DESC(wide_ppm_offset, "Increase CX4 interface clock ppm offset, 0=100ppm (default), 1=300ppm");
52
Roland Dreier1a855fbf2008-04-16 21:01:09 -070053static u32 crit_err_count;
Glenn Streiff3c2d7742008-02-04 20:20:45 -080054u32 int_mod_timer_init;
55u32 int_mod_cq_depth_256;
56u32 int_mod_cq_depth_128;
57u32 int_mod_cq_depth_32;
58u32 int_mod_cq_depth_24;
59u32 int_mod_cq_depth_16;
60u32 int_mod_cq_depth_4;
61u32 int_mod_cq_depth_1;
Chien Tung9d156942008-09-26 15:08:10 -050062static const u8 nes_max_critical_error_count = 100;
Glenn Streiff3c2d7742008-02-04 20:20:45 -080063#include "nes_cm.h"
64
Roland Dreier1a855fbf2008-04-16 21:01:09 -070065static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq);
66static void nes_init_csr_ne020(struct nes_device *nesdev, u8 hw_rev, u8 port_count);
67static int nes_init_serdes(struct nes_device *nesdev, u8 hw_rev, u8 port_count,
Chien Tungfcb7ad32008-09-30 14:49:44 -070068 struct nes_adapter *nesadapter, u8 OneG_Mode);
Roland Dreier1a855fbf2008-04-16 21:01:09 -070069static void nes_nic_napi_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq);
70static void nes_process_aeq(struct nes_device *nesdev, struct nes_hw_aeq *aeq);
71static void nes_process_ceq(struct nes_device *nesdev, struct nes_hw_ceq *ceq);
72static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
73 struct nes_hw_aeqe *aeqe);
Chien Tung9d156942008-09-26 15:08:10 -050074static void process_critical_error(struct nes_device *nesdev);
Roland Dreier1a855fbf2008-04-16 21:01:09 -070075static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number);
76static unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode);
Don Wood8b1c9dc2009-09-05 20:36:38 -070077static void nes_terminate_timeout(unsigned long context);
78static void nes_terminate_start_timer(struct nes_qp *nesqp);
Glenn Streiff3c2d7742008-02-04 20:20:45 -080079
80#ifdef CONFIG_INFINIBAND_NES_DEBUG
81static unsigned char *nes_iwarp_state_str[] = {
82 "Non-Existant",
83 "Idle",
84 "RTS",
85 "Closing",
86 "RSVD1",
87 "Terminate",
88 "Error",
89 "RSVD2",
90};
91
92static unsigned char *nes_tcp_state_str[] = {
93 "Non-Existant",
94 "Closed",
95 "Listen",
96 "SYN Sent",
97 "SYN Rcvd",
98 "Established",
99 "Close Wait",
100 "FIN Wait 1",
101 "Closing",
102 "Last Ack",
103 "FIN Wait 2",
104 "Time Wait",
105 "RSVD1",
106 "RSVD2",
107 "RSVD3",
108 "RSVD4",
109};
110#endif
111
112
113/**
114 * nes_nic_init_timer_defaults
115 */
116void nes_nic_init_timer_defaults(struct nes_device *nesdev, u8 jumbomode)
117{
118 unsigned long flags;
119 struct nes_adapter *nesadapter = nesdev->nesadapter;
120 struct nes_hw_tune_timer *shared_timer = &nesadapter->tune_timer;
121
122 spin_lock_irqsave(&nesadapter->periodic_timer_lock, flags);
123
124 shared_timer->timer_in_use_min = NES_NIC_FAST_TIMER_LOW;
125 shared_timer->timer_in_use_max = NES_NIC_FAST_TIMER_HIGH;
126 if (jumbomode) {
127 shared_timer->threshold_low = DEFAULT_JUMBO_NES_QL_LOW;
128 shared_timer->threshold_target = DEFAULT_JUMBO_NES_QL_TARGET;
129 shared_timer->threshold_high = DEFAULT_JUMBO_NES_QL_HIGH;
130 } else {
131 shared_timer->threshold_low = DEFAULT_NES_QL_LOW;
132 shared_timer->threshold_target = DEFAULT_NES_QL_TARGET;
133 shared_timer->threshold_high = DEFAULT_NES_QL_HIGH;
134 }
135
136 /* todo use netdev->mtu to set thresholds */
137 spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags);
138}
139
140
141/**
142 * nes_nic_init_timer
143 */
144static void nes_nic_init_timer(struct nes_device *nesdev)
145{
146 unsigned long flags;
147 struct nes_adapter *nesadapter = nesdev->nesadapter;
148 struct nes_hw_tune_timer *shared_timer = &nesadapter->tune_timer;
149
150 spin_lock_irqsave(&nesadapter->periodic_timer_lock, flags);
151
152 if (shared_timer->timer_in_use_old == 0) {
153 nesdev->deepcq_count = 0;
154 shared_timer->timer_direction_upward = 0;
155 shared_timer->timer_direction_downward = 0;
156 shared_timer->timer_in_use = NES_NIC_FAST_TIMER;
157 shared_timer->timer_in_use_old = 0;
158
159 }
160 if (shared_timer->timer_in_use != shared_timer->timer_in_use_old) {
161 shared_timer->timer_in_use_old = shared_timer->timer_in_use;
162 nes_write32(nesdev->regs+NES_PERIODIC_CONTROL,
163 0x80000000 | ((u32)(shared_timer->timer_in_use*8)));
164 }
165 /* todo use netdev->mtu to set thresholds */
166 spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags);
167}
168
169
170/**
171 * nes_nic_tune_timer
172 */
173static void nes_nic_tune_timer(struct nes_device *nesdev)
174{
175 unsigned long flags;
176 struct nes_adapter *nesadapter = nesdev->nesadapter;
177 struct nes_hw_tune_timer *shared_timer = &nesadapter->tune_timer;
178 u16 cq_count = nesdev->currcq_count;
179
180 spin_lock_irqsave(&nesadapter->periodic_timer_lock, flags);
181
John Lacombe4b1cc7e2008-02-21 08:34:58 -0600182 if (shared_timer->cq_count_old <= cq_count)
183 shared_timer->cq_direction_downward = 0;
184 else
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800185 shared_timer->cq_direction_downward++;
186 shared_timer->cq_count_old = cq_count;
187 if (shared_timer->cq_direction_downward > NES_NIC_CQ_DOWNWARD_TREND) {
John Lacombe4b1cc7e2008-02-21 08:34:58 -0600188 if (cq_count <= shared_timer->threshold_low &&
189 shared_timer->threshold_low > 4) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800190 shared_timer->threshold_low = shared_timer->threshold_low/2;
191 shared_timer->cq_direction_downward=0;
192 nesdev->currcq_count = 0;
193 spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags);
194 return;
195 }
196 }
197
198 if (cq_count > 1) {
199 nesdev->deepcq_count += cq_count;
200 if (cq_count <= shared_timer->threshold_low) { /* increase timer gently */
201 shared_timer->timer_direction_upward++;
202 shared_timer->timer_direction_downward = 0;
203 } else if (cq_count <= shared_timer->threshold_target) { /* balanced */
204 shared_timer->timer_direction_upward = 0;
205 shared_timer->timer_direction_downward = 0;
206 } else if (cq_count <= shared_timer->threshold_high) { /* decrease timer gently */
207 shared_timer->timer_direction_downward++;
208 shared_timer->timer_direction_upward = 0;
209 } else if (cq_count <= (shared_timer->threshold_high) * 2) {
210 shared_timer->timer_in_use -= 2;
211 shared_timer->timer_direction_upward = 0;
212 shared_timer->timer_direction_downward++;
213 } else {
214 shared_timer->timer_in_use -= 4;
215 shared_timer->timer_direction_upward = 0;
216 shared_timer->timer_direction_downward++;
217 }
218
219 if (shared_timer->timer_direction_upward > 3 ) { /* using history */
220 shared_timer->timer_in_use += 3;
221 shared_timer->timer_direction_upward = 0;
222 shared_timer->timer_direction_downward = 0;
223 }
224 if (shared_timer->timer_direction_downward > 5) { /* using history */
225 shared_timer->timer_in_use -= 4 ;
226 shared_timer->timer_direction_downward = 0;
227 shared_timer->timer_direction_upward = 0;
228 }
229 }
230
231 /* boundary checking */
John Lacombe27ffed62008-09-26 15:08:10 -0500232 if (shared_timer->timer_in_use > shared_timer->threshold_high)
233 shared_timer->timer_in_use = shared_timer->threshold_high;
234 else if (shared_timer->timer_in_use < shared_timer->threshold_low)
235 shared_timer->timer_in_use = shared_timer->threshold_low;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800236
237 nesdev->currcq_count = 0;
238
239 spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags);
240}
241
242
243/**
244 * nes_init_adapter - initialize adapter
245 */
246struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) {
247 struct nes_adapter *nesadapter = NULL;
248 unsigned long num_pds;
249 u32 u32temp;
250 u32 port_count;
251 u16 max_rq_wrs;
252 u16 max_sq_wrs;
253 u32 max_mr;
254 u32 max_256pbl;
255 u32 max_4kpbl;
256 u32 max_qp;
257 u32 max_irrq;
258 u32 max_cq;
259 u32 hte_index_mask;
260 u32 adapter_size;
261 u32 arp_table_size;
262 u16 vendor_id;
Chien Tungb9c367e2009-03-06 15:12:10 -0800263 u16 device_id;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800264 u8 OneG_Mode;
265 u8 func_index;
266
267 /* search the list of existing adapters */
268 list_for_each_entry(nesadapter, &nes_adapter_list, list) {
269 nes_debug(NES_DBG_INIT, "Searching Adapter list for PCI devfn = 0x%X,"
270 " adapter PCI slot/bus = %u/%u, pci devices PCI slot/bus = %u/%u, .\n",
271 nesdev->pcidev->devfn,
272 PCI_SLOT(nesadapter->devfn),
273 nesadapter->bus_number,
274 PCI_SLOT(nesdev->pcidev->devfn),
275 nesdev->pcidev->bus->number );
276 if ((PCI_SLOT(nesadapter->devfn) == PCI_SLOT(nesdev->pcidev->devfn)) &&
277 (nesadapter->bus_number == nesdev->pcidev->bus->number)) {
278 nesadapter->ref_count++;
279 return nesadapter;
280 }
281 }
282
283 /* no adapter found */
284 num_pds = pci_resource_len(nesdev->pcidev, BAR_1) >> PAGE_SHIFT;
285 if ((hw_rev != NE020_REV) && (hw_rev != NE020_REV1)) {
286 nes_debug(NES_DBG_INIT, "NE020 driver detected unknown hardware revision 0x%x\n",
287 hw_rev);
288 return NULL;
289 }
290
291 nes_debug(NES_DBG_INIT, "Determine Soft Reset, QP_control=0x%x, CPU0=0x%x, CPU1=0x%x, CPU2=0x%x\n",
292 nes_read_indexed(nesdev, NES_IDX_QP_CONTROL + PCI_FUNC(nesdev->pcidev->devfn) * 8),
293 nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS),
294 nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS + 4),
295 nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS + 8));
296
297 nes_debug(NES_DBG_INIT, "Reset and init NE020\n");
298
299
300 if ((port_count = nes_reset_adapter_ne020(nesdev, &OneG_Mode)) == 0)
301 return NULL;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800302
303 max_qp = nes_read_indexed(nesdev, NES_IDX_QP_CTX_SIZE);
304 nes_debug(NES_DBG_INIT, "QP_CTX_SIZE=%u\n", max_qp);
305
306 u32temp = nes_read_indexed(nesdev, NES_IDX_QUAD_HASH_TABLE_SIZE);
307 if (max_qp > ((u32)1 << (u32temp & 0x001f))) {
308 nes_debug(NES_DBG_INIT, "Reducing Max QPs to %u due to hash table size = 0x%08X\n",
309 max_qp, u32temp);
310 max_qp = (u32)1 << (u32temp & 0x001f);
311 }
312
313 hte_index_mask = ((u32)1 << ((u32temp & 0x001f)+1))-1;
314 nes_debug(NES_DBG_INIT, "Max QP = %u, hte_index_mask = 0x%08X.\n",
315 max_qp, hte_index_mask);
316
317 u32temp = nes_read_indexed(nesdev, NES_IDX_IRRQ_COUNT);
318
319 max_irrq = 1 << (u32temp & 0x001f);
320
321 if (max_qp > max_irrq) {
322 max_qp = max_irrq;
323 nes_debug(NES_DBG_INIT, "Reducing Max QPs to %u due to Available Q1s.\n",
324 max_qp);
325 }
326
327 /* there should be no reason to allocate more pds than qps */
328 if (num_pds > max_qp)
329 num_pds = max_qp;
330
331 u32temp = nes_read_indexed(nesdev, NES_IDX_MRT_SIZE);
332 max_mr = (u32)8192 << (u32temp & 0x7);
333
334 u32temp = nes_read_indexed(nesdev, NES_IDX_PBL_REGION_SIZE);
335 max_256pbl = (u32)1 << (u32temp & 0x0000001f);
336 max_4kpbl = (u32)1 << ((u32temp >> 16) & 0x0000001f);
337 max_cq = nes_read_indexed(nesdev, NES_IDX_CQ_CTX_SIZE);
338
339 u32temp = nes_read_indexed(nesdev, NES_IDX_ARP_CACHE_SIZE);
340 arp_table_size = 1 << u32temp;
341
342 adapter_size = (sizeof(struct nes_adapter) +
343 (sizeof(unsigned long)-1)) & (~(sizeof(unsigned long)-1));
344 adapter_size += sizeof(unsigned long) * BITS_TO_LONGS(max_qp);
345 adapter_size += sizeof(unsigned long) * BITS_TO_LONGS(max_mr);
346 adapter_size += sizeof(unsigned long) * BITS_TO_LONGS(max_cq);
347 adapter_size += sizeof(unsigned long) * BITS_TO_LONGS(num_pds);
348 adapter_size += sizeof(unsigned long) * BITS_TO_LONGS(arp_table_size);
349 adapter_size += sizeof(struct nes_qp **) * max_qp;
350
351 /* allocate a new adapter struct */
352 nesadapter = kzalloc(adapter_size, GFP_KERNEL);
353 if (nesadapter == NULL) {
354 return NULL;
355 }
356
357 nes_debug(NES_DBG_INIT, "Allocating new nesadapter @ %p, size = %u (actual size = %u).\n",
358 nesadapter, (u32)sizeof(struct nes_adapter), adapter_size);
359
Chien Tungfcb7ad32008-09-30 14:49:44 -0700360 if (nes_read_eeprom_values(nesdev, nesadapter)) {
361 printk(KERN_ERR PFX "Unable to read EEPROM data.\n");
362 kfree(nesadapter);
363 return NULL;
364 }
365
Chien Tungb9c367e2009-03-06 15:12:10 -0800366 nesadapter->vendor_id = (((u32) nesadapter->mac_addr_high) << 8) |
367 (nesadapter->mac_addr_low >> 24);
368
369 pci_bus_read_config_word(nesdev->pcidev->bus, nesdev->pcidev->devfn,
370 PCI_DEVICE_ID, &device_id);
371 nesadapter->vendor_part_id = device_id;
372
Chien Tungfcb7ad32008-09-30 14:49:44 -0700373 if (nes_init_serdes(nesdev, hw_rev, port_count, nesadapter,
374 OneG_Mode)) {
375 kfree(nesadapter);
376 return NULL;
377 }
378 nes_init_csr_ne020(nesdev, hw_rev, port_count);
379
Vadim Makhervaks7e36d3d2008-10-03 12:21:18 -0700380 memset(nesadapter->pft_mcast_map, 255,
381 sizeof nesadapter->pft_mcast_map);
382
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800383 /* populate the new nesadapter */
384 nesadapter->devfn = nesdev->pcidev->devfn;
385 nesadapter->bus_number = nesdev->pcidev->bus->number;
386 nesadapter->ref_count = 1;
387 nesadapter->timer_int_req = 0xffff0000;
388 nesadapter->OneG_Mode = OneG_Mode;
389 nesadapter->doorbell_start = nesdev->doorbell_region;
390
391 /* nesadapter->tick_delta = clk_divisor; */
392 nesadapter->hw_rev = hw_rev;
393 nesadapter->port_count = port_count;
394
395 nesadapter->max_qp = max_qp;
396 nesadapter->hte_index_mask = hte_index_mask;
397 nesadapter->max_irrq = max_irrq;
398 nesadapter->max_mr = max_mr;
399 nesadapter->max_256pbl = max_256pbl - 1;
400 nesadapter->max_4kpbl = max_4kpbl - 1;
401 nesadapter->max_cq = max_cq;
402 nesadapter->free_256pbl = max_256pbl - 1;
403 nesadapter->free_4kpbl = max_4kpbl - 1;
404 nesadapter->max_pd = num_pds;
405 nesadapter->arp_table_size = arp_table_size;
406
407 nesadapter->et_pkt_rate_low = NES_TIMER_ENABLE_LIMIT;
408 if (nes_drv_opt & NES_DRV_OPT_DISABLE_INT_MOD) {
409 nesadapter->et_use_adaptive_rx_coalesce = 0;
410 nesadapter->timer_int_limit = NES_TIMER_INT_LIMIT;
411 nesadapter->et_rx_coalesce_usecs_irq = interrupt_mod_interval;
412 } else {
413 nesadapter->et_use_adaptive_rx_coalesce = 1;
414 nesadapter->timer_int_limit = NES_TIMER_INT_LIMIT_DYNAMIC;
415 nesadapter->et_rx_coalesce_usecs_irq = 0;
Harvey Harrison33718362008-04-16 21:01:10 -0700416 printk(PFX "%s: Using Adaptive Interrupt Moderation\n", __func__);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800417 }
418 /* Setup and enable the periodic timer */
419 if (nesadapter->et_rx_coalesce_usecs_irq)
420 nes_write32(nesdev->regs+NES_PERIODIC_CONTROL, 0x80000000 |
421 ((u32)(nesadapter->et_rx_coalesce_usecs_irq * 8)));
422 else
423 nes_write32(nesdev->regs+NES_PERIODIC_CONTROL, 0x00000000);
424
425 nesadapter->base_pd = 1;
426
Chien Tunge293a262009-12-09 15:21:54 -0800427 nesadapter->device_cap_flags = IB_DEVICE_LOCAL_DMA_LKEY |
428 IB_DEVICE_MEM_WINDOW |
429 IB_DEVICE_MEM_MGT_EXTENSIONS;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800430
431 nesadapter->allocated_qps = (unsigned long *)&(((unsigned char *)nesadapter)
432 [(sizeof(struct nes_adapter)+(sizeof(unsigned long)-1))&(~(sizeof(unsigned long)-1))]);
433 nesadapter->allocated_cqs = &nesadapter->allocated_qps[BITS_TO_LONGS(max_qp)];
434 nesadapter->allocated_mrs = &nesadapter->allocated_cqs[BITS_TO_LONGS(max_cq)];
435 nesadapter->allocated_pds = &nesadapter->allocated_mrs[BITS_TO_LONGS(max_mr)];
436 nesadapter->allocated_arps = &nesadapter->allocated_pds[BITS_TO_LONGS(num_pds)];
437 nesadapter->qp_table = (struct nes_qp **)(&nesadapter->allocated_arps[BITS_TO_LONGS(arp_table_size)]);
438
439
440 /* mark the usual suspect QPs and CQs as in use */
441 for (u32temp = 0; u32temp < NES_FIRST_QPN; u32temp++) {
442 set_bit(u32temp, nesadapter->allocated_qps);
443 set_bit(u32temp, nesadapter->allocated_cqs);
444 }
445
446 for (u32temp = 0; u32temp < 20; u32temp++)
447 set_bit(u32temp, nesadapter->allocated_pds);
448 u32temp = nes_read_indexed(nesdev, NES_IDX_QP_MAX_CFG_SIZES);
449
450 max_rq_wrs = ((u32temp >> 8) & 3);
451 switch (max_rq_wrs) {
452 case 0:
453 max_rq_wrs = 4;
454 break;
455 case 1:
456 max_rq_wrs = 16;
457 break;
458 case 2:
459 max_rq_wrs = 32;
460 break;
461 case 3:
462 max_rq_wrs = 512;
463 break;
464 }
465
466 max_sq_wrs = (u32temp & 3);
467 switch (max_sq_wrs) {
468 case 0:
469 max_sq_wrs = 4;
470 break;
471 case 1:
472 max_sq_wrs = 16;
473 break;
474 case 2:
475 max_sq_wrs = 32;
476 break;
477 case 3:
478 max_sq_wrs = 512;
479 break;
480 }
481 nesadapter->max_qp_wr = min(max_rq_wrs, max_sq_wrs);
482 nesadapter->max_irrq_wr = (u32temp >> 16) & 3;
483
484 nesadapter->max_sge = 4;
485 nesadapter->max_cqe = 32767;
486
487 if (nes_read_eeprom_values(nesdev, nesadapter)) {
488 printk(KERN_ERR PFX "Unable to read EEPROM data.\n");
489 kfree(nesadapter);
490 return NULL;
491 }
492
493 u32temp = nes_read_indexed(nesdev, NES_IDX_TCP_TIMER_CONFIG);
494 nes_write_indexed(nesdev, NES_IDX_TCP_TIMER_CONFIG,
495 (u32temp & 0xff000000) | (nesadapter->tcp_timer_core_clk_divisor & 0x00ffffff));
496
497 /* setup port configuration */
498 if (nesadapter->port_count == 1) {
Chien Tungfcb7ad32008-09-30 14:49:44 -0700499 nesadapter->log_port = 0x00000000;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800500 if (nes_drv_opt & NES_DRV_OPT_DUAL_LOGICAL_PORT)
501 nes_write_indexed(nesdev, NES_IDX_TX_POOL_SIZE, 0x00000002);
502 else
503 nes_write_indexed(nesdev, NES_IDX_TX_POOL_SIZE, 0x00000003);
504 } else {
Chien Tungfcb7ad32008-09-30 14:49:44 -0700505 if (nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G) {
506 nesadapter->log_port = 0x000000D8;
507 } else {
508 if (nesadapter->port_count == 2)
509 nesadapter->log_port = 0x00000044;
510 else
511 nesadapter->log_port = 0x000000e4;
512 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800513 nes_write_indexed(nesdev, NES_IDX_TX_POOL_SIZE, 0x00000003);
514 }
515
Chien Tungfcb7ad32008-09-30 14:49:44 -0700516 nes_write_indexed(nesdev, NES_IDX_NIC_LOGPORT_TO_PHYPORT,
517 nesadapter->log_port);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800518 nes_debug(NES_DBG_INIT, "Probe time, LOG2PHY=%u\n",
519 nes_read_indexed(nesdev, NES_IDX_NIC_LOGPORT_TO_PHYPORT));
520
521 spin_lock_init(&nesadapter->resource_lock);
522 spin_lock_init(&nesadapter->phy_lock);
523 spin_lock_init(&nesadapter->pbl_lock);
524 spin_lock_init(&nesadapter->periodic_timer_lock);
525
526 INIT_LIST_HEAD(&nesadapter->nesvnic_list[0]);
527 INIT_LIST_HEAD(&nesadapter->nesvnic_list[1]);
528 INIT_LIST_HEAD(&nesadapter->nesvnic_list[2]);
529 INIT_LIST_HEAD(&nesadapter->nesvnic_list[3]);
530
531 if ((!nesadapter->OneG_Mode) && (nesadapter->port_count == 2)) {
532 u32 pcs_control_status0, pcs_control_status1;
533 u32 reset_value;
534 u32 i = 0;
535 u32 int_cnt = 0;
536 u32 ext_cnt = 0;
537 unsigned long flags;
538 u32 j = 0;
539
540 pcs_control_status0 = nes_read_indexed(nesdev,
541 NES_IDX_PHY_PCS_CONTROL_STATUS0);
542 pcs_control_status1 = nes_read_indexed(nesdev,
543 NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200);
544
545 for (i = 0; i < NES_MAX_LINK_CHECK; i++) {
546 pcs_control_status0 = nes_read_indexed(nesdev,
547 NES_IDX_PHY_PCS_CONTROL_STATUS0);
548 pcs_control_status1 = nes_read_indexed(nesdev,
549 NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200);
550 if ((0x0F000100 == (pcs_control_status0 & 0x0F000100))
551 || (0x0F000100 == (pcs_control_status1 & 0x0F000100)))
552 int_cnt++;
553 msleep(1);
554 }
555 if (int_cnt > 1) {
556 spin_lock_irqsave(&nesadapter->phy_lock, flags);
Chien Tung010db4d2009-04-27 13:27:21 -0700557 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F0C8);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800558 mh_detected++;
559 reset_value = nes_read32(nesdev->regs+NES_SOFTWARE_RESET);
560 reset_value |= 0x0000003d;
561 nes_write32(nesdev->regs+NES_SOFTWARE_RESET, reset_value);
562
563 while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET)
564 & 0x00000040) != 0x00000040) && (j++ < 5000));
565 spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
566
567 pcs_control_status0 = nes_read_indexed(nesdev,
568 NES_IDX_PHY_PCS_CONTROL_STATUS0);
569 pcs_control_status1 = nes_read_indexed(nesdev,
570 NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200);
571
572 for (i = 0; i < NES_MAX_LINK_CHECK; i++) {
573 pcs_control_status0 = nes_read_indexed(nesdev,
574 NES_IDX_PHY_PCS_CONTROL_STATUS0);
575 pcs_control_status1 = nes_read_indexed(nesdev,
576 NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200);
577 if ((0x0F000100 == (pcs_control_status0 & 0x0F000100))
578 || (0x0F000100 == (pcs_control_status1 & 0x0F000100))) {
579 if (++ext_cnt > int_cnt) {
580 spin_lock_irqsave(&nesadapter->phy_lock, flags);
581 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1,
Chien Tung010db4d2009-04-27 13:27:21 -0700582 0x0000F088);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800583 mh_detected++;
584 reset_value = nes_read32(nesdev->regs+NES_SOFTWARE_RESET);
585 reset_value |= 0x0000003d;
586 nes_write32(nesdev->regs+NES_SOFTWARE_RESET, reset_value);
587
588 while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET)
589 & 0x00000040) != 0x00000040) && (j++ < 5000));
590 spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
591 break;
592 }
593 }
594 msleep(1);
595 }
596 }
597 }
598
599 if (nesadapter->hw_rev == NE020_REV) {
600 init_timer(&nesadapter->mh_timer);
601 nesadapter->mh_timer.function = nes_mh_fix;
602 nesadapter->mh_timer.expires = jiffies + (HZ/5); /* 1 second */
603 nesadapter->mh_timer.data = (unsigned long)nesdev;
604 add_timer(&nesadapter->mh_timer);
605 } else {
606 nes_write32(nesdev->regs+NES_INTF_INT_STAT, 0x0f000000);
607 }
608
609 init_timer(&nesadapter->lc_timer);
610 nesadapter->lc_timer.function = nes_clc;
611 nesadapter->lc_timer.expires = jiffies + 3600 * HZ; /* 1 hour */
612 nesadapter->lc_timer.data = (unsigned long)nesdev;
613 add_timer(&nesadapter->lc_timer);
614
615 list_add_tail(&nesadapter->list, &nes_adapter_list);
616
617 for (func_index = 0; func_index < 8; func_index++) {
618 pci_bus_read_config_word(nesdev->pcidev->bus,
619 PCI_DEVFN(PCI_SLOT(nesdev->pcidev->devfn),
620 func_index), 0, &vendor_id);
621 if (vendor_id == 0xffff)
622 break;
623 }
Harvey Harrison33718362008-04-16 21:01:10 -0700624 nes_debug(NES_DBG_INIT, "%s %d functions found for %s.\n", __func__,
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800625 func_index, pci_name(nesdev->pcidev));
626 nesadapter->adapter_fcn_count = func_index;
627
628 return nesadapter;
629}
630
631
632/**
633 * nes_reset_adapter_ne020
634 */
Roland Dreier1a855fbf2008-04-16 21:01:09 -0700635static unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode)
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800636{
637 u32 port_count;
638 u32 u32temp;
639 u32 i;
640
641 u32temp = nes_read32(nesdev->regs+NES_SOFTWARE_RESET);
642 port_count = ((u32temp & 0x00000300) >> 8) + 1;
643 /* TODO: assuming that both SERDES are set the same for now */
644 *OneG_Mode = (u32temp & 0x00003c00) ? 0 : 1;
645 nes_debug(NES_DBG_INIT, "Initial Software Reset = 0x%08X, port_count=%u\n",
646 u32temp, port_count);
647 if (*OneG_Mode)
648 nes_debug(NES_DBG_INIT, "Running in 1G mode.\n");
649 u32temp &= 0xff00ffc0;
650 switch (port_count) {
651 case 1:
652 u32temp |= 0x00ee0000;
653 break;
654 case 2:
655 u32temp |= 0x00cc0000;
656 break;
657 case 4:
658 u32temp |= 0x00000000;
659 break;
660 default:
661 return 0;
662 break;
663 }
664
665 /* check and do full reset if needed */
666 if (nes_read_indexed(nesdev, NES_IDX_QP_CONTROL+(PCI_FUNC(nesdev->pcidev->devfn)*8))) {
667 nes_debug(NES_DBG_INIT, "Issuing Full Soft reset = 0x%08X\n", u32temp | 0xd);
668 nes_write32(nesdev->regs+NES_SOFTWARE_RESET, u32temp | 0xd);
669
670 i = 0;
671 while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET) & 0x00000040) == 0) && i++ < 10000)
672 mdelay(1);
Roel Kluin28e43a52009-05-15 10:16:45 -0700673 if (i > 10000) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800674 nes_debug(NES_DBG_INIT, "Did not see full soft reset done.\n");
675 return 0;
676 }
Chien Tungbc5698f32008-04-23 11:55:45 -0700677
678 i = 0;
679 while ((nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS) != 0x80) && i++ < 10000)
680 mdelay(1);
Roel Kluin28e43a52009-05-15 10:16:45 -0700681 if (i > 10000) {
Chien Tungbc5698f32008-04-23 11:55:45 -0700682 printk(KERN_ERR PFX "Internal CPU not ready, status = %02X\n",
683 nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS));
684 return 0;
685 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800686 }
687
688 /* port reset */
689 switch (port_count) {
690 case 1:
691 u32temp |= 0x00ee0010;
692 break;
693 case 2:
694 u32temp |= 0x00cc0030;
695 break;
696 case 4:
697 u32temp |= 0x00000030;
698 break;
699 }
700
701 nes_debug(NES_DBG_INIT, "Issuing Port Soft reset = 0x%08X\n", u32temp | 0xd);
702 nes_write32(nesdev->regs+NES_SOFTWARE_RESET, u32temp | 0xd);
703
704 i = 0;
705 while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET) & 0x00000040) == 0) && i++ < 10000)
706 mdelay(1);
Roel Kluin28e43a52009-05-15 10:16:45 -0700707 if (i > 10000) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800708 nes_debug(NES_DBG_INIT, "Did not see port soft reset done.\n");
709 return 0;
710 }
711
712 /* serdes 0 */
713 i = 0;
714 while (((u32temp = (nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0)
715 & 0x0000000f)) != 0x0000000f) && i++ < 5000)
716 mdelay(1);
Roel Kluin28e43a52009-05-15 10:16:45 -0700717 if (i > 5000) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800718 nes_debug(NES_DBG_INIT, "Serdes 0 not ready, status=%x\n", u32temp);
719 return 0;
720 }
721
722 /* serdes 1 */
723 if (port_count > 1) {
724 i = 0;
725 while (((u32temp = (nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS1)
726 & 0x0000000f)) != 0x0000000f) && i++ < 5000)
727 mdelay(1);
Roel Kluin28e43a52009-05-15 10:16:45 -0700728 if (i > 5000) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800729 nes_debug(NES_DBG_INIT, "Serdes 1 not ready, status=%x\n", u32temp);
730 return 0;
731 }
732 }
733
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800734 return port_count;
735}
736
737
738/**
739 * nes_init_serdes
740 */
Roland Dreier1a855fbf2008-04-16 21:01:09 -0700741static int nes_init_serdes(struct nes_device *nesdev, u8 hw_rev, u8 port_count,
Chien Tungfcb7ad32008-09-30 14:49:44 -0700742 struct nes_adapter *nesadapter, u8 OneG_Mode)
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800743{
744 int i;
745 u32 u32temp;
Chien Tunga4849fc2009-04-08 14:27:18 -0700746 u32 sds;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800747
748 if (hw_rev != NE020_REV) {
749 /* init serdes 0 */
Chien Tunga4849fc2009-04-08 14:27:18 -0700750 if (wide_ppm_offset && (nesadapter->phy_type[0] == NES_PHY_TYPE_CX4))
751 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000FFFAA);
752 else
753 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000000FF);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800754
Chien Tungfcb7ad32008-09-30 14:49:44 -0700755 if (nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G) {
Chien Tunga4849fc2009-04-08 14:27:18 -0700756 sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0);
757 sds |= 0x00000100;
758 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, sds);
759 }
760 if (!OneG_Mode)
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800761 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE0, 0x11110000);
Chien Tunga4849fc2009-04-08 14:27:18 -0700762
763 if (port_count < 2)
764 return 0;
765
766 /* init serdes 1 */
Chien Tung366835e2009-04-27 13:28:41 -0700767 if (!(OneG_Mode && (nesadapter->phy_type[1] != NES_PHY_TYPE_PUMA_1G)))
768 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000000FF);
769
Chien Tunga4849fc2009-04-08 14:27:18 -0700770 switch (nesadapter->phy_type[1]) {
Chien Tung43035652009-04-08 14:27:56 -0700771 case NES_PHY_TYPE_ARGUS:
772 case NES_PHY_TYPE_SFP_D:
Chien Tunga4849fc2009-04-08 14:27:18 -0700773 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP0, 0x00000000);
774 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP1, 0x00000000);
775 break;
776 case NES_PHY_TYPE_CX4:
Chien Tunga4849fc2009-04-08 14:27:18 -0700777 if (wide_ppm_offset)
778 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000FFFAA);
Chien Tunga4849fc2009-04-08 14:27:18 -0700779 break;
780 case NES_PHY_TYPE_PUMA_1G:
781 sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1);
782 sds |= 0x000000100;
783 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, sds);
Chien Tungfcb7ad32008-09-30 14:49:44 -0700784 }
Chien Tung366835e2009-04-27 13:28:41 -0700785 if (!OneG_Mode) {
Chien Tunga4849fc2009-04-08 14:27:18 -0700786 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE1, 0x11110000);
Chien Tung366835e2009-04-27 13:28:41 -0700787 sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1);
788 sds &= 0xFFFFFFBF;
789 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, sds);
790 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800791 } else {
792 /* init serdes 0 */
793 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, 0x00000008);
794 i = 0;
795 while (((u32temp = (nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0)
796 & 0x0000000f)) != 0x0000000f) && i++ < 5000)
797 mdelay(1);
Roel Kluin28e43a52009-05-15 10:16:45 -0700798 if (i > 5000) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800799 nes_debug(NES_DBG_PHY, "Init: serdes 0 not ready, status=%x\n", u32temp);
800 return 1;
801 }
802 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP0, 0x000bdef7);
803 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_DRIVE0, 0x9ce73000);
804 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_MODE0, 0x0ff00000);
805 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_SIGDET0, 0x00000000);
806 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_BYPASS0, 0x00000000);
807 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_LOOPBACK_CONTROL0, 0x00000000);
808 if (OneG_Mode)
809 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_EQ_CONTROL0, 0xf0182222);
810 else
811 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_EQ_CONTROL0, 0xf0042222);
812
813 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000000ff);
814 if (port_count > 1) {
815 /* init serdes 1 */
816 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x00000048);
817 i = 0;
818 while (((u32temp = (nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS1)
819 & 0x0000000f)) != 0x0000000f) && (i++ < 5000))
820 mdelay(1);
Roel Kluin28e43a52009-05-15 10:16:45 -0700821 if (i > 5000) {
Harvey Harrison33718362008-04-16 21:01:10 -0700822 printk("%s: Init: serdes 1 not ready, status=%x\n", __func__, u32temp);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800823 /* return 1; */
824 }
825 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP1, 0x000bdef7);
826 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_DRIVE1, 0x9ce73000);
827 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_MODE1, 0x0ff00000);
828 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_SIGDET1, 0x00000000);
829 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_BYPASS1, 0x00000000);
830 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_LOOPBACK_CONTROL1, 0x00000000);
831 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_EQ_CONTROL1, 0xf0002222);
832 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000000ff);
833 }
834 }
835 return 0;
836}
837
838
839/**
840 * nes_init_csr_ne020
841 * Initialize registers for ne020 hardware
842 */
Roland Dreier1a855fbf2008-04-16 21:01:09 -0700843static void nes_init_csr_ne020(struct nes_device *nesdev, u8 hw_rev, u8 port_count)
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800844{
845 u32 u32temp;
846
847 nes_debug(NES_DBG_INIT, "port_count=%d\n", port_count);
848
849 nes_write_indexed(nesdev, 0x000001E4, 0x00000007);
850 /* nes_write_indexed(nesdev, 0x000001E8, 0x000208C4); */
851 nes_write_indexed(nesdev, 0x000001E8, 0x00020874);
852 nes_write_indexed(nesdev, 0x000001D8, 0x00048002);
853 /* nes_write_indexed(nesdev, 0x000001D8, 0x0004B002); */
854 nes_write_indexed(nesdev, 0x000001FC, 0x00050005);
855 nes_write_indexed(nesdev, 0x00000600, 0x55555555);
856 nes_write_indexed(nesdev, 0x00000604, 0x55555555);
857
858 /* TODO: move these MAC register settings to NIC bringup */
859 nes_write_indexed(nesdev, 0x00002000, 0x00000001);
860 nes_write_indexed(nesdev, 0x00002004, 0x00000001);
861 nes_write_indexed(nesdev, 0x00002008, 0x0000FFFF);
862 nes_write_indexed(nesdev, 0x0000200C, 0x00000001);
863 nes_write_indexed(nesdev, 0x00002010, 0x000003c1);
864 nes_write_indexed(nesdev, 0x0000201C, 0x75345678);
865 if (port_count > 1) {
866 nes_write_indexed(nesdev, 0x00002200, 0x00000001);
867 nes_write_indexed(nesdev, 0x00002204, 0x00000001);
868 nes_write_indexed(nesdev, 0x00002208, 0x0000FFFF);
869 nes_write_indexed(nesdev, 0x0000220C, 0x00000001);
870 nes_write_indexed(nesdev, 0x00002210, 0x000003c1);
871 nes_write_indexed(nesdev, 0x0000221C, 0x75345678);
872 nes_write_indexed(nesdev, 0x00000908, 0x20000001);
873 }
874 if (port_count > 2) {
875 nes_write_indexed(nesdev, 0x00002400, 0x00000001);
876 nes_write_indexed(nesdev, 0x00002404, 0x00000001);
877 nes_write_indexed(nesdev, 0x00002408, 0x0000FFFF);
878 nes_write_indexed(nesdev, 0x0000240C, 0x00000001);
879 nes_write_indexed(nesdev, 0x00002410, 0x000003c1);
880 nes_write_indexed(nesdev, 0x0000241C, 0x75345678);
881 nes_write_indexed(nesdev, 0x00000910, 0x20000001);
882
883 nes_write_indexed(nesdev, 0x00002600, 0x00000001);
884 nes_write_indexed(nesdev, 0x00002604, 0x00000001);
885 nes_write_indexed(nesdev, 0x00002608, 0x0000FFFF);
886 nes_write_indexed(nesdev, 0x0000260C, 0x00000001);
887 nes_write_indexed(nesdev, 0x00002610, 0x000003c1);
888 nes_write_indexed(nesdev, 0x0000261C, 0x75345678);
889 nes_write_indexed(nesdev, 0x00000918, 0x20000001);
890 }
891
892 nes_write_indexed(nesdev, 0x00005000, 0x00018000);
893 /* nes_write_indexed(nesdev, 0x00005000, 0x00010000); */
Chien Tung2b537c22008-09-26 15:08:10 -0500894 nes_write_indexed(nesdev, NES_IDX_WQM_CONFIG1, (wqm_quanta << 1) |
895 0x00000001);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800896 nes_write_indexed(nesdev, 0x00005008, 0x1F1F1F1F);
897 nes_write_indexed(nesdev, 0x00005010, 0x1F1F1F1F);
898 nes_write_indexed(nesdev, 0x00005018, 0x1F1F1F1F);
899 nes_write_indexed(nesdev, 0x00005020, 0x1F1F1F1F);
900 nes_write_indexed(nesdev, 0x00006090, 0xFFFFFFFF);
901
902 /* TODO: move this to code, get from EEPROM */
903 nes_write_indexed(nesdev, 0x00000900, 0x20000001);
904 nes_write_indexed(nesdev, 0x000060C0, 0x0000028e);
905 nes_write_indexed(nesdev, 0x000060C8, 0x00000020);
Glenn Streiff7495ab62008-04-29 13:46:54 -0700906
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800907 nes_write_indexed(nesdev, 0x000001EC, 0x7b2625a0);
908 /* nes_write_indexed(nesdev, 0x000001EC, 0x5f2625a0); */
909
910 if (hw_rev != NE020_REV) {
911 u32temp = nes_read_indexed(nesdev, 0x000008e8);
912 u32temp |= 0x80000000;
913 nes_write_indexed(nesdev, 0x000008e8, u32temp);
914 u32temp = nes_read_indexed(nesdev, 0x000021f8);
915 u32temp &= 0x7fffffff;
916 u32temp |= 0x7fff0010;
917 nes_write_indexed(nesdev, 0x000021f8, u32temp);
Chien Tunge998c252009-04-27 13:29:42 -0700918 if (port_count > 1) {
919 u32temp = nes_read_indexed(nesdev, 0x000023f8);
920 u32temp &= 0x7fffffff;
921 u32temp |= 0x7fff0010;
922 nes_write_indexed(nesdev, 0x000023f8, u32temp);
923 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800924 }
925}
926
927
928/**
929 * nes_destroy_adapter - destroy the adapter structure
930 */
931void nes_destroy_adapter(struct nes_adapter *nesadapter)
932{
933 struct nes_adapter *tmp_adapter;
934
935 list_for_each_entry(tmp_adapter, &nes_adapter_list, list) {
936 nes_debug(NES_DBG_SHUTDOWN, "Nes Adapter list entry = 0x%p.\n",
937 tmp_adapter);
938 }
939
940 nesadapter->ref_count--;
941 if (!nesadapter->ref_count) {
942 if (nesadapter->hw_rev == NE020_REV) {
943 del_timer(&nesadapter->mh_timer);
944 }
945 del_timer(&nesadapter->lc_timer);
946
947 list_del(&nesadapter->list);
948 kfree(nesadapter);
949 }
950}
951
952
953/**
954 * nes_init_cqp
955 */
956int nes_init_cqp(struct nes_device *nesdev)
957{
958 struct nes_adapter *nesadapter = nesdev->nesadapter;
959 struct nes_hw_cqp_qp_context *cqp_qp_context;
960 struct nes_hw_cqp_wqe *cqp_wqe;
961 struct nes_hw_ceq *ceq;
962 struct nes_hw_ceq *nic_ceq;
963 struct nes_hw_aeq *aeq;
964 void *vmem;
965 dma_addr_t pmem;
966 u32 count=0;
967 u32 cqp_head;
968 u64 u64temp;
969 u32 u32temp;
970
971 /* allocate CQP memory */
972 /* Need to add max_cq to the aeq size once cq overflow checking is added back */
973 /* SQ is 512 byte aligned, others are 256 byte aligned */
974 nesdev->cqp_mem_size = 512 +
975 (sizeof(struct nes_hw_cqp_wqe) * NES_CQP_SQ_SIZE) +
976 (sizeof(struct nes_hw_cqe) * NES_CCQ_SIZE) +
977 max(((u32)sizeof(struct nes_hw_ceqe) * NES_CCEQ_SIZE), (u32)256) +
978 max(((u32)sizeof(struct nes_hw_ceqe) * NES_NIC_CEQ_SIZE), (u32)256) +
979 (sizeof(struct nes_hw_aeqe) * nesadapter->max_qp) +
980 sizeof(struct nes_hw_cqp_qp_context);
981
982 nesdev->cqp_vbase = pci_alloc_consistent(nesdev->pcidev, nesdev->cqp_mem_size,
983 &nesdev->cqp_pbase);
984 if (!nesdev->cqp_vbase) {
985 nes_debug(NES_DBG_INIT, "Unable to allocate memory for host descriptor rings\n");
986 return -ENOMEM;
987 }
988 memset(nesdev->cqp_vbase, 0, nesdev->cqp_mem_size);
989
990 /* Allocate a twice the number of CQP requests as the SQ size */
991 nesdev->nes_cqp_requests = kzalloc(sizeof(struct nes_cqp_request) *
992 2 * NES_CQP_SQ_SIZE, GFP_KERNEL);
993 if (nesdev->nes_cqp_requests == NULL) {
994 nes_debug(NES_DBG_INIT, "Unable to allocate memory CQP request entries.\n");
995 pci_free_consistent(nesdev->pcidev, nesdev->cqp_mem_size, nesdev->cqp.sq_vbase,
996 nesdev->cqp.sq_pbase);
997 return -ENOMEM;
998 }
999
1000 nes_debug(NES_DBG_INIT, "Allocated CQP structures at %p (phys = %016lX), size = %u.\n",
1001 nesdev->cqp_vbase, (unsigned long)nesdev->cqp_pbase, nesdev->cqp_mem_size);
1002
1003 spin_lock_init(&nesdev->cqp.lock);
1004 init_waitqueue_head(&nesdev->cqp.waitq);
1005
1006 /* Setup Various Structures */
1007 vmem = (void *)(((unsigned long)nesdev->cqp_vbase + (512 - 1)) &
1008 ~(unsigned long)(512 - 1));
1009 pmem = (dma_addr_t)(((unsigned long long)nesdev->cqp_pbase + (512 - 1)) &
1010 ~(unsigned long long)(512 - 1));
1011
1012 nesdev->cqp.sq_vbase = vmem;
1013 nesdev->cqp.sq_pbase = pmem;
1014 nesdev->cqp.sq_size = NES_CQP_SQ_SIZE;
1015 nesdev->cqp.sq_head = 0;
1016 nesdev->cqp.sq_tail = 0;
1017 nesdev->cqp.qp_id = PCI_FUNC(nesdev->pcidev->devfn);
1018
1019 vmem += (sizeof(struct nes_hw_cqp_wqe) * nesdev->cqp.sq_size);
1020 pmem += (sizeof(struct nes_hw_cqp_wqe) * nesdev->cqp.sq_size);
1021
1022 nesdev->ccq.cq_vbase = vmem;
1023 nesdev->ccq.cq_pbase = pmem;
1024 nesdev->ccq.cq_size = NES_CCQ_SIZE;
1025 nesdev->ccq.cq_head = 0;
1026 nesdev->ccq.ce_handler = nes_cqp_ce_handler;
1027 nesdev->ccq.cq_number = PCI_FUNC(nesdev->pcidev->devfn);
1028
1029 vmem += (sizeof(struct nes_hw_cqe) * nesdev->ccq.cq_size);
1030 pmem += (sizeof(struct nes_hw_cqe) * nesdev->ccq.cq_size);
1031
1032 nesdev->ceq_index = PCI_FUNC(nesdev->pcidev->devfn);
1033 ceq = &nesadapter->ceq[nesdev->ceq_index];
1034 ceq->ceq_vbase = vmem;
1035 ceq->ceq_pbase = pmem;
1036 ceq->ceq_size = NES_CCEQ_SIZE;
1037 ceq->ceq_head = 0;
1038
1039 vmem += max(((u32)sizeof(struct nes_hw_ceqe) * ceq->ceq_size), (u32)256);
1040 pmem += max(((u32)sizeof(struct nes_hw_ceqe) * ceq->ceq_size), (u32)256);
1041
1042 nesdev->nic_ceq_index = PCI_FUNC(nesdev->pcidev->devfn) + 8;
1043 nic_ceq = &nesadapter->ceq[nesdev->nic_ceq_index];
1044 nic_ceq->ceq_vbase = vmem;
1045 nic_ceq->ceq_pbase = pmem;
1046 nic_ceq->ceq_size = NES_NIC_CEQ_SIZE;
1047 nic_ceq->ceq_head = 0;
1048
1049 vmem += max(((u32)sizeof(struct nes_hw_ceqe) * nic_ceq->ceq_size), (u32)256);
1050 pmem += max(((u32)sizeof(struct nes_hw_ceqe) * nic_ceq->ceq_size), (u32)256);
1051
1052 aeq = &nesadapter->aeq[PCI_FUNC(nesdev->pcidev->devfn)];
1053 aeq->aeq_vbase = vmem;
1054 aeq->aeq_pbase = pmem;
1055 aeq->aeq_size = nesadapter->max_qp;
1056 aeq->aeq_head = 0;
1057
1058 /* Setup QP Context */
1059 vmem += (sizeof(struct nes_hw_aeqe) * aeq->aeq_size);
1060 pmem += (sizeof(struct nes_hw_aeqe) * aeq->aeq_size);
1061
1062 cqp_qp_context = vmem;
1063 cqp_qp_context->context_words[0] =
1064 cpu_to_le32((PCI_FUNC(nesdev->pcidev->devfn) << 12) + (2 << 10));
1065 cqp_qp_context->context_words[1] = 0;
1066 cqp_qp_context->context_words[2] = cpu_to_le32((u32)nesdev->cqp.sq_pbase);
1067 cqp_qp_context->context_words[3] = cpu_to_le32(((u64)nesdev->cqp.sq_pbase) >> 32);
1068
1069
1070 /* Write the address to Create CQP */
1071 if ((sizeof(dma_addr_t) > 4)) {
1072 nes_write_indexed(nesdev,
1073 NES_IDX_CREATE_CQP_HIGH + (PCI_FUNC(nesdev->pcidev->devfn) * 8),
1074 ((u64)pmem) >> 32);
1075 } else {
1076 nes_write_indexed(nesdev,
1077 NES_IDX_CREATE_CQP_HIGH + (PCI_FUNC(nesdev->pcidev->devfn) * 8), 0);
1078 }
1079 nes_write_indexed(nesdev,
1080 NES_IDX_CREATE_CQP_LOW + (PCI_FUNC(nesdev->pcidev->devfn) * 8),
1081 (u32)pmem);
1082
1083 INIT_LIST_HEAD(&nesdev->cqp_avail_reqs);
1084 INIT_LIST_HEAD(&nesdev->cqp_pending_reqs);
1085
1086 for (count = 0; count < 2*NES_CQP_SQ_SIZE; count++) {
1087 init_waitqueue_head(&nesdev->nes_cqp_requests[count].waitq);
1088 list_add_tail(&nesdev->nes_cqp_requests[count].list, &nesdev->cqp_avail_reqs);
1089 }
1090
1091 /* Write Create CCQ WQE */
1092 cqp_head = nesdev->cqp.sq_head++;
1093 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1094 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
1095 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
1096 (NES_CQP_CREATE_CQ | NES_CQP_CQ_CEQ_VALID |
1097 NES_CQP_CQ_CHK_OVERFLOW | ((u32)nesdev->ccq.cq_size << 16)));
1098 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,
1099 (nesdev->ccq.cq_number |
1100 ((u32)nesdev->ceq_index << 16)));
1101 u64temp = (u64)nesdev->ccq.cq_pbase;
1102 set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);
1103 cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] = 0;
1104 u64temp = (unsigned long)&nesdev->ccq;
1105 cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_LOW_IDX] =
1106 cpu_to_le32((u32)(u64temp >> 1));
1107 cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] =
1108 cpu_to_le32(((u32)((u64temp) >> 33)) & 0x7FFFFFFF);
1109 cqp_wqe->wqe_words[NES_CQP_CQ_WQE_DOORBELL_INDEX_HIGH_IDX] = 0;
1110
1111 /* Write Create CEQ WQE */
1112 cqp_head = nesdev->cqp.sq_head++;
1113 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1114 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
1115 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
1116 (NES_CQP_CREATE_CEQ + ((u32)nesdev->ceq_index << 8)));
1117 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_CEQ_WQE_ELEMENT_COUNT_IDX, ceq->ceq_size);
1118 u64temp = (u64)ceq->ceq_pbase;
1119 set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);
1120
1121 /* Write Create AEQ WQE */
1122 cqp_head = nesdev->cqp.sq_head++;
1123 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1124 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
1125 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
1126 (NES_CQP_CREATE_AEQ + ((u32)PCI_FUNC(nesdev->pcidev->devfn) << 8)));
1127 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_AEQ_WQE_ELEMENT_COUNT_IDX, aeq->aeq_size);
1128 u64temp = (u64)aeq->aeq_pbase;
1129 set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);
1130
1131 /* Write Create NIC CEQ WQE */
1132 cqp_head = nesdev->cqp.sq_head++;
1133 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1134 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
1135 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
1136 (NES_CQP_CREATE_CEQ + ((u32)nesdev->nic_ceq_index << 8)));
1137 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_CEQ_WQE_ELEMENT_COUNT_IDX, nic_ceq->ceq_size);
1138 u64temp = (u64)nic_ceq->ceq_pbase;
1139 set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);
1140
1141 /* Poll until CCQP done */
1142 count = 0;
1143 do {
1144 if (count++ > 1000) {
1145 printk(KERN_ERR PFX "Error creating CQP\n");
1146 pci_free_consistent(nesdev->pcidev, nesdev->cqp_mem_size,
1147 nesdev->cqp_vbase, nesdev->cqp_pbase);
1148 return -1;
1149 }
1150 udelay(10);
1151 } while (!(nes_read_indexed(nesdev,
1152 NES_IDX_QP_CONTROL + (PCI_FUNC(nesdev->pcidev->devfn) * 8)) & (1 << 8)));
1153
1154 nes_debug(NES_DBG_INIT, "CQP Status = 0x%08X\n", nes_read_indexed(nesdev,
1155 NES_IDX_QP_CONTROL+(PCI_FUNC(nesdev->pcidev->devfn)*8)));
1156
1157 u32temp = 0x04800000;
1158 nes_write32(nesdev->regs+NES_WQE_ALLOC, u32temp | nesdev->cqp.qp_id);
1159
1160 /* wait for the CCQ, CEQ, and AEQ to get created */
1161 count = 0;
1162 do {
1163 if (count++ > 1000) {
1164 printk(KERN_ERR PFX "Error creating CCQ, CEQ, and AEQ\n");
1165 pci_free_consistent(nesdev->pcidev, nesdev->cqp_mem_size,
1166 nesdev->cqp_vbase, nesdev->cqp_pbase);
1167 return -1;
1168 }
1169 udelay(10);
1170 } while (((nes_read_indexed(nesdev,
1171 NES_IDX_QP_CONTROL+(PCI_FUNC(nesdev->pcidev->devfn)*8)) & (15<<8)) != (15<<8)));
1172
1173 /* dump the QP status value */
1174 nes_debug(NES_DBG_INIT, "QP Status = 0x%08X\n", nes_read_indexed(nesdev,
1175 NES_IDX_QP_CONTROL+(PCI_FUNC(nesdev->pcidev->devfn)*8)));
1176
1177 nesdev->cqp.sq_tail++;
1178
1179 return 0;
1180}
1181
1182
1183/**
1184 * nes_destroy_cqp
1185 */
1186int nes_destroy_cqp(struct nes_device *nesdev)
1187{
1188 struct nes_hw_cqp_wqe *cqp_wqe;
1189 u32 count = 0;
1190 u32 cqp_head;
1191 unsigned long flags;
1192
1193 do {
1194 if (count++ > 1000)
1195 break;
1196 udelay(10);
1197 } while (!(nesdev->cqp.sq_head == nesdev->cqp.sq_tail));
1198
1199 /* Reset CCQ */
1200 nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_RESET |
1201 nesdev->ccq.cq_number);
1202
1203 /* Disable device interrupts */
1204 nes_write32(nesdev->regs+NES_INT_MASK, 0x7fffffff);
1205
1206 spin_lock_irqsave(&nesdev->cqp.lock, flags);
1207
1208 /* Destroy the AEQ */
1209 cqp_head = nesdev->cqp.sq_head++;
1210 nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
1211 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1212 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_AEQ |
1213 ((u32)PCI_FUNC(nesdev->pcidev->devfn) << 8));
1214 cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0;
1215
1216 /* Destroy the NIC CEQ */
1217 cqp_head = nesdev->cqp.sq_head++;
1218 nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
1219 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1220 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_CEQ |
1221 ((u32)nesdev->nic_ceq_index << 8));
1222
1223 /* Destroy the CEQ */
1224 cqp_head = nesdev->cqp.sq_head++;
1225 nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
1226 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1227 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_CEQ |
1228 (nesdev->ceq_index << 8));
1229
1230 /* Destroy the CCQ */
1231 cqp_head = nesdev->cqp.sq_head++;
1232 nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
1233 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1234 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_CQ);
1235 cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesdev->ccq.cq_number |
1236 ((u32)nesdev->ceq_index << 16));
1237
1238 /* Destroy CQP */
1239 cqp_head = nesdev->cqp.sq_head++;
1240 nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
1241 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1242 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_QP |
1243 NES_CQP_QP_TYPE_CQP);
1244 cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesdev->cqp.qp_id);
1245
1246 barrier();
1247 /* Ring doorbell (5 WQEs) */
1248 nes_write32(nesdev->regs+NES_WQE_ALLOC, 0x05800000 | nesdev->cqp.qp_id);
1249
1250 spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
1251
1252 /* wait for the CCQ, CEQ, and AEQ to get destroyed */
1253 count = 0;
1254 do {
1255 if (count++ > 1000) {
1256 printk(KERN_ERR PFX "Function%d: Error destroying CCQ, CEQ, and AEQ\n",
1257 PCI_FUNC(nesdev->pcidev->devfn));
1258 break;
1259 }
1260 udelay(10);
1261 } while (((nes_read_indexed(nesdev,
1262 NES_IDX_QP_CONTROL + (PCI_FUNC(nesdev->pcidev->devfn)*8)) & (15 << 8)) != 0));
1263
1264 /* dump the QP status value */
1265 nes_debug(NES_DBG_SHUTDOWN, "Function%d: QP Status = 0x%08X\n",
1266 PCI_FUNC(nesdev->pcidev->devfn),
1267 nes_read_indexed(nesdev,
1268 NES_IDX_QP_CONTROL+(PCI_FUNC(nesdev->pcidev->devfn)*8)));
1269
1270 kfree(nesdev->nes_cqp_requests);
1271
1272 /* Free the control structures */
1273 pci_free_consistent(nesdev->pcidev, nesdev->cqp_mem_size, nesdev->cqp.sq_vbase,
1274 nesdev->cqp.sq_pbase);
1275
1276 return 0;
1277}
1278
1279
1280/**
1281 * nes_init_phy
1282 */
1283int nes_init_phy(struct nes_device *nesdev)
1284{
1285 struct nes_adapter *nesadapter = nesdev->nesadapter;
1286 u32 counter = 0;
Chien Tung1b949322009-04-08 14:27:09 -07001287 u32 sds;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001288 u32 mac_index = nesdev->mac_index;
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001289 u32 tx_config = 0;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001290 u16 phy_data;
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001291 u32 temp_phy_data = 0;
1292 u32 temp_phy_data2 = 0;
Chien Tung1b949322009-04-08 14:27:09 -07001293 u8 phy_type = nesadapter->phy_type[mac_index];
1294 u8 phy_index = nesadapter->phy_index[mac_index];
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001295
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001296 if ((nesadapter->OneG_Mode) &&
Chien Tung1b949322009-04-08 14:27:09 -07001297 (phy_type != NES_PHY_TYPE_PUMA_1G)) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001298 nes_debug(NES_DBG_PHY, "1G PHY, mac_index = %d.\n", mac_index);
Chien Tung1b949322009-04-08 14:27:09 -07001299 if (phy_type == NES_PHY_TYPE_1G) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001300 tx_config = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG);
Chien Tunge88bd7b2008-09-26 15:08:10 -05001301 tx_config &= 0xFFFFFFE3;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001302 tx_config |= 0x04;
1303 nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config);
1304 }
1305
Chien Tung1b949322009-04-08 14:27:09 -07001306 nes_read_1G_phy_reg(nesdev, 1, phy_index, &phy_data);
1307 nes_write_1G_phy_reg(nesdev, 23, phy_index, 0xb000);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001308
1309 /* Reset the PHY */
Chien Tung1b949322009-04-08 14:27:09 -07001310 nes_write_1G_phy_reg(nesdev, 0, phy_index, 0x8000);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001311 udelay(100);
1312 counter = 0;
1313 do {
Chien Tung1b949322009-04-08 14:27:09 -07001314 nes_read_1G_phy_reg(nesdev, 0, phy_index, &phy_data);
1315 if (counter++ > 100)
1316 break;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001317 } while (phy_data & 0x8000);
1318
1319 /* Setting no phy loopback */
1320 phy_data &= 0xbfff;
1321 phy_data |= 0x1140;
Chien Tung1b949322009-04-08 14:27:09 -07001322 nes_write_1G_phy_reg(nesdev, 0, phy_index, phy_data);
1323 nes_read_1G_phy_reg(nesdev, 0, phy_index, &phy_data);
1324 nes_read_1G_phy_reg(nesdev, 0x17, phy_index, &phy_data);
1325 nes_read_1G_phy_reg(nesdev, 0x1e, phy_index, &phy_data);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001326
1327 /* Setting the interrupt mask */
Chien Tung1b949322009-04-08 14:27:09 -07001328 nes_read_1G_phy_reg(nesdev, 0x19, phy_index, &phy_data);
1329 nes_write_1G_phy_reg(nesdev, 0x19, phy_index, 0xffee);
1330 nes_read_1G_phy_reg(nesdev, 0x19, phy_index, &phy_data);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001331
1332 /* turning on flow control */
Chien Tung1b949322009-04-08 14:27:09 -07001333 nes_read_1G_phy_reg(nesdev, 4, phy_index, &phy_data);
1334 nes_write_1G_phy_reg(nesdev, 4, phy_index, (phy_data & ~(0x03E0)) | 0xc00);
1335 nes_read_1G_phy_reg(nesdev, 4, phy_index, &phy_data);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001336
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001337 /* Clear Half duplex */
Chien Tung1b949322009-04-08 14:27:09 -07001338 nes_read_1G_phy_reg(nesdev, 9, phy_index, &phy_data);
1339 nes_write_1G_phy_reg(nesdev, 9, phy_index, phy_data & ~(0x0100));
1340 nes_read_1G_phy_reg(nesdev, 9, phy_index, &phy_data);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001341
Chien Tung1b949322009-04-08 14:27:09 -07001342 nes_read_1G_phy_reg(nesdev, 0, phy_index, &phy_data);
1343 nes_write_1G_phy_reg(nesdev, 0, phy_index, phy_data | 0x0300);
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001344
Chien Tung1b949322009-04-08 14:27:09 -07001345 return 0;
1346 }
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001347
Chien Tung1b949322009-04-08 14:27:09 -07001348 if ((phy_type == NES_PHY_TYPE_IRIS) ||
Chien Tung43035652009-04-08 14:27:56 -07001349 (phy_type == NES_PHY_TYPE_ARGUS) ||
1350 (phy_type == NES_PHY_TYPE_SFP_D)) {
Chien Tung1b949322009-04-08 14:27:09 -07001351 /* setup 10G MDIO operation */
1352 tx_config = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG);
1353 tx_config &= 0xFFFFFFE3;
1354 tx_config |= 0x15;
1355 nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config);
1356 }
Chien Tung43035652009-04-08 14:27:56 -07001357 if ((phy_type == NES_PHY_TYPE_ARGUS) ||
1358 (phy_type == NES_PHY_TYPE_SFP_D)) {
Chien Tung1b949322009-04-08 14:27:09 -07001359 /* Check firmware heartbeat */
1360 nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee);
1361 temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
1362 udelay(1500);
1363 nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee);
1364 temp_phy_data2 = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001365
Chien Tung1b949322009-04-08 14:27:09 -07001366 if (temp_phy_data != temp_phy_data2)
1367 return 0;
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001368
Chien Tung1b949322009-04-08 14:27:09 -07001369 /* no heartbeat, configure the PHY */
1370 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0x0000, 0x8000);
1371 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc300, 0x0000);
Chien Tung1b949322009-04-08 14:27:09 -07001372 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc316, 0x000A);
1373 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc318, 0x0052);
Chien Tung43035652009-04-08 14:27:56 -07001374 if (phy_type == NES_PHY_TYPE_ARGUS) {
1375 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc302, 0x000C);
1376 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc319, 0x0008);
Chien Tung92322372009-04-27 13:30:35 -07001377 nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0027, 0x0001);
Chien Tung43035652009-04-08 14:27:56 -07001378 } else {
1379 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc302, 0x0004);
1380 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc319, 0x0038);
Chien Tung92322372009-04-27 13:30:35 -07001381 nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0027, 0x0013);
Chien Tung43035652009-04-08 14:27:56 -07001382 }
Chien Tung1b949322009-04-08 14:27:09 -07001383 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc31a, 0x0098);
1384 nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0026, 0x0E00);
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001385
Chien Tung1b949322009-04-08 14:27:09 -07001386 /* setup LEDs */
1387 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd006, 0x0007);
1388 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd007, 0x000A);
1389 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd008, 0x0009);
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001390
Chien Tung1b949322009-04-08 14:27:09 -07001391 nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0028, 0xA528);
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001392
Chien Tung1b949322009-04-08 14:27:09 -07001393 /* Bring PHY out of reset */
1394 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc300, 0x0002);
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001395
Chien Tung1b949322009-04-08 14:27:09 -07001396 /* Check for heartbeat */
1397 counter = 0;
1398 mdelay(690);
1399 nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee);
1400 temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
1401 do {
1402 if (counter++ > 150) {
1403 nes_debug(NES_DBG_PHY, "No PHY heartbeat\n");
1404 break;
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001405 }
Chien Tung1b949322009-04-08 14:27:09 -07001406 mdelay(1);
1407 nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee);
1408 temp_phy_data2 = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
1409 } while ((temp_phy_data2 == temp_phy_data));
1410
1411 /* wait for tracking */
1412 counter = 0;
1413 do {
1414 nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7fd);
1415 temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
1416 if (counter++ > 300) {
1417 nes_debug(NES_DBG_PHY, "PHY did not track\n");
1418 break;
1419 }
1420 mdelay(10);
1421 } while (((temp_phy_data & 0xff) != 0x50) && ((temp_phy_data & 0xff) != 0x70));
1422
1423 /* setup signal integrity */
1424 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd003, 0x0000);
1425 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xF00D, 0x00FE);
1426 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xF00E, 0x0032);
1427 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xF00F, 0x0002);
1428 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc314, 0x0063);
1429
1430 /* reset serdes */
1431 sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0 +
1432 mac_index * 0x200);
1433 sds |= 0x1;
1434 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0 +
1435 mac_index * 0x200, sds);
1436 sds &= 0xfffffffe;
1437 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0 +
1438 mac_index * 0x200, sds);
1439
1440 counter = 0;
1441 while (((nes_read32(nesdev->regs + NES_SOFTWARE_RESET) & 0x00000040) != 0x00000040)
1442 && (counter++ < 5000))
1443 ;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001444 }
1445 return 0;
1446}
1447
1448
1449/**
1450 * nes_replenish_nic_rq
1451 */
1452static void nes_replenish_nic_rq(struct nes_vnic *nesvnic)
1453{
1454 unsigned long flags;
1455 dma_addr_t bus_address;
1456 struct sk_buff *skb;
1457 struct nes_hw_nic_rq_wqe *nic_rqe;
1458 struct nes_hw_nic *nesnic;
1459 struct nes_device *nesdev;
1460 u32 rx_wqes_posted = 0;
1461
1462 nesnic = &nesvnic->nic;
1463 nesdev = nesvnic->nesdev;
1464 spin_lock_irqsave(&nesnic->rq_lock, flags);
1465 if (nesnic->replenishing_rq !=0) {
1466 if (((nesnic->rq_size-1) == atomic_read(&nesvnic->rx_skbs_needed)) &&
1467 (atomic_read(&nesvnic->rx_skb_timer_running) == 0)) {
1468 atomic_set(&nesvnic->rx_skb_timer_running, 1);
1469 spin_unlock_irqrestore(&nesnic->rq_lock, flags);
1470 nesvnic->rq_wqes_timer.expires = jiffies + (HZ/2); /* 1/2 second */
1471 add_timer(&nesvnic->rq_wqes_timer);
1472 } else
1473 spin_unlock_irqrestore(&nesnic->rq_lock, flags);
1474 return;
1475 }
1476 nesnic->replenishing_rq = 1;
1477 spin_unlock_irqrestore(&nesnic->rq_lock, flags);
1478 do {
1479 skb = dev_alloc_skb(nesvnic->max_frame_size);
1480 if (skb) {
1481 skb->dev = nesvnic->netdev;
1482
1483 bus_address = pci_map_single(nesdev->pcidev,
1484 skb->data, nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
1485
1486 nic_rqe = &nesnic->rq_vbase[nesvnic->nic.rq_head];
1487 nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] =
1488 cpu_to_le32(nesvnic->max_frame_size);
1489 nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_3_2_IDX] = 0;
1490 nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX] =
1491 cpu_to_le32((u32)bus_address);
1492 nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX] =
1493 cpu_to_le32((u32)((u64)bus_address >> 32));
1494 nesnic->rx_skb[nesnic->rq_head] = skb;
1495 nesnic->rq_head++;
1496 nesnic->rq_head &= nesnic->rq_size - 1;
1497 atomic_dec(&nesvnic->rx_skbs_needed);
1498 barrier();
1499 if (++rx_wqes_posted == 255) {
1500 nes_write32(nesdev->regs+NES_WQE_ALLOC, (rx_wqes_posted << 24) | nesnic->qp_id);
1501 rx_wqes_posted = 0;
1502 }
1503 } else {
1504 spin_lock_irqsave(&nesnic->rq_lock, flags);
1505 if (((nesnic->rq_size-1) == atomic_read(&nesvnic->rx_skbs_needed)) &&
1506 (atomic_read(&nesvnic->rx_skb_timer_running) == 0)) {
1507 atomic_set(&nesvnic->rx_skb_timer_running, 1);
1508 spin_unlock_irqrestore(&nesnic->rq_lock, flags);
1509 nesvnic->rq_wqes_timer.expires = jiffies + (HZ/2); /* 1/2 second */
1510 add_timer(&nesvnic->rq_wqes_timer);
1511 } else
1512 spin_unlock_irqrestore(&nesnic->rq_lock, flags);
1513 break;
1514 }
1515 } while (atomic_read(&nesvnic->rx_skbs_needed));
1516 barrier();
1517 if (rx_wqes_posted)
1518 nes_write32(nesdev->regs+NES_WQE_ALLOC, (rx_wqes_posted << 24) | nesnic->qp_id);
1519 nesnic->replenishing_rq = 0;
1520}
1521
1522
1523/**
1524 * nes_rq_wqes_timeout
1525 */
1526static void nes_rq_wqes_timeout(unsigned long parm)
1527{
1528 struct nes_vnic *nesvnic = (struct nes_vnic *)parm;
Harvey Harrison33718362008-04-16 21:01:10 -07001529 printk("%s: Timer fired.\n", __func__);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001530 atomic_set(&nesvnic->rx_skb_timer_running, 0);
1531 if (atomic_read(&nesvnic->rx_skbs_needed))
1532 nes_replenish_nic_rq(nesvnic);
1533}
1534
1535
Faisal Latif37dab412008-04-29 13:46:54 -07001536static int nes_lro_get_skb_hdr(struct sk_buff *skb, void **iphdr,
1537 void **tcph, u64 *hdr_flags, void *priv)
1538{
1539 unsigned int ip_len;
1540 struct iphdr *iph;
1541 skb_reset_network_header(skb);
1542 iph = ip_hdr(skb);
1543 if (iph->protocol != IPPROTO_TCP)
1544 return -1;
1545 ip_len = ip_hdrlen(skb);
1546 skb_set_transport_header(skb, ip_len);
1547 *tcph = tcp_hdr(skb);
1548
1549 *hdr_flags = LRO_IPV4 | LRO_TCP;
1550 *iphdr = iph;
1551 return 0;
1552}
1553
1554
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001555/**
1556 * nes_init_nic_qp
1557 */
1558int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
1559{
1560 struct nes_hw_cqp_wqe *cqp_wqe;
1561 struct nes_hw_nic_sq_wqe *nic_sqe;
1562 struct nes_hw_nic_qp_context *nic_context;
1563 struct sk_buff *skb;
1564 struct nes_hw_nic_rq_wqe *nic_rqe;
1565 struct nes_vnic *nesvnic = netdev_priv(netdev);
1566 unsigned long flags;
1567 void *vmem;
1568 dma_addr_t pmem;
1569 u64 u64temp;
1570 int ret;
1571 u32 cqp_head;
1572 u32 counter;
1573 u32 wqe_count;
1574 u8 jumbomode=0;
1575
1576 /* Allocate fragment, SQ, RQ, and CQ; Reuse CEQ based on the PCI function */
1577 nesvnic->nic_mem_size = 256 +
1578 (NES_NIC_WQ_SIZE * sizeof(struct nes_first_frag)) +
1579 (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_sq_wqe)) +
1580 (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_rq_wqe)) +
1581 (NES_NIC_WQ_SIZE * 2 * sizeof(struct nes_hw_nic_cqe)) +
1582 sizeof(struct nes_hw_nic_qp_context);
1583
1584 nesvnic->nic_vbase = pci_alloc_consistent(nesdev->pcidev, nesvnic->nic_mem_size,
1585 &nesvnic->nic_pbase);
1586 if (!nesvnic->nic_vbase) {
1587 nes_debug(NES_DBG_INIT, "Unable to allocate memory for NIC host descriptor rings\n");
1588 return -ENOMEM;
1589 }
1590 memset(nesvnic->nic_vbase, 0, nesvnic->nic_mem_size);
1591 nes_debug(NES_DBG_INIT, "Allocated NIC QP structures at %p (phys = %016lX), size = %u.\n",
1592 nesvnic->nic_vbase, (unsigned long)nesvnic->nic_pbase, nesvnic->nic_mem_size);
1593
1594 vmem = (void *)(((unsigned long)nesvnic->nic_vbase + (256 - 1)) &
1595 ~(unsigned long)(256 - 1));
1596 pmem = (dma_addr_t)(((unsigned long long)nesvnic->nic_pbase + (256 - 1)) &
1597 ~(unsigned long long)(256 - 1));
1598
1599 /* Setup the first Fragment buffers */
1600 nesvnic->nic.first_frag_vbase = vmem;
1601
1602 for (counter = 0; counter < NES_NIC_WQ_SIZE; counter++) {
1603 nesvnic->nic.frag_paddr[counter] = pmem;
1604 pmem += sizeof(struct nes_first_frag);
1605 }
1606
1607 /* setup the SQ */
1608 vmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_first_frag));
1609
1610 nesvnic->nic.sq_vbase = (void *)vmem;
1611 nesvnic->nic.sq_pbase = pmem;
1612 nesvnic->nic.sq_head = 0;
1613 nesvnic->nic.sq_tail = 0;
1614 nesvnic->nic.sq_size = NES_NIC_WQ_SIZE;
1615 for (counter = 0; counter < NES_NIC_WQ_SIZE; counter++) {
1616 nic_sqe = &nesvnic->nic.sq_vbase[counter];
1617 nic_sqe->wqe_words[NES_NIC_SQ_WQE_MISC_IDX] =
1618 cpu_to_le32(NES_NIC_SQ_WQE_DISABLE_CHKSUM |
1619 NES_NIC_SQ_WQE_COMPLETION);
1620 nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX] =
1621 cpu_to_le32((u32)NES_FIRST_FRAG_SIZE << 16);
1622 nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX] =
1623 cpu_to_le32((u32)nesvnic->nic.frag_paddr[counter]);
1624 nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX] =
1625 cpu_to_le32((u32)((u64)nesvnic->nic.frag_paddr[counter] >> 32));
1626 }
1627
1628 nesvnic->get_cqp_request = nes_get_cqp_request;
1629 nesvnic->post_cqp_request = nes_post_cqp_request;
1630 nesvnic->mcrq_mcast_filter = NULL;
1631
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001632 spin_lock_init(&nesvnic->nic.rq_lock);
1633
1634 /* setup the RQ */
1635 vmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_sq_wqe));
1636 pmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_sq_wqe));
1637
1638
1639 nesvnic->nic.rq_vbase = vmem;
1640 nesvnic->nic.rq_pbase = pmem;
1641 nesvnic->nic.rq_head = 0;
1642 nesvnic->nic.rq_tail = 0;
1643 nesvnic->nic.rq_size = NES_NIC_WQ_SIZE;
1644
1645 /* setup the CQ */
1646 vmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_rq_wqe));
1647 pmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_rq_wqe));
1648
1649 if (nesdev->nesadapter->netdev_count > 2)
1650 nesvnic->mcrq_qp_id = nesvnic->nic_index + 32;
1651 else
1652 nesvnic->mcrq_qp_id = nesvnic->nic.qp_id + 4;
1653
1654 nesvnic->nic_cq.cq_vbase = vmem;
1655 nesvnic->nic_cq.cq_pbase = pmem;
1656 nesvnic->nic_cq.cq_head = 0;
1657 nesvnic->nic_cq.cq_size = NES_NIC_WQ_SIZE * 2;
1658
1659 nesvnic->nic_cq.ce_handler = nes_nic_napi_ce_handler;
1660
1661 /* Send CreateCQ request to CQP */
1662 spin_lock_irqsave(&nesdev->cqp.lock, flags);
1663 cqp_head = nesdev->cqp.sq_head;
1664
1665 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1666 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
1667
1668 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(
1669 NES_CQP_CREATE_CQ | NES_CQP_CQ_CEQ_VALID |
1670 ((u32)nesvnic->nic_cq.cq_size << 16));
1671 cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(
1672 nesvnic->nic_cq.cq_number | ((u32)nesdev->nic_ceq_index << 16));
1673 u64temp = (u64)nesvnic->nic_cq.cq_pbase;
1674 set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);
1675 cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] = 0;
1676 u64temp = (unsigned long)&nesvnic->nic_cq;
1677 cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_LOW_IDX] = cpu_to_le32((u32)(u64temp >> 1));
1678 cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] =
1679 cpu_to_le32(((u32)((u64temp) >> 33)) & 0x7FFFFFFF);
1680 cqp_wqe->wqe_words[NES_CQP_CQ_WQE_DOORBELL_INDEX_HIGH_IDX] = 0;
1681 if (++cqp_head >= nesdev->cqp.sq_size)
1682 cqp_head = 0;
1683 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1684 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
1685
1686 /* Send CreateQP request to CQP */
1687 nic_context = (void *)(&nesvnic->nic_cq.cq_vbase[nesvnic->nic_cq.cq_size]);
1688 nic_context->context_words[NES_NIC_CTX_MISC_IDX] =
1689 cpu_to_le32((u32)NES_NIC_CTX_SIZE |
1690 ((u32)PCI_FUNC(nesdev->pcidev->devfn) << 12));
1691 nes_debug(NES_DBG_INIT, "RX_WINDOW_BUFFER_PAGE_TABLE_SIZE = 0x%08X, RX_WINDOW_BUFFER_SIZE = 0x%08X\n",
1692 nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_PAGE_TABLE_SIZE),
1693 nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_SIZE));
1694 if (nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_SIZE) != 0) {
1695 nic_context->context_words[NES_NIC_CTX_MISC_IDX] |= cpu_to_le32(NES_NIC_BACK_STORE);
1696 }
1697
1698 u64temp = (u64)nesvnic->nic.sq_pbase;
Glenn Streiff7495ab62008-04-29 13:46:54 -07001699 nic_context->context_words[NES_NIC_CTX_SQ_LOW_IDX] = cpu_to_le32((u32)u64temp);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001700 nic_context->context_words[NES_NIC_CTX_SQ_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32));
1701 u64temp = (u64)nesvnic->nic.rq_pbase;
Glenn Streiff7495ab62008-04-29 13:46:54 -07001702 nic_context->context_words[NES_NIC_CTX_RQ_LOW_IDX] = cpu_to_le32((u32)u64temp);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001703 nic_context->context_words[NES_NIC_CTX_RQ_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32));
1704
1705 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_CREATE_QP |
1706 NES_CQP_QP_TYPE_NIC);
1707 cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesvnic->nic.qp_id);
1708 u64temp = (u64)nesvnic->nic_cq.cq_pbase +
1709 (nesvnic->nic_cq.cq_size * sizeof(struct nes_hw_nic_cqe));
1710 set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, u64temp);
1711
1712 if (++cqp_head >= nesdev->cqp.sq_size)
1713 cqp_head = 0;
1714 nesdev->cqp.sq_head = cqp_head;
1715
1716 barrier();
1717
1718 /* Ring doorbell (2 WQEs) */
1719 nes_write32(nesdev->regs+NES_WQE_ALLOC, 0x02800000 | nesdev->cqp.qp_id);
1720
1721 spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
1722 nes_debug(NES_DBG_INIT, "Waiting for create NIC QP%u to complete.\n",
1723 nesvnic->nic.qp_id);
1724
1725 ret = wait_event_timeout(nesdev->cqp.waitq, (nesdev->cqp.sq_tail == cqp_head),
1726 NES_EVENT_TIMEOUT);
1727 nes_debug(NES_DBG_INIT, "Create NIC QP%u completed, wait_event_timeout ret = %u.\n",
1728 nesvnic->nic.qp_id, ret);
1729 if (!ret) {
1730 nes_debug(NES_DBG_INIT, "NIC QP%u create timeout expired\n", nesvnic->nic.qp_id);
1731 pci_free_consistent(nesdev->pcidev, nesvnic->nic_mem_size, nesvnic->nic_vbase,
1732 nesvnic->nic_pbase);
1733 return -EIO;
1734 }
1735
1736 /* Populate the RQ */
1737 for (counter = 0; counter < (NES_NIC_WQ_SIZE - 1); counter++) {
1738 skb = dev_alloc_skb(nesvnic->max_frame_size);
1739 if (!skb) {
1740 nes_debug(NES_DBG_INIT, "%s: out of memory for receive skb\n", netdev->name);
1741
1742 nes_destroy_nic_qp(nesvnic);
1743 return -ENOMEM;
1744 }
1745
1746 skb->dev = netdev;
1747
1748 pmem = pci_map_single(nesdev->pcidev, skb->data,
1749 nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
1750
1751 nic_rqe = &nesvnic->nic.rq_vbase[counter];
1752 nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] = cpu_to_le32(nesvnic->max_frame_size);
1753 nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_3_2_IDX] = 0;
Glenn Streiff7495ab62008-04-29 13:46:54 -07001754 nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX] = cpu_to_le32((u32)pmem);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001755 nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX] = cpu_to_le32((u32)((u64)pmem >> 32));
1756 nesvnic->nic.rx_skb[counter] = skb;
1757 }
1758
1759 wqe_count = NES_NIC_WQ_SIZE - 1;
1760 nesvnic->nic.rq_head = wqe_count;
1761 barrier();
1762 do {
1763 counter = min(wqe_count, ((u32)255));
1764 wqe_count -= counter;
1765 nes_write32(nesdev->regs+NES_WQE_ALLOC, (counter << 24) | nesvnic->nic.qp_id);
1766 } while (wqe_count);
1767 init_timer(&nesvnic->rq_wqes_timer);
1768 nesvnic->rq_wqes_timer.function = nes_rq_wqes_timeout;
1769 nesvnic->rq_wqes_timer.data = (unsigned long)nesvnic;
1770 nes_debug(NES_DBG_INIT, "NAPI support Enabled\n");
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001771 if (nesdev->nesadapter->et_use_adaptive_rx_coalesce)
1772 {
1773 nes_nic_init_timer(nesdev);
1774 if (netdev->mtu > 1500)
1775 jumbomode = 1;
Faisal Latif37dab412008-04-29 13:46:54 -07001776 nes_nic_init_timer_defaults(nesdev, jumbomode);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001777 }
Roland Dreierdd378182008-05-13 11:27:25 -07001778 nesvnic->lro_mgr.max_aggr = nes_lro_max_aggr;
Glenn Streiff7495ab62008-04-29 13:46:54 -07001779 nesvnic->lro_mgr.max_desc = NES_MAX_LRO_DESCRIPTORS;
1780 nesvnic->lro_mgr.lro_arr = nesvnic->lro_desc;
Faisal Latif37dab412008-04-29 13:46:54 -07001781 nesvnic->lro_mgr.get_skb_header = nes_lro_get_skb_hdr;
Glenn Streiff7495ab62008-04-29 13:46:54 -07001782 nesvnic->lro_mgr.features = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID;
1783 nesvnic->lro_mgr.dev = netdev;
1784 nesvnic->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY;
Faisal Latif37dab412008-04-29 13:46:54 -07001785 nesvnic->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001786 return 0;
1787}
1788
1789
1790/**
1791 * nes_destroy_nic_qp
1792 */
1793void nes_destroy_nic_qp(struct nes_vnic *nesvnic)
1794{
Bob Sharp7a8d1402008-09-26 15:08:10 -05001795 u64 u64temp;
1796 dma_addr_t bus_address;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001797 struct nes_device *nesdev = nesvnic->nesdev;
1798 struct nes_hw_cqp_wqe *cqp_wqe;
Bob Sharp7a8d1402008-09-26 15:08:10 -05001799 struct nes_hw_nic_sq_wqe *nic_sqe;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001800 struct nes_hw_nic_rq_wqe *nic_rqe;
Bob Sharp7a8d1402008-09-26 15:08:10 -05001801 __le16 *wqe_fragment_length;
1802 u16 wqe_fragment_index;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001803 u64 wqe_frag;
1804 u32 cqp_head;
1805 unsigned long flags;
1806 int ret;
1807
1808 /* Free remaining NIC receive buffers */
1809 while (nesvnic->nic.rq_head != nesvnic->nic.rq_tail) {
Glenn Streiff7495ab62008-04-29 13:46:54 -07001810 nic_rqe = &nesvnic->nic.rq_vbase[nesvnic->nic.rq_tail];
Bob Sharp7a8d1402008-09-26 15:08:10 -05001811 wqe_frag = (u64)le32_to_cpu(
1812 nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]);
1813 wqe_frag |= ((u64)le32_to_cpu(
1814 nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX]))<<32;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001815 pci_unmap_single(nesdev->pcidev, (dma_addr_t)wqe_frag,
1816 nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
1817 dev_kfree_skb(nesvnic->nic.rx_skb[nesvnic->nic.rq_tail++]);
1818 nesvnic->nic.rq_tail &= (nesvnic->nic.rq_size - 1);
1819 }
1820
Bob Sharp7a8d1402008-09-26 15:08:10 -05001821 /* Free remaining NIC transmit buffers */
1822 while (nesvnic->nic.sq_head != nesvnic->nic.sq_tail) {
1823 nic_sqe = &nesvnic->nic.sq_vbase[nesvnic->nic.sq_tail];
1824 wqe_fragment_index = 1;
1825 wqe_fragment_length = (__le16 *)
1826 &nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX];
1827 /* bump past the vlan tag */
1828 wqe_fragment_length++;
1829 if (le16_to_cpu(wqe_fragment_length[wqe_fragment_index]) != 0) {
1830 u64temp = (u64)le32_to_cpu(
1831 nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX+
1832 wqe_fragment_index*2]);
1833 u64temp += ((u64)le32_to_cpu(
1834 nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX
1835 + wqe_fragment_index*2]))<<32;
1836 bus_address = (dma_addr_t)u64temp;
1837 if (test_and_clear_bit(nesvnic->nic.sq_tail,
1838 nesvnic->nic.first_frag_overflow)) {
1839 pci_unmap_single(nesdev->pcidev,
1840 bus_address,
1841 le16_to_cpu(wqe_fragment_length[
1842 wqe_fragment_index++]),
1843 PCI_DMA_TODEVICE);
1844 }
1845 for (; wqe_fragment_index < 5; wqe_fragment_index++) {
1846 if (wqe_fragment_length[wqe_fragment_index]) {
1847 u64temp = le32_to_cpu(
1848 nic_sqe->wqe_words[
1849 NES_NIC_SQ_WQE_FRAG0_LOW_IDX+
1850 wqe_fragment_index*2]);
1851 u64temp += ((u64)le32_to_cpu(
1852 nic_sqe->wqe_words[
1853 NES_NIC_SQ_WQE_FRAG0_HIGH_IDX+
1854 wqe_fragment_index*2]))<<32;
1855 bus_address = (dma_addr_t)u64temp;
1856 pci_unmap_page(nesdev->pcidev,
1857 bus_address,
1858 le16_to_cpu(
1859 wqe_fragment_length[
1860 wqe_fragment_index]),
1861 PCI_DMA_TODEVICE);
1862 } else
1863 break;
1864 }
1865 }
1866 if (nesvnic->nic.tx_skb[nesvnic->nic.sq_tail])
1867 dev_kfree_skb(
1868 nesvnic->nic.tx_skb[nesvnic->nic.sq_tail]);
1869
1870 nesvnic->nic.sq_tail = (++nesvnic->nic.sq_tail)
1871 & (nesvnic->nic.sq_size - 1);
1872 }
1873
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001874 spin_lock_irqsave(&nesdev->cqp.lock, flags);
1875
1876 /* Destroy NIC QP */
1877 cqp_head = nesdev->cqp.sq_head;
1878 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1879 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
1880
1881 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
1882 (NES_CQP_DESTROY_QP | NES_CQP_QP_TYPE_NIC));
1883 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,
1884 nesvnic->nic.qp_id);
1885
1886 if (++cqp_head >= nesdev->cqp.sq_size)
1887 cqp_head = 0;
1888
1889 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1890
1891 /* Destroy NIC CQ */
1892 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
1893 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
1894 (NES_CQP_DESTROY_CQ | ((u32)nesvnic->nic_cq.cq_size << 16)));
1895 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,
1896 (nesvnic->nic_cq.cq_number | ((u32)nesdev->nic_ceq_index << 16)));
1897
1898 if (++cqp_head >= nesdev->cqp.sq_size)
1899 cqp_head = 0;
1900
1901 nesdev->cqp.sq_head = cqp_head;
1902 barrier();
1903
1904 /* Ring doorbell (2 WQEs) */
1905 nes_write32(nesdev->regs+NES_WQE_ALLOC, 0x02800000 | nesdev->cqp.qp_id);
1906
1907 spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
1908 nes_debug(NES_DBG_SHUTDOWN, "Waiting for CQP, cqp_head=%u, cqp.sq_head=%u,"
1909 " cqp.sq_tail=%u, cqp.sq_size=%u\n",
1910 cqp_head, nesdev->cqp.sq_head,
1911 nesdev->cqp.sq_tail, nesdev->cqp.sq_size);
1912
1913 ret = wait_event_timeout(nesdev->cqp.waitq, (nesdev->cqp.sq_tail == cqp_head),
1914 NES_EVENT_TIMEOUT);
1915
1916 nes_debug(NES_DBG_SHUTDOWN, "Destroy NIC QP returned, wait_event_timeout ret = %u, cqp_head=%u,"
1917 " cqp.sq_head=%u, cqp.sq_tail=%u\n",
1918 ret, cqp_head, nesdev->cqp.sq_head, nesdev->cqp.sq_tail);
1919 if (!ret) {
1920 nes_debug(NES_DBG_SHUTDOWN, "NIC QP%u destroy timeout expired\n",
1921 nesvnic->nic.qp_id);
1922 }
1923
1924 pci_free_consistent(nesdev->pcidev, nesvnic->nic_mem_size, nesvnic->nic_vbase,
1925 nesvnic->nic_pbase);
1926}
1927
1928/**
1929 * nes_napi_isr
1930 */
1931int nes_napi_isr(struct nes_device *nesdev)
1932{
1933 struct nes_adapter *nesadapter = nesdev->nesadapter;
1934 u32 int_stat;
1935
1936 if (nesdev->napi_isr_ran) {
1937 /* interrupt status has already been read in ISR */
1938 int_stat = nesdev->int_stat;
1939 } else {
1940 int_stat = nes_read32(nesdev->regs + NES_INT_STAT);
1941 nesdev->int_stat = int_stat;
1942 nesdev->napi_isr_ran = 1;
1943 }
1944
1945 int_stat &= nesdev->int_req;
1946 /* iff NIC, process here, else wait for DPC */
1947 if ((int_stat) && ((int_stat & 0x0000ff00) == int_stat)) {
1948 nesdev->napi_isr_ran = 0;
Glenn Streiff7495ab62008-04-29 13:46:54 -07001949 nes_write32(nesdev->regs + NES_INT_STAT,
1950 (int_stat &
1951 ~(NES_INT_INTF | NES_INT_TIMER | NES_INT_MAC0 | NES_INT_MAC1 | NES_INT_MAC2 | NES_INT_MAC3)));
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001952
1953 /* Process the CEQs */
1954 nes_process_ceq(nesdev, &nesdev->nesadapter->ceq[nesdev->nic_ceq_index]);
1955
1956 if (unlikely((((nesadapter->et_rx_coalesce_usecs_irq) &&
Glenn Streiff7495ab62008-04-29 13:46:54 -07001957 (!nesadapter->et_use_adaptive_rx_coalesce)) ||
1958 ((nesadapter->et_use_adaptive_rx_coalesce) &&
1959 (nesdev->deepcq_count > nesadapter->et_pkt_rate_low))))) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001960 if ((nesdev->int_req & NES_INT_TIMER) == 0) {
1961 /* Enable Periodic timer interrupts */
1962 nesdev->int_req |= NES_INT_TIMER;
1963 /* ack any pending periodic timer interrupts so we don't get an immediate interrupt */
1964 /* TODO: need to also ack other unused periodic timer values, get from nesadapter */
1965 nes_write32(nesdev->regs+NES_TIMER_STAT,
1966 nesdev->timer_int_req | ~(nesdev->nesadapter->timer_int_req));
1967 nes_write32(nesdev->regs+NES_INTF_INT_MASK,
1968 ~(nesdev->intf_int_req | NES_INTF_PERIODIC_TIMER));
1969 }
1970
1971 if (unlikely(nesadapter->et_use_adaptive_rx_coalesce))
1972 {
1973 nes_nic_init_timer(nesdev);
1974 }
1975 /* Enable interrupts, except CEQs */
1976 nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff | (~nesdev->int_req));
1977 } else {
1978 /* Enable interrupts, make sure timer is off */
1979 nesdev->int_req &= ~NES_INT_TIMER;
1980 nes_write32(nesdev->regs+NES_INTF_INT_MASK, ~(nesdev->intf_int_req));
1981 nes_write32(nesdev->regs+NES_INT_MASK, ~nesdev->int_req);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001982 }
1983 nesdev->deepcq_count = 0;
1984 return 1;
1985 } else {
1986 return 0;
1987 }
1988}
1989
Chien Tung9d156942008-09-26 15:08:10 -05001990static void process_critical_error(struct nes_device *nesdev)
1991{
1992 u32 debug_error;
1993 u32 nes_idx_debug_error_masks0 = 0;
1994 u16 error_module = 0;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001995
Chien Tung9d156942008-09-26 15:08:10 -05001996 debug_error = nes_read_indexed(nesdev, NES_IDX_DEBUG_ERROR_CONTROL_STATUS);
1997 printk(KERN_ERR PFX "Critical Error reported by device!!! 0x%02X\n",
1998 (u16)debug_error);
1999 nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_CONTROL_STATUS,
2000 0x01010000 | (debug_error & 0x0000ffff));
2001 if (crit_err_count++ > 10)
2002 nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS1, 1 << 0x17);
Chien Tunge2f5e732008-10-08 14:43:29 -07002003 error_module = (u16) (debug_error & 0x1F00) >> 8;
Chien Tung9d156942008-09-26 15:08:10 -05002004 if (++nesdev->nesadapter->crit_error_count[error_module-1] >=
2005 nes_max_critical_error_count) {
2006 printk(KERN_ERR PFX "Masking off critical error for module "
2007 "0x%02X\n", (u16)error_module);
2008 nes_idx_debug_error_masks0 = nes_read_indexed(nesdev,
2009 NES_IDX_DEBUG_ERROR_MASKS0);
2010 nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS0,
2011 nes_idx_debug_error_masks0 | (1 << error_module));
2012 }
2013}
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002014/**
2015 * nes_dpc
2016 */
2017void nes_dpc(unsigned long param)
2018{
2019 struct nes_device *nesdev = (struct nes_device *)param;
2020 struct nes_adapter *nesadapter = nesdev->nesadapter;
2021 u32 counter;
2022 u32 loop_counter = 0;
2023 u32 int_status_bit;
2024 u32 int_stat;
2025 u32 timer_stat;
2026 u32 temp_int_stat;
2027 u32 intf_int_stat;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002028 u32 processed_intf_int = 0;
2029 u16 processed_timer_int = 0;
2030 u16 completion_ints = 0;
2031 u16 timer_ints = 0;
2032
2033 /* nes_debug(NES_DBG_ISR, "\n"); */
2034
2035 do {
2036 timer_stat = 0;
2037 if (nesdev->napi_isr_ran) {
2038 nesdev->napi_isr_ran = 0;
2039 int_stat = nesdev->int_stat;
2040 } else
2041 int_stat = nes_read32(nesdev->regs+NES_INT_STAT);
2042 if (processed_intf_int != 0)
2043 int_stat &= nesdev->int_req & ~NES_INT_INTF;
2044 else
2045 int_stat &= nesdev->int_req;
2046 if (processed_timer_int == 0) {
2047 processed_timer_int = 1;
2048 if (int_stat & NES_INT_TIMER) {
2049 timer_stat = nes_read32(nesdev->regs + NES_TIMER_STAT);
2050 if ((timer_stat & nesdev->timer_int_req) == 0) {
2051 int_stat &= ~NES_INT_TIMER;
2052 }
2053 }
2054 } else {
2055 int_stat &= ~NES_INT_TIMER;
2056 }
2057
2058 if (int_stat) {
Glenn Streiff7495ab62008-04-29 13:46:54 -07002059 if (int_stat & ~(NES_INT_INTF | NES_INT_TIMER | NES_INT_MAC0|
2060 NES_INT_MAC1|NES_INT_MAC2 | NES_INT_MAC3)) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002061 /* Ack the interrupts */
2062 nes_write32(nesdev->regs+NES_INT_STAT,
Glenn Streiff7495ab62008-04-29 13:46:54 -07002063 (int_stat & ~(NES_INT_INTF | NES_INT_TIMER | NES_INT_MAC0|
2064 NES_INT_MAC1 | NES_INT_MAC2 | NES_INT_MAC3)));
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002065 }
2066
2067 temp_int_stat = int_stat;
2068 for (counter = 0, int_status_bit = 1; counter < 16; counter++) {
2069 if (int_stat & int_status_bit) {
2070 nes_process_ceq(nesdev, &nesadapter->ceq[counter]);
2071 temp_int_stat &= ~int_status_bit;
2072 completion_ints = 1;
2073 }
2074 if (!(temp_int_stat & 0x0000ffff))
2075 break;
2076 int_status_bit <<= 1;
2077 }
2078
2079 /* Process the AEQ for this pci function */
2080 int_status_bit = 1 << (16 + PCI_FUNC(nesdev->pcidev->devfn));
2081 if (int_stat & int_status_bit) {
2082 nes_process_aeq(nesdev, &nesadapter->aeq[PCI_FUNC(nesdev->pcidev->devfn)]);
2083 }
2084
2085 /* Process the MAC interrupt for this pci function */
2086 int_status_bit = 1 << (24 + nesdev->mac_index);
2087 if (int_stat & int_status_bit) {
2088 nes_process_mac_intr(nesdev, nesdev->mac_index);
2089 }
2090
2091 if (int_stat & NES_INT_TIMER) {
2092 if (timer_stat & nesdev->timer_int_req) {
2093 nes_write32(nesdev->regs + NES_TIMER_STAT,
2094 (timer_stat & nesdev->timer_int_req) |
2095 ~(nesdev->nesadapter->timer_int_req));
2096 timer_ints = 1;
2097 }
2098 }
2099
2100 if (int_stat & NES_INT_INTF) {
2101 processed_intf_int = 1;
2102 intf_int_stat = nes_read32(nesdev->regs+NES_INTF_INT_STAT);
2103 intf_int_stat &= nesdev->intf_int_req;
2104 if (NES_INTF_INT_CRITERR & intf_int_stat) {
Chien Tung9d156942008-09-26 15:08:10 -05002105 process_critical_error(nesdev);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002106 }
2107 if (NES_INTF_INT_PCIERR & intf_int_stat) {
2108 printk(KERN_ERR PFX "PCI Error reported by device!!!\n");
2109 BUG();
2110 }
2111 if (NES_INTF_INT_AEQ_OFLOW & intf_int_stat) {
2112 printk(KERN_ERR PFX "AEQ Overflow reported by device!!!\n");
2113 BUG();
2114 }
2115 nes_write32(nesdev->regs+NES_INTF_INT_STAT, intf_int_stat);
2116 }
2117
2118 if (int_stat & NES_INT_TSW) {
2119 }
2120 }
2121 /* Don't use the interface interrupt bit stay in loop */
Glenn Streiff7495ab62008-04-29 13:46:54 -07002122 int_stat &= ~NES_INT_INTF | NES_INT_TIMER | NES_INT_MAC0 |
2123 NES_INT_MAC1 | NES_INT_MAC2 | NES_INT_MAC3;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002124 } while ((int_stat != 0) && (loop_counter++ < MAX_DPC_ITERATIONS));
2125
2126 if (timer_ints == 1) {
2127 if ((nesadapter->et_rx_coalesce_usecs_irq) || (nesadapter->et_use_adaptive_rx_coalesce)) {
2128 if (completion_ints == 0) {
2129 nesdev->timer_only_int_count++;
2130 if (nesdev->timer_only_int_count>=nesadapter->timer_int_limit) {
2131 nesdev->timer_only_int_count = 0;
2132 nesdev->int_req &= ~NES_INT_TIMER;
2133 nes_write32(nesdev->regs + NES_INTF_INT_MASK, ~(nesdev->intf_int_req));
Glenn Streiff7495ab62008-04-29 13:46:54 -07002134 nes_write32(nesdev->regs + NES_INT_MASK, ~nesdev->int_req);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002135 } else {
Glenn Streiff7495ab62008-04-29 13:46:54 -07002136 nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff | (~nesdev->int_req));
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002137 }
2138 } else {
2139 if (unlikely(nesadapter->et_use_adaptive_rx_coalesce))
2140 {
2141 nes_nic_init_timer(nesdev);
2142 }
2143 nesdev->timer_only_int_count = 0;
Glenn Streiff7495ab62008-04-29 13:46:54 -07002144 nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff | (~nesdev->int_req));
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002145 }
2146 } else {
2147 nesdev->timer_only_int_count = 0;
2148 nesdev->int_req &= ~NES_INT_TIMER;
2149 nes_write32(nesdev->regs+NES_INTF_INT_MASK, ~(nesdev->intf_int_req));
2150 nes_write32(nesdev->regs+NES_TIMER_STAT,
2151 nesdev->timer_int_req | ~(nesdev->nesadapter->timer_int_req));
2152 nes_write32(nesdev->regs+NES_INT_MASK, ~nesdev->int_req);
2153 }
2154 } else {
2155 if ( (completion_ints == 1) &&
2156 (((nesadapter->et_rx_coalesce_usecs_irq) &&
2157 (!nesadapter->et_use_adaptive_rx_coalesce)) ||
2158 ((nesdev->deepcq_count > nesadapter->et_pkt_rate_low) &&
2159 (nesadapter->et_use_adaptive_rx_coalesce) )) ) {
2160 /* nes_debug(NES_DBG_ISR, "Enabling periodic timer interrupt.\n" ); */
2161 nesdev->timer_only_int_count = 0;
2162 nesdev->int_req |= NES_INT_TIMER;
2163 nes_write32(nesdev->regs+NES_TIMER_STAT,
2164 nesdev->timer_int_req | ~(nesdev->nesadapter->timer_int_req));
2165 nes_write32(nesdev->regs+NES_INTF_INT_MASK,
2166 ~(nesdev->intf_int_req | NES_INTF_PERIODIC_TIMER));
2167 nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff | (~nesdev->int_req));
2168 } else {
2169 nes_write32(nesdev->regs+NES_INT_MASK, ~nesdev->int_req);
2170 }
2171 }
2172 nesdev->deepcq_count = 0;
2173}
2174
2175
2176/**
2177 * nes_process_ceq
2178 */
Roland Dreier1a855fbf2008-04-16 21:01:09 -07002179static void nes_process_ceq(struct nes_device *nesdev, struct nes_hw_ceq *ceq)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002180{
2181 u64 u64temp;
2182 struct nes_hw_cq *cq;
2183 u32 head;
2184 u32 ceq_size;
2185
2186 /* nes_debug(NES_DBG_CQ, "\n"); */
2187 head = ceq->ceq_head;
2188 ceq_size = ceq->ceq_size;
2189
2190 do {
2191 if (le32_to_cpu(ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_HIGH_IDX]) &
2192 NES_CEQE_VALID) {
Glenn Streiff7495ab62008-04-29 13:46:54 -07002193 u64temp = (((u64)(le32_to_cpu(ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_HIGH_IDX]))) << 32) |
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002194 ((u64)(le32_to_cpu(ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_LOW_IDX])));
2195 u64temp <<= 1;
2196 cq = *((struct nes_hw_cq **)&u64temp);
2197 /* nes_debug(NES_DBG_CQ, "pCQ = %p\n", cq); */
2198 barrier();
2199 ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_HIGH_IDX] = 0;
2200
2201 /* call the event handler */
2202 cq->ce_handler(nesdev, cq);
2203
2204 if (++head >= ceq_size)
2205 head = 0;
2206 } else {
2207 break;
2208 }
2209
2210 } while (1);
2211
2212 ceq->ceq_head = head;
2213}
2214
2215
2216/**
2217 * nes_process_aeq
2218 */
Roland Dreier1a855fbf2008-04-16 21:01:09 -07002219static void nes_process_aeq(struct nes_device *nesdev, struct nes_hw_aeq *aeq)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002220{
Glenn Streiff7495ab62008-04-29 13:46:54 -07002221 /* u64 u64temp; */
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002222 u32 head;
2223 u32 aeq_size;
2224 u32 aeqe_misc;
2225 u32 aeqe_cq_id;
2226 struct nes_hw_aeqe volatile *aeqe;
2227
2228 head = aeq->aeq_head;
2229 aeq_size = aeq->aeq_size;
2230
2231 do {
2232 aeqe = &aeq->aeq_vbase[head];
2233 if ((le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]) & NES_AEQE_VALID) == 0)
2234 break;
2235 aeqe_misc = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]);
2236 aeqe_cq_id = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]);
2237 if (aeqe_misc & (NES_AEQE_QP|NES_AEQE_CQ)) {
2238 if (aeqe_cq_id >= NES_FIRST_QPN) {
2239 /* dealing with an accelerated QP related AE */
Glenn Streiff7495ab62008-04-29 13:46:54 -07002240 /*
2241 * u64temp = (((u64)(le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX]))) << 32) |
2242 * ((u64)(le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX])));
2243 */
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002244 nes_process_iwarp_aeqe(nesdev, (struct nes_hw_aeqe *)aeqe);
2245 } else {
2246 /* TODO: dealing with a CQP related AE */
2247 nes_debug(NES_DBG_AEQ, "Processing CQP related AE, misc = 0x%04X\n",
2248 (u16)(aeqe_misc >> 16));
2249 }
2250 }
2251
2252 aeqe->aeqe_words[NES_AEQE_MISC_IDX] = 0;
2253
2254 if (++head >= aeq_size)
2255 head = 0;
Don Woodfd877782009-03-06 15:12:11 -08002256
2257 nes_write32(nesdev->regs + NES_AEQ_ALLOC, 1 << 16);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002258 }
2259 while (1);
2260 aeq->aeq_head = head;
2261}
2262
2263static void nes_reset_link(struct nes_device *nesdev, u32 mac_index)
2264{
2265 struct nes_adapter *nesadapter = nesdev->nesadapter;
2266 u32 reset_value;
2267 u32 i=0;
2268 u32 u32temp;
2269
2270 if (nesadapter->hw_rev == NE020_REV) {
2271 return;
2272 }
2273 mh_detected++;
2274
2275 reset_value = nes_read32(nesdev->regs+NES_SOFTWARE_RESET);
2276
2277 if ((mac_index == 0) || ((mac_index == 1) && (nesadapter->OneG_Mode)))
2278 reset_value |= 0x0000001d;
2279 else
2280 reset_value |= 0x0000002d;
2281
2282 if (4 <= (nesadapter->link_interrupt_count[mac_index] / ((u16)NES_MAX_LINK_INTERRUPTS))) {
2283 if ((!nesadapter->OneG_Mode) && (nesadapter->port_count == 2)) {
2284 nesadapter->link_interrupt_count[0] = 0;
2285 nesadapter->link_interrupt_count[1] = 0;
2286 u32temp = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1);
2287 if (0x00000040 & u32temp)
2288 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F088);
2289 else
2290 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F0C8);
2291
2292 reset_value |= 0x0000003d;
2293 }
2294 nesadapter->link_interrupt_count[mac_index] = 0;
2295 }
2296
2297 nes_write32(nesdev->regs+NES_SOFTWARE_RESET, reset_value);
2298
2299 while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET)
2300 & 0x00000040) != 0x00000040) && (i++ < 5000));
2301
2302 if (0x0000003d == (reset_value & 0x0000003d)) {
2303 u32 pcs_control_status0, pcs_control_status1;
2304
2305 for (i = 0; i < 10; i++) {
2306 pcs_control_status0 = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0);
2307 pcs_control_status1 = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200);
2308 if (((0x0F000000 == (pcs_control_status0 & 0x0F000000))
2309 && (pcs_control_status0 & 0x00100000))
2310 || ((0x0F000000 == (pcs_control_status1 & 0x0F000000))
2311 && (pcs_control_status1 & 0x00100000)))
2312 continue;
2313 else
2314 break;
2315 }
2316 if (10 == i) {
2317 u32temp = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1);
2318 if (0x00000040 & u32temp)
2319 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F088);
2320 else
2321 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F0C8);
2322
2323 nes_write32(nesdev->regs+NES_SOFTWARE_RESET, reset_value);
2324
2325 while (((nes_read32(nesdev->regs + NES_SOFTWARE_RESET)
2326 & 0x00000040) != 0x00000040) && (i++ < 5000));
2327 }
2328 }
2329}
2330
2331/**
2332 * nes_process_mac_intr
2333 */
Roland Dreier1a855fbf2008-04-16 21:01:09 -07002334static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002335{
2336 unsigned long flags;
2337 u32 pcs_control_status;
2338 struct nes_adapter *nesadapter = nesdev->nesadapter;
2339 struct nes_vnic *nesvnic;
2340 u32 mac_status;
2341 u32 mac_index = nesdev->mac_index;
2342 u32 u32temp;
2343 u16 phy_data;
2344 u16 temp_phy_data;
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002345 u32 pcs_val = 0x0f0f0000;
2346 u32 pcs_mask = 0x0f1f0000;
Chien Tunga4849fc2009-04-08 14:27:18 -07002347 u32 cdr_ctrl;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002348
2349 spin_lock_irqsave(&nesadapter->phy_lock, flags);
2350 if (nesadapter->mac_sw_state[mac_number] != NES_MAC_SW_IDLE) {
2351 spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
2352 return;
2353 }
2354 nesadapter->mac_sw_state[mac_number] = NES_MAC_SW_INTERRUPT;
2355 spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
2356
2357 /* ack the MAC interrupt */
2358 mac_status = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (mac_index * 0x200));
2359 /* Clear the interrupt */
2360 nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (mac_index * 0x200), mac_status);
2361
2362 nes_debug(NES_DBG_PHY, "MAC%u interrupt status = 0x%X.\n", mac_number, mac_status);
2363
2364 if (mac_status & (NES_MAC_INT_LINK_STAT_CHG | NES_MAC_INT_XGMII_EXT)) {
2365 nesdev->link_status_interrupts++;
2366 if (0 == (++nesadapter->link_interrupt_count[mac_index] % ((u16)NES_MAX_LINK_INTERRUPTS))) {
2367 spin_lock_irqsave(&nesadapter->phy_lock, flags);
2368 nes_reset_link(nesdev, mac_index);
2369 spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
2370 }
2371 /* read the PHY interrupt status register */
Chien Tungfcb7ad32008-09-30 14:49:44 -07002372 if ((nesadapter->OneG_Mode) &&
2373 (nesadapter->phy_type[mac_index] != NES_PHY_TYPE_PUMA_1G)) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002374 do {
2375 nes_read_1G_phy_reg(nesdev, 0x1a,
2376 nesadapter->phy_index[mac_index], &phy_data);
2377 nes_debug(NES_DBG_PHY, "Phy%d data from register 0x1a = 0x%X.\n",
2378 nesadapter->phy_index[mac_index], phy_data);
2379 } while (phy_data&0x8000);
2380
2381 temp_phy_data = 0;
2382 do {
2383 nes_read_1G_phy_reg(nesdev, 0x11,
2384 nesadapter->phy_index[mac_index], &phy_data);
2385 nes_debug(NES_DBG_PHY, "Phy%d data from register 0x11 = 0x%X.\n",
2386 nesadapter->phy_index[mac_index], phy_data);
2387 if (temp_phy_data == phy_data)
2388 break;
2389 temp_phy_data = phy_data;
2390 } while (1);
2391
2392 nes_read_1G_phy_reg(nesdev, 0x1e,
2393 nesadapter->phy_index[mac_index], &phy_data);
2394 nes_debug(NES_DBG_PHY, "Phy%d data from register 0x1e = 0x%X.\n",
2395 nesadapter->phy_index[mac_index], phy_data);
2396
2397 nes_read_1G_phy_reg(nesdev, 1,
2398 nesadapter->phy_index[mac_index], &phy_data);
2399 nes_debug(NES_DBG_PHY, "1G phy%u data from register 1 = 0x%X\n",
2400 nesadapter->phy_index[mac_index], phy_data);
2401
2402 if (temp_phy_data & 0x1000) {
2403 nes_debug(NES_DBG_PHY, "The Link is up according to the PHY\n");
2404 phy_data = 4;
2405 } else {
2406 nes_debug(NES_DBG_PHY, "The Link is down according to the PHY\n");
2407 }
2408 }
2409 nes_debug(NES_DBG_PHY, "Eth SERDES Common Status: 0=0x%08X, 1=0x%08X\n",
2410 nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0),
2411 nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0+0x200));
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002412
2413 if (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_PUMA_1G) {
2414 switch (mac_index) {
2415 case 1:
2416 case 3:
2417 pcs_control_status = nes_read_indexed(nesdev,
2418 NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200);
2419 break;
2420 default:
2421 pcs_control_status = nes_read_indexed(nesdev,
2422 NES_IDX_PHY_PCS_CONTROL_STATUS0);
2423 break;
2424 }
2425 } else {
2426 pcs_control_status = nes_read_indexed(nesdev,
2427 NES_IDX_PHY_PCS_CONTROL_STATUS0 + ((mac_index & 1) * 0x200));
2428 pcs_control_status = nes_read_indexed(nesdev,
2429 NES_IDX_PHY_PCS_CONTROL_STATUS0 + ((mac_index & 1) * 0x200));
2430 }
2431
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002432 nes_debug(NES_DBG_PHY, "PCS PHY Control/Status%u: 0x%08X\n",
2433 mac_index, pcs_control_status);
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002434 if ((nesadapter->OneG_Mode) &&
2435 (nesadapter->phy_type[mac_index] != NES_PHY_TYPE_PUMA_1G)) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002436 u32temp = 0x01010000;
2437 if (nesadapter->port_count > 2) {
2438 u32temp |= 0x02020000;
2439 }
2440 if ((pcs_control_status & u32temp)!= u32temp) {
2441 phy_data = 0;
2442 nes_debug(NES_DBG_PHY, "PCS says the link is down\n");
2443 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002444 } else {
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002445 switch (nesadapter->phy_type[mac_index]) {
2446 case NES_PHY_TYPE_IRIS:
2447 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 1);
2448 temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
2449 u32temp = 20;
2450 do {
2451 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 1);
2452 phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
2453 if ((phy_data == temp_phy_data) || (!(--u32temp)))
2454 break;
2455 temp_phy_data = phy_data;
2456 } while (1);
2457 nes_debug(NES_DBG_PHY, "%s: Phy data = 0x%04X, link was %s.\n",
2458 __func__, phy_data, nesadapter->mac_link_down[mac_index] ? "DOWN" : "UP");
2459 break;
2460
2461 case NES_PHY_TYPE_ARGUS:
Chien Tung43035652009-04-08 14:27:56 -07002462 case NES_PHY_TYPE_SFP_D:
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002463 /* clear the alarms */
2464 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0x0008);
2465 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0xc001);
2466 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0xc002);
2467 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0xc005);
2468 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0xc006);
2469 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9003);
2470 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9004);
2471 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9005);
2472 /* check link status */
Chien Tung1b949322009-04-08 14:27:09 -07002473 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9003);
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002474 temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002475
Chien Tung1b949322009-04-08 14:27:09 -07002476 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 3, 0x0021);
2477 nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
2478 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 3, 0x0021);
2479 phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
2480
2481 phy_data = (!temp_phy_data && (phy_data == 0x8000)) ? 0x4 : 0x0;
2482
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002483 nes_debug(NES_DBG_PHY, "%s: Phy data = 0x%04X, link was %s.\n",
Chien Tung1b949322009-04-08 14:27:09 -07002484 __func__, phy_data, nesadapter->mac_link_down[mac_index] ? "DOWN" : "UP");
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002485 break;
2486
2487 case NES_PHY_TYPE_PUMA_1G:
2488 if (mac_index < 2)
2489 pcs_val = pcs_mask = 0x01010000;
2490 else
2491 pcs_val = pcs_mask = 0x02020000;
2492 /* fall through */
2493 default:
2494 phy_data = (pcs_val == (pcs_control_status & pcs_mask)) ? 0x4 : 0x0;
2495 break;
2496 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002497 }
2498
2499 if (phy_data & 0x0004) {
Chien Tunga4849fc2009-04-08 14:27:18 -07002500 if (wide_ppm_offset &&
2501 (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_CX4) &&
2502 (nesadapter->hw_rev != NE020_REV)) {
2503 cdr_ctrl = nes_read_indexed(nesdev,
2504 NES_IDX_ETH_SERDES_CDR_CONTROL0 +
2505 mac_index * 0x200);
2506 nes_write_indexed(nesdev,
2507 NES_IDX_ETH_SERDES_CDR_CONTROL0 +
2508 mac_index * 0x200,
2509 cdr_ctrl | 0x000F0000);
2510 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002511 nesadapter->mac_link_down[mac_index] = 0;
2512 list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) {
2513 nes_debug(NES_DBG_PHY, "The Link is UP!!. linkup was %d\n",
2514 nesvnic->linkup);
2515 if (nesvnic->linkup == 0) {
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002516 printk(PFX "The Link is now up for port %s, netdev %p.\n",
2517 nesvnic->netdev->name, nesvnic->netdev);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002518 if (netif_queue_stopped(nesvnic->netdev))
2519 netif_start_queue(nesvnic->netdev);
2520 nesvnic->linkup = 1;
2521 netif_carrier_on(nesvnic->netdev);
2522 }
2523 }
2524 } else {
Chien Tunga4849fc2009-04-08 14:27:18 -07002525 if (wide_ppm_offset &&
2526 (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_CX4) &&
2527 (nesadapter->hw_rev != NE020_REV)) {
2528 cdr_ctrl = nes_read_indexed(nesdev,
2529 NES_IDX_ETH_SERDES_CDR_CONTROL0 +
2530 mac_index * 0x200);
2531 nes_write_indexed(nesdev,
2532 NES_IDX_ETH_SERDES_CDR_CONTROL0 +
2533 mac_index * 0x200,
2534 cdr_ctrl & 0xFFF0FFFF);
2535 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002536 nesadapter->mac_link_down[mac_index] = 1;
2537 list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) {
2538 nes_debug(NES_DBG_PHY, "The Link is Down!!. linkup was %d\n",
2539 nesvnic->linkup);
2540 if (nesvnic->linkup == 1) {
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002541 printk(PFX "The Link is now down for port %s, netdev %p.\n",
2542 nesvnic->netdev->name, nesvnic->netdev);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002543 if (!(netif_queue_stopped(nesvnic->netdev)))
2544 netif_stop_queue(nesvnic->netdev);
2545 nesvnic->linkup = 0;
2546 netif_carrier_off(nesvnic->netdev);
2547 }
2548 }
2549 }
2550 }
2551
2552 nesadapter->mac_sw_state[mac_number] = NES_MAC_SW_IDLE;
2553}
2554
2555
2556
Roland Dreier1a855fbf2008-04-16 21:01:09 -07002557static void nes_nic_napi_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002558{
2559 struct nes_vnic *nesvnic = container_of(cq, struct nes_vnic, nic_cq);
2560
Ben Hutchings288379f2009-01-19 16:43:59 -08002561 napi_schedule(&nesvnic->napi);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002562}
2563
2564
2565/* The MAX_RQES_TO_PROCESS defines how many max read requests to complete before
2566* getting out of nic_ce_handler
2567*/
2568#define MAX_RQES_TO_PROCESS 384
2569
2570/**
2571 * nes_nic_ce_handler
2572 */
2573void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
2574{
2575 u64 u64temp;
2576 dma_addr_t bus_address;
2577 struct nes_hw_nic *nesnic;
2578 struct nes_vnic *nesvnic = container_of(cq, struct nes_vnic, nic_cq);
2579 struct nes_adapter *nesadapter = nesdev->nesadapter;
2580 struct nes_hw_nic_rq_wqe *nic_rqe;
2581 struct nes_hw_nic_sq_wqe *nic_sqe;
2582 struct sk_buff *skb;
2583 struct sk_buff *rx_skb;
2584 __le16 *wqe_fragment_length;
2585 u32 head;
2586 u32 cq_size;
2587 u32 rx_pkt_size;
2588 u32 cqe_count=0;
2589 u32 cqe_errv;
2590 u32 cqe_misc;
2591 u16 wqe_fragment_index = 1; /* first fragment (0) is used by copy buffer */
2592 u16 vlan_tag;
2593 u16 pkt_type;
2594 u16 rqes_processed = 0;
2595 u8 sq_cqes = 0;
Faisal Latif37dab412008-04-29 13:46:54 -07002596 u8 nes_use_lro = 0;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002597
2598 head = cq->cq_head;
2599 cq_size = cq->cq_size;
2600 cq->cqes_pending = 1;
Faisal Latif37dab412008-04-29 13:46:54 -07002601 if (nesvnic->netdev->features & NETIF_F_LRO)
2602 nes_use_lro = 1;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002603 do {
2604 if (le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX]) &
2605 NES_NIC_CQE_VALID) {
2606 nesnic = &nesvnic->nic;
2607 cqe_misc = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX]);
2608 if (cqe_misc & NES_NIC_CQE_SQ) {
2609 sq_cqes++;
2610 wqe_fragment_index = 1;
2611 nic_sqe = &nesnic->sq_vbase[nesnic->sq_tail];
2612 skb = nesnic->tx_skb[nesnic->sq_tail];
2613 wqe_fragment_length = (__le16 *)&nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX];
2614 /* bump past the vlan tag */
2615 wqe_fragment_length++;
2616 if (le16_to_cpu(wqe_fragment_length[wqe_fragment_index]) != 0) {
Glenn Streiff7495ab62008-04-29 13:46:54 -07002617 u64temp = (u64) le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX +
2618 wqe_fragment_index * 2]);
2619 u64temp += ((u64)le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX +
2620 wqe_fragment_index * 2])) << 32;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002621 bus_address = (dma_addr_t)u64temp;
2622 if (test_and_clear_bit(nesnic->sq_tail, nesnic->first_frag_overflow)) {
2623 pci_unmap_single(nesdev->pcidev,
2624 bus_address,
2625 le16_to_cpu(wqe_fragment_length[wqe_fragment_index++]),
2626 PCI_DMA_TODEVICE);
2627 }
2628 for (; wqe_fragment_index < 5; wqe_fragment_index++) {
2629 if (wqe_fragment_length[wqe_fragment_index]) {
Glenn Streiff7495ab62008-04-29 13:46:54 -07002630 u64temp = le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX +
2631 wqe_fragment_index * 2]);
2632 u64temp += ((u64)le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX
2633 + wqe_fragment_index * 2])) <<32;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002634 bus_address = (dma_addr_t)u64temp;
2635 pci_unmap_page(nesdev->pcidev,
2636 bus_address,
2637 le16_to_cpu(wqe_fragment_length[wqe_fragment_index]),
2638 PCI_DMA_TODEVICE);
2639 } else
2640 break;
2641 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002642 }
Faisal Latif28699752009-03-06 15:12:11 -08002643 if (skb)
2644 dev_kfree_skb_any(skb);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002645 nesnic->sq_tail++;
2646 nesnic->sq_tail &= nesnic->sq_size-1;
2647 if (sq_cqes > 128) {
2648 barrier();
2649 /* restart the queue if it had been stopped */
2650 if (netif_queue_stopped(nesvnic->netdev))
2651 netif_wake_queue(nesvnic->netdev);
2652 sq_cqes = 0;
2653 }
2654 } else {
2655 rqes_processed ++;
2656
2657 cq->rx_cqes_completed++;
2658 cq->rx_pkts_indicated++;
2659 rx_pkt_size = cqe_misc & 0x0000ffff;
2660 nic_rqe = &nesnic->rq_vbase[nesnic->rq_tail];
2661 /* Get the skb */
2662 rx_skb = nesnic->rx_skb[nesnic->rq_tail];
2663 nic_rqe = &nesnic->rq_vbase[nesvnic->nic.rq_tail];
2664 bus_address = (dma_addr_t)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]);
2665 bus_address += ((u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX])) << 32;
2666 pci_unmap_single(nesdev->pcidev, bus_address,
2667 nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
2668 /* rx_skb->tail = rx_skb->data + rx_pkt_size; */
2669 /* rx_skb->len = rx_pkt_size; */
2670 rx_skb->len = 0; /* TODO: see if this is necessary */
2671 skb_put(rx_skb, rx_pkt_size);
2672 rx_skb->protocol = eth_type_trans(rx_skb, nesvnic->netdev);
2673 nesnic->rq_tail++;
2674 nesnic->rq_tail &= nesnic->rq_size - 1;
2675
2676 atomic_inc(&nesvnic->rx_skbs_needed);
2677 if (atomic_read(&nesvnic->rx_skbs_needed) > (nesvnic->nic.rq_size>>1)) {
2678 nes_write32(nesdev->regs+NES_CQE_ALLOC,
2679 cq->cq_number | (cqe_count << 16));
Glenn Streiff7495ab62008-04-29 13:46:54 -07002680 /* nesadapter->tune_timer.cq_count += cqe_count; */
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002681 nesdev->currcq_count += cqe_count;
2682 cqe_count = 0;
2683 nes_replenish_nic_rq(nesvnic);
2684 }
2685 pkt_type = (u16)(le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_TAG_PKT_TYPE_IDX]));
2686 cqe_errv = (cqe_misc & NES_NIC_CQE_ERRV_MASK) >> NES_NIC_CQE_ERRV_SHIFT;
2687 rx_skb->ip_summed = CHECKSUM_NONE;
2688
2689 if ((NES_PKT_TYPE_TCPV4_BITS == (pkt_type & NES_PKT_TYPE_TCPV4_MASK)) ||
2690 (NES_PKT_TYPE_UDPV4_BITS == (pkt_type & NES_PKT_TYPE_UDPV4_MASK))) {
2691 if ((cqe_errv &
2692 (NES_NIC_ERRV_BITS_IPV4_CSUM_ERR | NES_NIC_ERRV_BITS_TCPUDP_CSUM_ERR |
2693 NES_NIC_ERRV_BITS_IPH_ERR | NES_NIC_ERRV_BITS_WQE_OVERRUN)) == 0) {
2694 if (nesvnic->rx_checksum_disabled == 0) {
2695 rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
2696 }
2697 } else
2698 nes_debug(NES_DBG_CQ, "%s: unsuccessfully checksummed TCP or UDP packet."
2699 " errv = 0x%X, pkt_type = 0x%X.\n",
2700 nesvnic->netdev->name, cqe_errv, pkt_type);
2701
2702 } else if ((pkt_type & NES_PKT_TYPE_IPV4_MASK) == NES_PKT_TYPE_IPV4_BITS) {
2703 if ((cqe_errv &
2704 (NES_NIC_ERRV_BITS_IPV4_CSUM_ERR | NES_NIC_ERRV_BITS_IPH_ERR |
2705 NES_NIC_ERRV_BITS_WQE_OVERRUN)) == 0) {
2706 if (nesvnic->rx_checksum_disabled == 0) {
2707 rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
2708 /* nes_debug(NES_DBG_CQ, "%s: Reporting successfully checksummed IPv4 packet.\n",
2709 nesvnic->netdev->name); */
2710 }
2711 } else
2712 nes_debug(NES_DBG_CQ, "%s: unsuccessfully checksummed TCP or UDP packet."
2713 " errv = 0x%X, pkt_type = 0x%X.\n",
2714 nesvnic->netdev->name, cqe_errv, pkt_type);
2715 }
2716 /* nes_debug(NES_DBG_CQ, "pkt_type=%x, APBVT_MASK=%x\n",
2717 pkt_type, (pkt_type & NES_PKT_TYPE_APBVT_MASK)); */
2718
2719 if ((pkt_type & NES_PKT_TYPE_APBVT_MASK) == NES_PKT_TYPE_APBVT_BITS) {
Faisal Latif4a14f6a2008-11-21 20:50:49 -06002720 if (nes_cm_recv(rx_skb, nesvnic->netdev))
2721 rx_skb = NULL;
2722 }
2723 if (rx_skb == NULL)
2724 goto skip_rx_indicate0;
2725
2726
2727 if ((cqe_misc & NES_NIC_CQE_TAG_VALID) &&
2728 (nesvnic->vlan_grp != NULL)) {
2729 vlan_tag = (u16)(le32_to_cpu(
2730 cq->cq_vbase[head].cqe_words[NES_NIC_CQE_TAG_PKT_TYPE_IDX])
2731 >> 16);
2732 nes_debug(NES_DBG_CQ, "%s: Reporting stripped VLAN packet. Tag = 0x%04X\n",
2733 nesvnic->netdev->name, vlan_tag);
2734 if (nes_use_lro)
2735 lro_vlan_hwaccel_receive_skb(&nesvnic->lro_mgr, rx_skb,
2736 nesvnic->vlan_grp, vlan_tag, NULL);
2737 else
2738 nes_vlan_rx(rx_skb, nesvnic->vlan_grp, vlan_tag);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002739 } else {
Faisal Latif4a14f6a2008-11-21 20:50:49 -06002740 if (nes_use_lro)
2741 lro_receive_skb(&nesvnic->lro_mgr, rx_skb, NULL);
2742 else
2743 nes_netif_rx(rx_skb);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002744 }
2745
Faisal Latif4a14f6a2008-11-21 20:50:49 -06002746skip_rx_indicate0:
Eric Dumazet451f1442009-08-31 06:34:50 +00002747 ;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002748 /* nesvnic->netstats.rx_packets++; */
2749 /* nesvnic->netstats.rx_bytes += rx_pkt_size; */
2750 }
2751
2752 cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX] = 0;
2753 /* Accounting... */
2754 cqe_count++;
2755 if (++head >= cq_size)
2756 head = 0;
2757 if (cqe_count == 255) {
2758 /* Replenish Nic CQ */
2759 nes_write32(nesdev->regs+NES_CQE_ALLOC,
2760 cq->cq_number | (cqe_count << 16));
Glenn Streiff7495ab62008-04-29 13:46:54 -07002761 /* nesdev->nesadapter->tune_timer.cq_count += cqe_count; */
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002762 nesdev->currcq_count += cqe_count;
2763 cqe_count = 0;
2764 }
2765
2766 if (cq->rx_cqes_completed >= nesvnic->budget)
2767 break;
2768 } else {
2769 cq->cqes_pending = 0;
2770 break;
2771 }
2772
2773 } while (1);
2774
Faisal Latif37dab412008-04-29 13:46:54 -07002775 if (nes_use_lro)
2776 lro_flush_all(&nesvnic->lro_mgr);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002777 if (sq_cqes) {
2778 barrier();
2779 /* restart the queue if it had been stopped */
2780 if (netif_queue_stopped(nesvnic->netdev))
2781 netif_wake_queue(nesvnic->netdev);
2782 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002783 cq->cq_head = head;
2784 /* nes_debug(NES_DBG_CQ, "CQ%u Processed = %u cqes, new head = %u.\n",
2785 cq->cq_number, cqe_count, cq->cq_head); */
2786 cq->cqe_allocs_pending = cqe_count;
2787 if (unlikely(nesadapter->et_use_adaptive_rx_coalesce))
2788 {
Glenn Streiff7495ab62008-04-29 13:46:54 -07002789 /* nesdev->nesadapter->tune_timer.cq_count += cqe_count; */
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002790 nesdev->currcq_count += cqe_count;
2791 nes_nic_tune_timer(nesdev);
2792 }
2793 if (atomic_read(&nesvnic->rx_skbs_needed))
2794 nes_replenish_nic_rq(nesvnic);
Faisal Latif37dab412008-04-29 13:46:54 -07002795}
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002796
2797
2798/**
2799 * nes_cqp_ce_handler
2800 */
Roland Dreier1a855fbf2008-04-16 21:01:09 -07002801static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002802{
2803 u64 u64temp;
2804 unsigned long flags;
2805 struct nes_hw_cqp *cqp = NULL;
2806 struct nes_cqp_request *cqp_request;
2807 struct nes_hw_cqp_wqe *cqp_wqe;
2808 u32 head;
2809 u32 cq_size;
2810 u32 cqe_count=0;
2811 u32 error_code;
2812 /* u32 counter; */
2813
2814 head = cq->cq_head;
2815 cq_size = cq->cq_size;
2816
2817 do {
2818 /* process the CQE */
2819 /* nes_debug(NES_DBG_CQP, "head=%u cqe_words=%08X\n", head,
2820 le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX])); */
2821
2822 if (le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_VALID) {
2823 u64temp = (((u64)(le32_to_cpu(cq->cq_vbase[head].
Glenn Streiff7495ab62008-04-29 13:46:54 -07002824 cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX]))) << 32) |
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002825 ((u64)(le32_to_cpu(cq->cq_vbase[head].
2826 cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX])));
2827 cqp = *((struct nes_hw_cqp **)&u64temp);
2828
2829 error_code = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_ERROR_CODE_IDX]);
2830 if (error_code) {
2831 nes_debug(NES_DBG_CQP, "Bad Completion code for opcode 0x%02X from CQP,"
2832 " Major/Minor codes = 0x%04X:%04X.\n",
2833 le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX])&0x3f,
2834 (u16)(error_code >> 16),
2835 (u16)error_code);
2836 nes_debug(NES_DBG_CQP, "cqp: qp_id=%u, sq_head=%u, sq_tail=%u\n",
2837 cqp->qp_id, cqp->sq_head, cqp->sq_tail);
2838 }
2839
2840 u64temp = (((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail].
Glenn Streiff7495ab62008-04-29 13:46:54 -07002841 wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX]))) << 32) |
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002842 ((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail].
2843 wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX])));
2844 cqp_request = *((struct nes_cqp_request **)&u64temp);
2845 if (cqp_request) {
2846 if (cqp_request->waiting) {
2847 /* nes_debug(NES_DBG_CQP, "%s: Waking up requestor\n"); */
2848 cqp_request->major_code = (u16)(error_code >> 16);
2849 cqp_request->minor_code = (u16)error_code;
2850 barrier();
2851 cqp_request->request_done = 1;
2852 wake_up(&cqp_request->waitq);
Roland Dreier1ff66e82008-07-14 23:48:49 -07002853 nes_put_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002854 } else {
Roland Dreier1ff66e82008-07-14 23:48:49 -07002855 if (cqp_request->callback)
2856 cqp_request->cqp_callback(nesdev, cqp_request);
2857 nes_free_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002858 }
2859 } else {
2860 wake_up(&nesdev->cqp.waitq);
2861 }
2862
2863 cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX] = 0;
Glenn Streiff7495ab62008-04-29 13:46:54 -07002864 nes_write32(nesdev->regs + NES_CQE_ALLOC, cq->cq_number | (1 << 16));
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002865 if (++cqp->sq_tail >= cqp->sq_size)
2866 cqp->sq_tail = 0;
2867
2868 /* Accounting... */
2869 cqe_count++;
2870 if (++head >= cq_size)
2871 head = 0;
2872 } else {
2873 break;
2874 }
2875 } while (1);
2876 cq->cq_head = head;
2877
2878 spin_lock_irqsave(&nesdev->cqp.lock, flags);
2879 while ((!list_empty(&nesdev->cqp_pending_reqs)) &&
2880 ((((nesdev->cqp.sq_tail+nesdev->cqp.sq_size)-nesdev->cqp.sq_head) &
2881 (nesdev->cqp.sq_size - 1)) != 1)) {
2882 cqp_request = list_entry(nesdev->cqp_pending_reqs.next,
2883 struct nes_cqp_request, list);
2884 list_del_init(&cqp_request->list);
2885 head = nesdev->cqp.sq_head++;
2886 nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
2887 cqp_wqe = &nesdev->cqp.sq_vbase[head];
2888 memcpy(cqp_wqe, &cqp_request->cqp_wqe, sizeof(*cqp_wqe));
2889 barrier();
2890 cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] =
2891 cpu_to_le32((u32)((unsigned long)cqp_request));
2892 cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] =
2893 cpu_to_le32((u32)(upper_32_bits((unsigned long)cqp_request)));
2894 nes_debug(NES_DBG_CQP, "CQP request %p (opcode 0x%02X) put on CQPs SQ wqe%u.\n",
2895 cqp_request, le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f, head);
2896 /* Ring doorbell (1 WQEs) */
2897 barrier();
2898 nes_write32(nesdev->regs+NES_WQE_ALLOC, 0x01800000 | nesdev->cqp.qp_id);
2899 }
2900 spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
2901
2902 /* Arm the CCQ */
2903 nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT |
2904 cq->cq_number);
2905 nes_read32(nesdev->regs+NES_CQE_ALLOC);
2906}
2907
2908
Don Wood8b1c9dc2009-09-05 20:36:38 -07002909static u8 *locate_mpa(u8 *pkt, u32 aeq_info)
2910{
2911 u16 pkt_len;
2912
2913 if (aeq_info & NES_AEQE_Q2_DATA_ETHERNET) {
2914 /* skip over ethernet header */
2915 pkt_len = be16_to_cpu(*(u16 *)(pkt + ETH_HLEN - 2));
2916 pkt += ETH_HLEN;
2917
2918 /* Skip over IP and TCP headers */
2919 pkt += 4 * (pkt[0] & 0x0f);
2920 pkt += 4 * ((pkt[12] >> 4) & 0x0f);
2921 }
2922 return pkt;
2923}
2924
2925/* Determine if incoming error pkt is rdma layer */
2926static u32 iwarp_opcode(struct nes_qp *nesqp, u32 aeq_info)
2927{
2928 u8 *pkt;
2929 u16 *mpa;
2930 u32 opcode = 0xffffffff;
2931
2932 if (aeq_info & NES_AEQE_Q2_DATA_WRITTEN) {
2933 pkt = nesqp->hwqp.q2_vbase + BAD_FRAME_OFFSET;
2934 mpa = (u16 *)locate_mpa(pkt, aeq_info);
2935 opcode = be16_to_cpu(mpa[1]) & 0xf;
2936 }
2937
2938 return opcode;
2939}
2940
2941/* Build iWARP terminate header */
2942static int nes_bld_terminate_hdr(struct nes_qp *nesqp, u16 async_event_id, u32 aeq_info)
2943{
2944 u8 *pkt = nesqp->hwqp.q2_vbase + BAD_FRAME_OFFSET;
2945 u16 ddp_seg_len;
2946 int copy_len = 0;
2947 u8 is_tagged = 0;
Don Wood4b281fa2009-09-05 20:36:38 -07002948 u8 flush_code = 0;
Don Wood8b1c9dc2009-09-05 20:36:38 -07002949 struct nes_terminate_hdr *termhdr;
2950
2951 termhdr = (struct nes_terminate_hdr *)nesqp->hwqp.q2_vbase;
2952 memset(termhdr, 0, 64);
2953
2954 if (aeq_info & NES_AEQE_Q2_DATA_WRITTEN) {
2955
2956 /* Use data from offending packet to fill in ddp & rdma hdrs */
2957 pkt = locate_mpa(pkt, aeq_info);
2958 ddp_seg_len = be16_to_cpu(*(u16 *)pkt);
2959 if (ddp_seg_len) {
2960 copy_len = 2;
2961 termhdr->hdrct = DDP_LEN_FLAG;
2962 if (pkt[2] & 0x80) {
2963 is_tagged = 1;
2964 if (ddp_seg_len >= TERM_DDP_LEN_TAGGED) {
2965 copy_len += TERM_DDP_LEN_TAGGED;
2966 termhdr->hdrct |= DDP_HDR_FLAG;
2967 }
2968 } else {
2969 if (ddp_seg_len >= TERM_DDP_LEN_UNTAGGED) {
2970 copy_len += TERM_DDP_LEN_UNTAGGED;
2971 termhdr->hdrct |= DDP_HDR_FLAG;
2972 }
2973
2974 if (ddp_seg_len >= (TERM_DDP_LEN_UNTAGGED + TERM_RDMA_LEN)) {
2975 if ((pkt[3] & RDMA_OPCODE_MASK) == RDMA_READ_REQ_OPCODE) {
2976 copy_len += TERM_RDMA_LEN;
2977 termhdr->hdrct |= RDMA_HDR_FLAG;
2978 }
2979 }
2980 }
2981 }
2982 }
2983
2984 switch (async_event_id) {
2985 case NES_AEQE_AEID_AMP_UNALLOCATED_STAG:
2986 switch (iwarp_opcode(nesqp, aeq_info)) {
2987 case IWARP_OPCODE_WRITE:
Don Wood4b281fa2009-09-05 20:36:38 -07002988 flush_code = IB_WC_LOC_PROT_ERR;
Don Wood8b1c9dc2009-09-05 20:36:38 -07002989 termhdr->layer_etype = (LAYER_DDP << 4) | DDP_TAGGED_BUFFER;
2990 termhdr->error_code = DDP_TAGGED_INV_STAG;
2991 break;
2992 default:
Don Wood4b281fa2009-09-05 20:36:38 -07002993 flush_code = IB_WC_REM_ACCESS_ERR;
Don Wood8b1c9dc2009-09-05 20:36:38 -07002994 termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT;
2995 termhdr->error_code = RDMAP_INV_STAG;
2996 }
2997 break;
2998 case NES_AEQE_AEID_AMP_INVALID_STAG:
Don Wood4b281fa2009-09-05 20:36:38 -07002999 flush_code = IB_WC_REM_ACCESS_ERR;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003000 termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT;
3001 termhdr->error_code = RDMAP_INV_STAG;
3002 break;
3003 case NES_AEQE_AEID_AMP_BAD_QP:
Don Wood4b281fa2009-09-05 20:36:38 -07003004 flush_code = IB_WC_LOC_QP_OP_ERR;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003005 termhdr->layer_etype = (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER;
3006 termhdr->error_code = DDP_UNTAGGED_INV_QN;
3007 break;
3008 case NES_AEQE_AEID_AMP_BAD_STAG_KEY:
3009 case NES_AEQE_AEID_AMP_BAD_STAG_INDEX:
3010 switch (iwarp_opcode(nesqp, aeq_info)) {
3011 case IWARP_OPCODE_SEND_INV:
3012 case IWARP_OPCODE_SEND_SE_INV:
Don Wood4b281fa2009-09-05 20:36:38 -07003013 flush_code = IB_WC_REM_OP_ERR;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003014 termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_OP;
3015 termhdr->error_code = RDMAP_CANT_INV_STAG;
3016 break;
3017 default:
Don Wood4b281fa2009-09-05 20:36:38 -07003018 flush_code = IB_WC_REM_ACCESS_ERR;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003019 termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT;
3020 termhdr->error_code = RDMAP_INV_STAG;
3021 }
3022 break;
3023 case NES_AEQE_AEID_AMP_BOUNDS_VIOLATION:
3024 if (aeq_info & (NES_AEQE_Q2_DATA_ETHERNET | NES_AEQE_Q2_DATA_MPA)) {
Don Wood4b281fa2009-09-05 20:36:38 -07003025 flush_code = IB_WC_LOC_PROT_ERR;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003026 termhdr->layer_etype = (LAYER_DDP << 4) | DDP_TAGGED_BUFFER;
3027 termhdr->error_code = DDP_TAGGED_BOUNDS;
3028 } else {
Don Wood4b281fa2009-09-05 20:36:38 -07003029 flush_code = IB_WC_REM_ACCESS_ERR;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003030 termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT;
3031 termhdr->error_code = RDMAP_INV_BOUNDS;
3032 }
3033 break;
3034 case NES_AEQE_AEID_AMP_RIGHTS_VIOLATION:
3035 case NES_AEQE_AEID_AMP_INVALIDATE_NO_REMOTE_ACCESS_RIGHTS:
3036 case NES_AEQE_AEID_PRIV_OPERATION_DENIED:
Don Wood4b281fa2009-09-05 20:36:38 -07003037 flush_code = IB_WC_REM_ACCESS_ERR;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003038 termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT;
3039 termhdr->error_code = RDMAP_ACCESS;
3040 break;
3041 case NES_AEQE_AEID_AMP_TO_WRAP:
Don Wood4b281fa2009-09-05 20:36:38 -07003042 flush_code = IB_WC_REM_ACCESS_ERR;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003043 termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT;
3044 termhdr->error_code = RDMAP_TO_WRAP;
3045 break;
3046 case NES_AEQE_AEID_AMP_BAD_PD:
3047 switch (iwarp_opcode(nesqp, aeq_info)) {
3048 case IWARP_OPCODE_WRITE:
Don Wood4b281fa2009-09-05 20:36:38 -07003049 flush_code = IB_WC_LOC_PROT_ERR;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003050 termhdr->layer_etype = (LAYER_DDP << 4) | DDP_TAGGED_BUFFER;
3051 termhdr->error_code = DDP_TAGGED_UNASSOC_STAG;
3052 break;
3053 case IWARP_OPCODE_SEND_INV:
3054 case IWARP_OPCODE_SEND_SE_INV:
Don Wood4b281fa2009-09-05 20:36:38 -07003055 flush_code = IB_WC_REM_ACCESS_ERR;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003056 termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT;
3057 termhdr->error_code = RDMAP_CANT_INV_STAG;
3058 break;
3059 default:
Don Wood4b281fa2009-09-05 20:36:38 -07003060 flush_code = IB_WC_REM_ACCESS_ERR;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003061 termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT;
3062 termhdr->error_code = RDMAP_UNASSOC_STAG;
3063 }
3064 break;
3065 case NES_AEQE_AEID_LLP_RECEIVED_MARKER_AND_LENGTH_FIELDS_DONT_MATCH:
Don Wood4b281fa2009-09-05 20:36:38 -07003066 flush_code = IB_WC_LOC_LEN_ERR;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003067 termhdr->layer_etype = (LAYER_MPA << 4) | DDP_LLP;
3068 termhdr->error_code = MPA_MARKER;
3069 break;
3070 case NES_AEQE_AEID_LLP_RECEIVED_MPA_CRC_ERROR:
Don Wood4b281fa2009-09-05 20:36:38 -07003071 flush_code = IB_WC_GENERAL_ERR;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003072 termhdr->layer_etype = (LAYER_MPA << 4) | DDP_LLP;
3073 termhdr->error_code = MPA_CRC;
3074 break;
3075 case NES_AEQE_AEID_LLP_SEGMENT_TOO_LARGE:
3076 case NES_AEQE_AEID_LLP_SEGMENT_TOO_SMALL:
Don Wood4b281fa2009-09-05 20:36:38 -07003077 flush_code = IB_WC_LOC_LEN_ERR;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003078 termhdr->layer_etype = (LAYER_DDP << 4) | DDP_CATASTROPHIC;
3079 termhdr->error_code = DDP_CATASTROPHIC_LOCAL;
3080 break;
3081 case NES_AEQE_AEID_DDP_LCE_LOCAL_CATASTROPHIC:
3082 case NES_AEQE_AEID_DDP_NO_L_BIT:
Don Wood4b281fa2009-09-05 20:36:38 -07003083 flush_code = IB_WC_FATAL_ERR;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003084 termhdr->layer_etype = (LAYER_DDP << 4) | DDP_CATASTROPHIC;
3085 termhdr->error_code = DDP_CATASTROPHIC_LOCAL;
3086 break;
3087 case NES_AEQE_AEID_DDP_INVALID_MSN_GAP_IN_MSN:
3088 case NES_AEQE_AEID_DDP_INVALID_MSN_RANGE_IS_NOT_VALID:
Don Wood4b281fa2009-09-05 20:36:38 -07003089 flush_code = IB_WC_GENERAL_ERR;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003090 termhdr->layer_etype = (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER;
3091 termhdr->error_code = DDP_UNTAGGED_INV_MSN_RANGE;
3092 break;
3093 case NES_AEQE_AEID_DDP_UBE_DDP_MESSAGE_TOO_LONG_FOR_AVAILABLE_BUFFER:
Don Wood4b281fa2009-09-05 20:36:38 -07003094 flush_code = IB_WC_LOC_LEN_ERR;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003095 termhdr->layer_etype = (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER;
3096 termhdr->error_code = DDP_UNTAGGED_INV_TOO_LONG;
3097 break;
3098 case NES_AEQE_AEID_DDP_UBE_INVALID_DDP_VERSION:
Don Wood4b281fa2009-09-05 20:36:38 -07003099 flush_code = IB_WC_GENERAL_ERR;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003100 if (is_tagged) {
3101 termhdr->layer_etype = (LAYER_DDP << 4) | DDP_TAGGED_BUFFER;
3102 termhdr->error_code = DDP_TAGGED_INV_DDP_VER;
3103 } else {
3104 termhdr->layer_etype = (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER;
3105 termhdr->error_code = DDP_UNTAGGED_INV_DDP_VER;
3106 }
3107 break;
3108 case NES_AEQE_AEID_DDP_UBE_INVALID_MO:
Don Wood4b281fa2009-09-05 20:36:38 -07003109 flush_code = IB_WC_GENERAL_ERR;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003110 termhdr->layer_etype = (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER;
3111 termhdr->error_code = DDP_UNTAGGED_INV_MO;
3112 break;
3113 case NES_AEQE_AEID_DDP_UBE_INVALID_MSN_NO_BUFFER_AVAILABLE:
Don Wood4b281fa2009-09-05 20:36:38 -07003114 flush_code = IB_WC_REM_OP_ERR;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003115 termhdr->layer_etype = (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER;
3116 termhdr->error_code = DDP_UNTAGGED_INV_MSN_NO_BUF;
3117 break;
3118 case NES_AEQE_AEID_DDP_UBE_INVALID_QN:
Don Wood4b281fa2009-09-05 20:36:38 -07003119 flush_code = IB_WC_GENERAL_ERR;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003120 termhdr->layer_etype = (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER;
3121 termhdr->error_code = DDP_UNTAGGED_INV_QN;
3122 break;
3123 case NES_AEQE_AEID_RDMAP_ROE_INVALID_RDMAP_VERSION:
Don Wood4b281fa2009-09-05 20:36:38 -07003124 flush_code = IB_WC_GENERAL_ERR;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003125 termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_OP;
3126 termhdr->error_code = RDMAP_INV_RDMAP_VER;
3127 break;
3128 case NES_AEQE_AEID_RDMAP_ROE_UNEXPECTED_OPCODE:
Don Wood4b281fa2009-09-05 20:36:38 -07003129 flush_code = IB_WC_LOC_QP_OP_ERR;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003130 termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_OP;
3131 termhdr->error_code = RDMAP_UNEXPECTED_OP;
3132 break;
3133 default:
Don Wood4b281fa2009-09-05 20:36:38 -07003134 flush_code = IB_WC_FATAL_ERR;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003135 termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_OP;
3136 termhdr->error_code = RDMAP_UNSPECIFIED;
3137 break;
3138 }
3139
3140 if (copy_len)
3141 memcpy(termhdr + 1, pkt, copy_len);
3142
Don Wood4b281fa2009-09-05 20:36:38 -07003143 if ((flush_code) && ((NES_AEQE_INBOUND_RDMA & aeq_info) == 0)) {
3144 if (aeq_info & NES_AEQE_SQ)
3145 nesqp->term_sq_flush_code = flush_code;
3146 else
3147 nesqp->term_rq_flush_code = flush_code;
3148 }
3149
Don Wood8b1c9dc2009-09-05 20:36:38 -07003150 return sizeof(struct nes_terminate_hdr) + copy_len;
3151}
3152
3153static void nes_terminate_connection(struct nes_device *nesdev, struct nes_qp *nesqp,
3154 struct nes_hw_aeqe *aeqe, enum ib_event_type eventtype)
3155{
3156 u64 context;
3157 unsigned long flags;
3158 u32 aeq_info;
3159 u16 async_event_id;
3160 u8 tcp_state;
3161 u8 iwarp_state;
3162 u32 termlen = 0;
3163 u32 mod_qp_flags = NES_CQP_QP_IWARP_STATE_TERMINATE |
3164 NES_CQP_QP_TERM_DONT_SEND_FIN;
3165 struct nes_adapter *nesadapter = nesdev->nesadapter;
3166
3167 if (nesqp->term_flags & NES_TERM_SENT)
3168 return; /* Sanity check */
3169
3170 aeq_info = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]);
3171 tcp_state = (aeq_info & NES_AEQE_TCP_STATE_MASK) >> NES_AEQE_TCP_STATE_SHIFT;
3172 iwarp_state = (aeq_info & NES_AEQE_IWARP_STATE_MASK) >> NES_AEQE_IWARP_STATE_SHIFT;
3173 async_event_id = (u16)aeq_info;
3174
3175 context = (unsigned long)nesadapter->qp_table[le32_to_cpu(
3176 aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]) - NES_FIRST_QPN];
3177 if (!context) {
3178 WARN_ON(!context);
3179 return;
3180 }
3181
3182 nesqp = (struct nes_qp *)(unsigned long)context;
3183 spin_lock_irqsave(&nesqp->lock, flags);
3184 nesqp->hw_iwarp_state = iwarp_state;
3185 nesqp->hw_tcp_state = tcp_state;
3186 nesqp->last_aeq = async_event_id;
3187 nesqp->terminate_eventtype = eventtype;
3188 spin_unlock_irqrestore(&nesqp->lock, flags);
3189
3190 if (nesadapter->send_term_ok)
3191 termlen = nes_bld_terminate_hdr(nesqp, async_event_id, aeq_info);
3192 else
3193 mod_qp_flags |= NES_CQP_QP_TERM_DONT_SEND_TERM_MSG;
3194
3195 nes_terminate_start_timer(nesqp);
3196 nesqp->term_flags |= NES_TERM_SENT;
3197 nes_hw_modify_qp(nesdev, nesqp, mod_qp_flags, termlen, 0);
3198}
3199
3200static void nes_terminate_send_fin(struct nes_device *nesdev,
3201 struct nes_qp *nesqp, struct nes_hw_aeqe *aeqe)
3202{
3203 u32 aeq_info;
3204 u16 async_event_id;
3205 u8 tcp_state;
3206 u8 iwarp_state;
3207 unsigned long flags;
3208
3209 aeq_info = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]);
3210 tcp_state = (aeq_info & NES_AEQE_TCP_STATE_MASK) >> NES_AEQE_TCP_STATE_SHIFT;
3211 iwarp_state = (aeq_info & NES_AEQE_IWARP_STATE_MASK) >> NES_AEQE_IWARP_STATE_SHIFT;
3212 async_event_id = (u16)aeq_info;
3213
3214 spin_lock_irqsave(&nesqp->lock, flags);
3215 nesqp->hw_iwarp_state = iwarp_state;
3216 nesqp->hw_tcp_state = tcp_state;
3217 nesqp->last_aeq = async_event_id;
3218 spin_unlock_irqrestore(&nesqp->lock, flags);
3219
3220 /* Send the fin only */
3221 nes_hw_modify_qp(nesdev, nesqp, NES_CQP_QP_IWARP_STATE_TERMINATE |
3222 NES_CQP_QP_TERM_DONT_SEND_TERM_MSG, 0, 0);
3223}
3224
3225/* Cleanup after a terminate sent or received */
3226static void nes_terminate_done(struct nes_qp *nesqp, int timeout_occurred)
3227{
3228 u32 next_iwarp_state = NES_CQP_QP_IWARP_STATE_ERROR;
3229 unsigned long flags;
3230 struct nes_vnic *nesvnic = to_nesvnic(nesqp->ibqp.device);
3231 struct nes_device *nesdev = nesvnic->nesdev;
3232 u8 first_time = 0;
3233
3234 spin_lock_irqsave(&nesqp->lock, flags);
3235 if (nesqp->hte_added) {
3236 nesqp->hte_added = 0;
3237 next_iwarp_state |= NES_CQP_QP_DEL_HTE;
3238 }
3239
3240 first_time = (nesqp->term_flags & NES_TERM_DONE) == 0;
3241 nesqp->term_flags |= NES_TERM_DONE;
3242 spin_unlock_irqrestore(&nesqp->lock, flags);
3243
3244 /* Make sure we go through this only once */
3245 if (first_time) {
3246 if (timeout_occurred == 0)
3247 del_timer(&nesqp->terminate_timer);
3248 else
3249 next_iwarp_state |= NES_CQP_QP_RESET;
3250
3251 nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0, 0);
3252 nes_cm_disconn(nesqp);
3253 }
3254}
3255
3256static void nes_terminate_received(struct nes_device *nesdev,
3257 struct nes_qp *nesqp, struct nes_hw_aeqe *aeqe)
3258{
3259 u32 aeq_info;
3260 u8 *pkt;
3261 u32 *mpa;
3262 u8 ddp_ctl;
3263 u8 rdma_ctl;
3264 u16 aeq_id = 0;
3265
3266 aeq_info = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]);
3267 if (aeq_info & NES_AEQE_Q2_DATA_WRITTEN) {
3268 /* Terminate is not a performance path so the silicon */
3269 /* did not validate the frame - do it now */
3270 pkt = nesqp->hwqp.q2_vbase + BAD_FRAME_OFFSET;
3271 mpa = (u32 *)locate_mpa(pkt, aeq_info);
3272 ddp_ctl = (be32_to_cpu(mpa[0]) >> 8) & 0xff;
3273 rdma_ctl = be32_to_cpu(mpa[0]) & 0xff;
3274 if ((ddp_ctl & 0xc0) != 0x40)
3275 aeq_id = NES_AEQE_AEID_DDP_LCE_LOCAL_CATASTROPHIC;
3276 else if ((ddp_ctl & 0x03) != 1)
3277 aeq_id = NES_AEQE_AEID_DDP_UBE_INVALID_DDP_VERSION;
3278 else if (be32_to_cpu(mpa[2]) != 2)
3279 aeq_id = NES_AEQE_AEID_DDP_UBE_INVALID_QN;
3280 else if (be32_to_cpu(mpa[3]) != 1)
3281 aeq_id = NES_AEQE_AEID_DDP_INVALID_MSN_GAP_IN_MSN;
3282 else if (be32_to_cpu(mpa[4]) != 0)
3283 aeq_id = NES_AEQE_AEID_DDP_UBE_INVALID_MO;
3284 else if ((rdma_ctl & 0xc0) != 0x40)
3285 aeq_id = NES_AEQE_AEID_RDMAP_ROE_INVALID_RDMAP_VERSION;
3286
3287 if (aeq_id) {
3288 /* Bad terminate recvd - send back a terminate */
3289 aeq_info = (aeq_info & 0xffff0000) | aeq_id;
3290 aeqe->aeqe_words[NES_AEQE_MISC_IDX] = cpu_to_le32(aeq_info);
3291 nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_FATAL);
3292 return;
3293 }
3294 }
3295
3296 nesqp->term_flags |= NES_TERM_RCVD;
3297 nesqp->terminate_eventtype = IB_EVENT_QP_FATAL;
3298 nes_terminate_start_timer(nesqp);
3299 nes_terminate_send_fin(nesdev, nesqp, aeqe);
3300}
3301
3302/* Timeout routine in case terminate fails to complete */
3303static void nes_terminate_timeout(unsigned long context)
3304{
3305 struct nes_qp *nesqp = (struct nes_qp *)(unsigned long)context;
3306
3307 nes_terminate_done(nesqp, 1);
3308}
3309
3310/* Set a timer in case hw cannot complete the terminate sequence */
3311static void nes_terminate_start_timer(struct nes_qp *nesqp)
3312{
3313 init_timer(&nesqp->terminate_timer);
3314 nesqp->terminate_timer.function = nes_terminate_timeout;
3315 nesqp->terminate_timer.expires = jiffies + HZ;
3316 nesqp->terminate_timer.data = (unsigned long)nesqp;
3317 add_timer(&nesqp->terminate_timer);
3318}
3319
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003320/**
3321 * nes_process_iwarp_aeqe
3322 */
Roland Dreier1a855fbf2008-04-16 21:01:09 -07003323static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
3324 struct nes_hw_aeqe *aeqe)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003325{
3326 u64 context;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003327 unsigned long flags;
3328 struct nes_qp *nesqp;
Don Wood3c28b442009-09-05 20:36:38 -07003329 struct nes_hw_cq *hw_cq;
3330 struct nes_cq *nescq;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003331 int resource_allocated;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003332 struct nes_adapter *nesadapter = nesdev->nesadapter;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003333 u32 aeq_info;
3334 u32 next_iwarp_state = 0;
3335 u16 async_event_id;
3336 u8 tcp_state;
3337 u8 iwarp_state;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003338 int must_disconn = 1;
3339 int must_terminate = 0;
3340 struct ib_event ibevent;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003341
3342 nes_debug(NES_DBG_AEQ, "\n");
3343 aeq_info = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]);
Don Wood8b1c9dc2009-09-05 20:36:38 -07003344 if ((NES_AEQE_INBOUND_RDMA & aeq_info) || (!(NES_AEQE_QP & aeq_info))) {
Glenn Streiff7495ab62008-04-29 13:46:54 -07003345 context = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX]);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003346 context += ((u64)le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX])) << 32;
3347 } else {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003348 context = (unsigned long)nesadapter->qp_table[le32_to_cpu(
Glenn Streiff7495ab62008-04-29 13:46:54 -07003349 aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]) - NES_FIRST_QPN];
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003350 BUG_ON(!context);
3351 }
3352
3353 async_event_id = (u16)aeq_info;
3354 tcp_state = (aeq_info & NES_AEQE_TCP_STATE_MASK) >> NES_AEQE_TCP_STATE_SHIFT;
3355 iwarp_state = (aeq_info & NES_AEQE_IWARP_STATE_MASK) >> NES_AEQE_IWARP_STATE_SHIFT;
3356 nes_debug(NES_DBG_AEQ, "aeid = 0x%04X, qp-cq id = %d, aeqe = %p,"
3357 " Tcp state = %s, iWARP state = %s\n",
3358 async_event_id,
3359 le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]), aeqe,
3360 nes_tcp_state_str[tcp_state], nes_iwarp_state_str[iwarp_state]);
3361
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003362 switch (async_event_id) {
3363 case NES_AEQE_AEID_LLP_FIN_RECEIVED:
Don Wood8b1c9dc2009-09-05 20:36:38 -07003364 nesqp = (struct nes_qp *)(unsigned long)context;
3365
3366 if (nesqp->term_flags)
3367 return; /* Ignore it, wait for close complete */
3368
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003369 if (atomic_inc_return(&nesqp->close_timer_started) == 1) {
3370 nesqp->cm_id->add_ref(nesqp->cm_id);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003371 schedule_nes_timer(nesqp->cm_node, (struct sk_buff *)nesqp,
3372 NES_TIMER_TYPE_CLOSE, 1, 0);
3373 nes_debug(NES_DBG_AEQ, "QP%u Not decrementing QP refcount (%d),"
3374 " need ae to finish up, original_last_aeq = 0x%04X."
3375 " last_aeq = 0x%04X, scheduling timer. TCP state = %d\n",
3376 nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),
3377 async_event_id, nesqp->last_aeq, tcp_state);
3378 }
Don Wood8b1c9dc2009-09-05 20:36:38 -07003379
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003380 if ((tcp_state != NES_AEQE_TCP_STATE_CLOSE_WAIT) ||
3381 (nesqp->ibqp_state != IB_QPS_RTS)) {
3382 /* FIN Received but tcp state or IB state moved on,
3383 should expect a close complete */
3384 return;
3385 }
Don Wood8b1c9dc2009-09-05 20:36:38 -07003386
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003387 case NES_AEQE_AEID_LLP_CLOSE_COMPLETE:
Don Wood8b1c9dc2009-09-05 20:36:38 -07003388 nesqp = (struct nes_qp *)(unsigned long)context;
3389 if (nesqp->term_flags) {
3390 nes_terminate_done(nesqp, 0);
3391 return;
3392 }
3393
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003394 case NES_AEQE_AEID_LLP_CONNECTION_RESET:
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003395 case NES_AEQE_AEID_RESET_SENT:
Don Wood8b1c9dc2009-09-05 20:36:38 -07003396 nesqp = (struct nes_qp *)(unsigned long)context;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003397 if (async_event_id == NES_AEQE_AEID_RESET_SENT) {
3398 tcp_state = NES_AEQE_TCP_STATE_CLOSED;
3399 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003400 spin_lock_irqsave(&nesqp->lock, flags);
3401 nesqp->hw_iwarp_state = iwarp_state;
3402 nesqp->hw_tcp_state = tcp_state;
3403 nesqp->last_aeq = async_event_id;
3404
3405 if ((tcp_state == NES_AEQE_TCP_STATE_CLOSED) ||
3406 (tcp_state == NES_AEQE_TCP_STATE_TIME_WAIT)) {
3407 nesqp->hte_added = 0;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003408 next_iwarp_state = NES_CQP_QP_IWARP_STATE_ERROR | NES_CQP_QP_DEL_HTE;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003409 }
3410
3411 if ((nesqp->ibqp_state == IB_QPS_RTS) &&
3412 ((tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) ||
3413 (async_event_id == NES_AEQE_AEID_LLP_CONNECTION_RESET))) {
3414 switch (nesqp->hw_iwarp_state) {
3415 case NES_AEQE_IWARP_STATE_RTS:
3416 next_iwarp_state = NES_CQP_QP_IWARP_STATE_CLOSING;
3417 nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_CLOSING;
3418 break;
3419 case NES_AEQE_IWARP_STATE_TERMINATE:
Don Wood8b1c9dc2009-09-05 20:36:38 -07003420 must_disconn = 0; /* terminate path takes care of disconn */
3421 if (nesqp->term_flags == 0)
3422 must_terminate = 1;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003423 break;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003424 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003425 } else {
3426 if (async_event_id == NES_AEQE_AEID_LLP_FIN_RECEIVED) {
3427 /* FIN Received but ib state not RTS,
3428 close complete will be on its way */
Don Wood8b1c9dc2009-09-05 20:36:38 -07003429 must_disconn = 0;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003430 }
Don Wood8b1c9dc2009-09-05 20:36:38 -07003431 }
3432 spin_unlock_irqrestore(&nesqp->lock, flags);
3433
3434 if (must_terminate)
3435 nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_FATAL);
3436 else if (must_disconn) {
3437 if (next_iwarp_state) {
3438 nes_debug(NES_DBG_AEQ, "issuing hw modifyqp for QP%u. next state = 0x%08X\n",
3439 nesqp->hwqp.qp_id, next_iwarp_state);
3440 nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0, 0);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003441 }
3442 nes_cm_disconn(nesqp);
3443 }
3444 break;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003445
3446 case NES_AEQE_AEID_TERMINATE_SENT:
3447 nesqp = (struct nes_qp *)(unsigned long)context;
3448 nes_terminate_send_fin(nesdev, nesqp, aeqe);
3449 break;
3450
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003451 case NES_AEQE_AEID_LLP_TERMINATE_RECEIVED:
Don Wood8b1c9dc2009-09-05 20:36:38 -07003452 nesqp = (struct nes_qp *)(unsigned long)context;
3453 nes_terminate_received(nesdev, nesqp, aeqe);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003454 break;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003455
3456 case NES_AEQE_AEID_AMP_BAD_STAG_KEY:
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003457 case NES_AEQE_AEID_AMP_BAD_STAG_INDEX:
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003458 case NES_AEQE_AEID_AMP_UNALLOCATED_STAG:
Don Wood8b1c9dc2009-09-05 20:36:38 -07003459 case NES_AEQE_AEID_AMP_INVALID_STAG:
3460 case NES_AEQE_AEID_AMP_RIGHTS_VIOLATION:
3461 case NES_AEQE_AEID_AMP_INVALIDATE_NO_REMOTE_ACCESS_RIGHTS:
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003462 case NES_AEQE_AEID_PRIV_OPERATION_DENIED:
Don Wood8b1c9dc2009-09-05 20:36:38 -07003463 case NES_AEQE_AEID_DDP_UBE_DDP_MESSAGE_TOO_LONG_FOR_AVAILABLE_BUFFER:
3464 case NES_AEQE_AEID_AMP_BOUNDS_VIOLATION:
3465 case NES_AEQE_AEID_AMP_TO_WRAP:
3466 nesqp = (struct nes_qp *)(unsigned long)context;
3467 nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_ACCESS_ERR);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003468 break;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003469
3470 case NES_AEQE_AEID_LLP_SEGMENT_TOO_LARGE:
3471 case NES_AEQE_AEID_LLP_SEGMENT_TOO_SMALL:
3472 case NES_AEQE_AEID_DDP_UBE_INVALID_MO:
3473 case NES_AEQE_AEID_DDP_UBE_INVALID_QN:
3474 nesqp = (struct nes_qp *)(unsigned long)context;
3475 if (iwarp_opcode(nesqp, aeq_info) > IWARP_OPCODE_TERM) {
3476 aeq_info &= 0xffff0000;
3477 aeq_info |= NES_AEQE_AEID_RDMAP_ROE_UNEXPECTED_OPCODE;
3478 aeqe->aeqe_words[NES_AEQE_MISC_IDX] = cpu_to_le32(aeq_info);
3479 }
3480
3481 case NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE:
3482 case NES_AEQE_AEID_LLP_TOO_MANY_RETRIES:
3483 case NES_AEQE_AEID_DDP_UBE_INVALID_MSN_NO_BUFFER_AVAILABLE:
3484 case NES_AEQE_AEID_LLP_RECEIVED_MPA_CRC_ERROR:
3485 case NES_AEQE_AEID_AMP_BAD_QP:
3486 case NES_AEQE_AEID_LLP_RECEIVED_MARKER_AND_LENGTH_FIELDS_DONT_MATCH:
3487 case NES_AEQE_AEID_DDP_LCE_LOCAL_CATASTROPHIC:
3488 case NES_AEQE_AEID_DDP_NO_L_BIT:
3489 case NES_AEQE_AEID_DDP_INVALID_MSN_GAP_IN_MSN:
3490 case NES_AEQE_AEID_DDP_INVALID_MSN_RANGE_IS_NOT_VALID:
3491 case NES_AEQE_AEID_DDP_UBE_INVALID_DDP_VERSION:
3492 case NES_AEQE_AEID_RDMAP_ROE_INVALID_RDMAP_VERSION:
3493 case NES_AEQE_AEID_RDMAP_ROE_UNEXPECTED_OPCODE:
3494 case NES_AEQE_AEID_AMP_BAD_PD:
3495 case NES_AEQE_AEID_AMP_FASTREG_SHARED:
3496 case NES_AEQE_AEID_AMP_FASTREG_VALID_STAG:
3497 case NES_AEQE_AEID_AMP_FASTREG_MW_STAG:
3498 case NES_AEQE_AEID_AMP_FASTREG_INVALID_RIGHTS:
3499 case NES_AEQE_AEID_AMP_FASTREG_PBL_TABLE_OVERFLOW:
3500 case NES_AEQE_AEID_AMP_FASTREG_INVALID_LENGTH:
3501 case NES_AEQE_AEID_AMP_INVALIDATE_SHARED:
3502 case NES_AEQE_AEID_AMP_INVALIDATE_MR_WITH_BOUND_WINDOWS:
3503 case NES_AEQE_AEID_AMP_MWBIND_VALID_STAG:
3504 case NES_AEQE_AEID_AMP_MWBIND_OF_MR_STAG:
3505 case NES_AEQE_AEID_AMP_MWBIND_TO_ZERO_BASED_STAG:
3506 case NES_AEQE_AEID_AMP_MWBIND_TO_MW_STAG:
3507 case NES_AEQE_AEID_AMP_MWBIND_INVALID_RIGHTS:
3508 case NES_AEQE_AEID_AMP_MWBIND_INVALID_BOUNDS:
3509 case NES_AEQE_AEID_AMP_MWBIND_TO_INVALID_PARENT:
3510 case NES_AEQE_AEID_AMP_MWBIND_BIND_DISABLED:
3511 case NES_AEQE_AEID_BAD_CLOSE:
3512 case NES_AEQE_AEID_RDMA_READ_WHILE_ORD_ZERO:
3513 case NES_AEQE_AEID_STAG_ZERO_INVALID:
3514 case NES_AEQE_AEID_ROE_INVALID_RDMA_READ_REQUEST:
3515 case NES_AEQE_AEID_ROE_INVALID_RDMA_WRITE_OR_READ_RESP:
3516 nesqp = (struct nes_qp *)(unsigned long)context;
3517 nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_FATAL);
3518 break;
3519
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003520 case NES_AEQE_AEID_CQ_OPERATION_ERROR:
3521 context <<= 1;
3522 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_CQ_OPERATION_ERROR event on CQ%u, %p\n",
3523 le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]), (void *)(unsigned long)context);
3524 resource_allocated = nes_is_resource_allocated(nesadapter, nesadapter->allocated_cqs,
3525 le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]));
3526 if (resource_allocated) {
3527 printk(KERN_ERR PFX "%s: Processing an NES_AEQE_AEID_CQ_OPERATION_ERROR event on CQ%u\n",
Harvey Harrison33718362008-04-16 21:01:10 -07003528 __func__, le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]));
Don Wood3c28b442009-09-05 20:36:38 -07003529 hw_cq = (struct nes_hw_cq *)(unsigned long)context;
3530 if (hw_cq) {
3531 nescq = container_of(hw_cq, struct nes_cq, hw_cq);
3532 if (nescq->ibcq.event_handler) {
3533 ibevent.device = nescq->ibcq.device;
3534 ibevent.event = IB_EVENT_CQ_ERR;
3535 ibevent.element.cq = &nescq->ibcq;
3536 nescq->ibcq.event_handler(&ibevent, nescq->ibcq.cq_context);
3537 }
3538 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003539 }
3540 break;
Don Wood8b1c9dc2009-09-05 20:36:38 -07003541
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003542 default:
3543 nes_debug(NES_DBG_AEQ, "Processing an iWARP related AE for QP, misc = 0x%04X\n",
3544 async_event_id);
3545 break;
3546 }
3547
3548}
3549
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003550/**
3551 * nes_iwarp_ce_handler
3552 */
3553void nes_iwarp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *hw_cq)
3554{
3555 struct nes_cq *nescq = container_of(hw_cq, struct nes_cq, hw_cq);
3556
3557 /* nes_debug(NES_DBG_CQ, "Processing completion event for iWARP CQ%u.\n",
3558 nescq->hw_cq.cq_number); */
3559 nes_write32(nesdev->regs+NES_CQ_ACK, nescq->hw_cq.cq_number);
3560
3561 if (nescq->ibcq.comp_handler)
3562 nescq->ibcq.comp_handler(&nescq->ibcq, nescq->ibcq.cq_context);
3563
3564 return;
3565}
3566
3567
3568/**
3569 * nes_manage_apbvt()
3570 */
3571int nes_manage_apbvt(struct nes_vnic *nesvnic, u32 accel_local_port,
3572 u32 nic_index, u32 add_port)
3573{
3574 struct nes_device *nesdev = nesvnic->nesdev;
3575 struct nes_hw_cqp_wqe *cqp_wqe;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003576 struct nes_cqp_request *cqp_request;
3577 int ret = 0;
3578 u16 major_code;
3579
3580 /* Send manage APBVT request to CQP */
3581 cqp_request = nes_get_cqp_request(nesdev);
3582 if (cqp_request == NULL) {
3583 nes_debug(NES_DBG_QP, "Failed to get a cqp_request.\n");
3584 return -ENOMEM;
3585 }
3586 cqp_request->waiting = 1;
3587 cqp_wqe = &cqp_request->cqp_wqe;
3588
3589 nes_debug(NES_DBG_QP, "%s APBV for local port=%u(0x%04x), nic_index=%u\n",
3590 (add_port == NES_MANAGE_APBVT_ADD) ? "ADD" : "DEL",
3591 accel_local_port, accel_local_port, nic_index);
3592
3593 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
3594 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, (NES_CQP_MANAGE_APBVT |
3595 ((add_port == NES_MANAGE_APBVT_ADD) ? NES_CQP_APBVT_ADD : 0)));
3596 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,
3597 ((nic_index << NES_CQP_APBVT_NIC_SHIFT) | accel_local_port));
3598
3599 nes_debug(NES_DBG_QP, "Waiting for CQP completion for APBVT.\n");
3600
3601 atomic_set(&cqp_request->refcount, 2);
Roland Dreier8294f292008-07-14 23:48:49 -07003602 nes_post_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003603
3604 if (add_port == NES_MANAGE_APBVT_ADD)
3605 ret = wait_event_timeout(cqp_request->waitq, (cqp_request->request_done != 0),
3606 NES_EVENT_TIMEOUT);
3607 nes_debug(NES_DBG_QP, "Completed, ret=%u, CQP Major:Minor codes = 0x%04X:0x%04X\n",
3608 ret, cqp_request->major_code, cqp_request->minor_code);
3609 major_code = cqp_request->major_code;
Roland Dreier1ff66e82008-07-14 23:48:49 -07003610
3611 nes_put_cqp_request(nesdev, cqp_request);
3612
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003613 if (!ret)
3614 return -ETIME;
3615 else if (major_code)
3616 return -EIO;
3617 else
3618 return 0;
3619}
3620
3621
3622/**
3623 * nes_manage_arp_cache
3624 */
3625void nes_manage_arp_cache(struct net_device *netdev, unsigned char *mac_addr,
3626 u32 ip_addr, u32 action)
3627{
3628 struct nes_hw_cqp_wqe *cqp_wqe;
3629 struct nes_vnic *nesvnic = netdev_priv(netdev);
3630 struct nes_device *nesdev;
3631 struct nes_cqp_request *cqp_request;
3632 int arp_index;
3633
3634 nesdev = nesvnic->nesdev;
3635 arp_index = nes_arp_table(nesdev, ip_addr, mac_addr, action);
3636 if (arp_index == -1) {
3637 return;
3638 }
3639
3640 /* update the ARP entry */
3641 cqp_request = nes_get_cqp_request(nesdev);
3642 if (cqp_request == NULL) {
3643 nes_debug(NES_DBG_NETDEV, "Failed to get a cqp_request.\n");
3644 return;
3645 }
3646 cqp_request->waiting = 0;
3647 cqp_wqe = &cqp_request->cqp_wqe;
3648 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
3649
3650 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(
3651 NES_CQP_MANAGE_ARP_CACHE | NES_CQP_ARP_PERM);
3652 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= cpu_to_le32(
3653 (u32)PCI_FUNC(nesdev->pcidev->devfn) << NES_CQP_ARP_AEQ_INDEX_SHIFT);
3654 cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(arp_index);
3655
3656 if (action == NES_ARP_ADD) {
3657 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= cpu_to_le32(NES_CQP_ARP_VALID);
3658 cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_ADDR_LOW_IDX] = cpu_to_le32(
3659 (((u32)mac_addr[2]) << 24) | (((u32)mac_addr[3]) << 16) |
Glenn Streiff7495ab62008-04-29 13:46:54 -07003660 (((u32)mac_addr[4]) << 8) | (u32)mac_addr[5]);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003661 cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_HIGH_IDX] = cpu_to_le32(
3662 (((u32)mac_addr[0]) << 16) | (u32)mac_addr[1]);
3663 } else {
3664 cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_ADDR_LOW_IDX] = 0;
3665 cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_HIGH_IDX] = 0;
3666 }
3667
3668 nes_debug(NES_DBG_NETDEV, "Not waiting for CQP, cqp.sq_head=%u, cqp.sq_tail=%u\n",
3669 nesdev->cqp.sq_head, nesdev->cqp.sq_tail);
3670
3671 atomic_set(&cqp_request->refcount, 1);
Roland Dreier8294f292008-07-14 23:48:49 -07003672 nes_post_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003673}
3674
3675
3676/**
3677 * flush_wqes
3678 */
3679void flush_wqes(struct nes_device *nesdev, struct nes_qp *nesqp,
3680 u32 which_wq, u32 wait_completion)
3681{
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003682 struct nes_cqp_request *cqp_request;
3683 struct nes_hw_cqp_wqe *cqp_wqe;
Don Wood4b281fa2009-09-05 20:36:38 -07003684 u32 sq_code = (NES_IWARP_CQE_MAJOR_FLUSH << 16) | NES_IWARP_CQE_MINOR_FLUSH;
3685 u32 rq_code = (NES_IWARP_CQE_MAJOR_FLUSH << 16) | NES_IWARP_CQE_MINOR_FLUSH;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003686 int ret;
3687
3688 cqp_request = nes_get_cqp_request(nesdev);
3689 if (cqp_request == NULL) {
3690 nes_debug(NES_DBG_QP, "Failed to get a cqp_request.\n");
3691 return;
3692 }
3693 if (wait_completion) {
3694 cqp_request->waiting = 1;
3695 atomic_set(&cqp_request->refcount, 2);
3696 } else {
3697 cqp_request->waiting = 0;
3698 }
3699 cqp_wqe = &cqp_request->cqp_wqe;
3700 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
3701
Don Wood4b281fa2009-09-05 20:36:38 -07003702 /* If wqe in error was identified, set code to be put into cqe */
3703 if ((nesqp->term_sq_flush_code) && (which_wq & NES_CQP_FLUSH_SQ)) {
3704 which_wq |= NES_CQP_FLUSH_MAJ_MIN;
3705 sq_code = (CQE_MAJOR_DRV << 16) | nesqp->term_sq_flush_code;
3706 nesqp->term_sq_flush_code = 0;
3707 }
3708
3709 if ((nesqp->term_rq_flush_code) && (which_wq & NES_CQP_FLUSH_RQ)) {
3710 which_wq |= NES_CQP_FLUSH_MAJ_MIN;
3711 rq_code = (CQE_MAJOR_DRV << 16) | nesqp->term_rq_flush_code;
3712 nesqp->term_rq_flush_code = 0;
3713 }
3714
3715 if (which_wq & NES_CQP_FLUSH_MAJ_MIN) {
3716 cqp_wqe->wqe_words[NES_CQP_QP_WQE_FLUSH_SQ_CODE] = cpu_to_le32(sq_code);
3717 cqp_wqe->wqe_words[NES_CQP_QP_WQE_FLUSH_RQ_CODE] = cpu_to_le32(rq_code);
3718 }
3719
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003720 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] =
3721 cpu_to_le32(NES_CQP_FLUSH_WQES | which_wq);
3722 cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesqp->hwqp.qp_id);
3723
Roland Dreier8294f292008-07-14 23:48:49 -07003724 nes_post_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003725
3726 if (wait_completion) {
3727 /* Wait for CQP */
3728 ret = wait_event_timeout(cqp_request->waitq, (cqp_request->request_done != 0),
3729 NES_EVENT_TIMEOUT);
3730 nes_debug(NES_DBG_QP, "Flush SQ QP WQEs completed, ret=%u,"
3731 " CQP Major:Minor codes = 0x%04X:0x%04X\n",
3732 ret, cqp_request->major_code, cqp_request->minor_code);
Roland Dreier1ff66e82008-07-14 23:48:49 -07003733 nes_put_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003734 }
3735}