blob: 7e20a7fd3c3cca4f51c66c9761d675e3e1baf489 [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);
Glenn Streiff3c2d7742008-02-04 20:20:45 -080077
78#ifdef CONFIG_INFINIBAND_NES_DEBUG
79static unsigned char *nes_iwarp_state_str[] = {
80 "Non-Existant",
81 "Idle",
82 "RTS",
83 "Closing",
84 "RSVD1",
85 "Terminate",
86 "Error",
87 "RSVD2",
88};
89
90static unsigned char *nes_tcp_state_str[] = {
91 "Non-Existant",
92 "Closed",
93 "Listen",
94 "SYN Sent",
95 "SYN Rcvd",
96 "Established",
97 "Close Wait",
98 "FIN Wait 1",
99 "Closing",
100 "Last Ack",
101 "FIN Wait 2",
102 "Time Wait",
103 "RSVD1",
104 "RSVD2",
105 "RSVD3",
106 "RSVD4",
107};
108#endif
109
110
111/**
112 * nes_nic_init_timer_defaults
113 */
114void nes_nic_init_timer_defaults(struct nes_device *nesdev, u8 jumbomode)
115{
116 unsigned long flags;
117 struct nes_adapter *nesadapter = nesdev->nesadapter;
118 struct nes_hw_tune_timer *shared_timer = &nesadapter->tune_timer;
119
120 spin_lock_irqsave(&nesadapter->periodic_timer_lock, flags);
121
122 shared_timer->timer_in_use_min = NES_NIC_FAST_TIMER_LOW;
123 shared_timer->timer_in_use_max = NES_NIC_FAST_TIMER_HIGH;
124 if (jumbomode) {
125 shared_timer->threshold_low = DEFAULT_JUMBO_NES_QL_LOW;
126 shared_timer->threshold_target = DEFAULT_JUMBO_NES_QL_TARGET;
127 shared_timer->threshold_high = DEFAULT_JUMBO_NES_QL_HIGH;
128 } else {
129 shared_timer->threshold_low = DEFAULT_NES_QL_LOW;
130 shared_timer->threshold_target = DEFAULT_NES_QL_TARGET;
131 shared_timer->threshold_high = DEFAULT_NES_QL_HIGH;
132 }
133
134 /* todo use netdev->mtu to set thresholds */
135 spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags);
136}
137
138
139/**
140 * nes_nic_init_timer
141 */
142static void nes_nic_init_timer(struct nes_device *nesdev)
143{
144 unsigned long flags;
145 struct nes_adapter *nesadapter = nesdev->nesadapter;
146 struct nes_hw_tune_timer *shared_timer = &nesadapter->tune_timer;
147
148 spin_lock_irqsave(&nesadapter->periodic_timer_lock, flags);
149
150 if (shared_timer->timer_in_use_old == 0) {
151 nesdev->deepcq_count = 0;
152 shared_timer->timer_direction_upward = 0;
153 shared_timer->timer_direction_downward = 0;
154 shared_timer->timer_in_use = NES_NIC_FAST_TIMER;
155 shared_timer->timer_in_use_old = 0;
156
157 }
158 if (shared_timer->timer_in_use != shared_timer->timer_in_use_old) {
159 shared_timer->timer_in_use_old = shared_timer->timer_in_use;
160 nes_write32(nesdev->regs+NES_PERIODIC_CONTROL,
161 0x80000000 | ((u32)(shared_timer->timer_in_use*8)));
162 }
163 /* todo use netdev->mtu to set thresholds */
164 spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags);
165}
166
167
168/**
169 * nes_nic_tune_timer
170 */
171static void nes_nic_tune_timer(struct nes_device *nesdev)
172{
173 unsigned long flags;
174 struct nes_adapter *nesadapter = nesdev->nesadapter;
175 struct nes_hw_tune_timer *shared_timer = &nesadapter->tune_timer;
176 u16 cq_count = nesdev->currcq_count;
177
178 spin_lock_irqsave(&nesadapter->periodic_timer_lock, flags);
179
John Lacombe4b1cc7e2008-02-21 08:34:58 -0600180 if (shared_timer->cq_count_old <= cq_count)
181 shared_timer->cq_direction_downward = 0;
182 else
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800183 shared_timer->cq_direction_downward++;
184 shared_timer->cq_count_old = cq_count;
185 if (shared_timer->cq_direction_downward > NES_NIC_CQ_DOWNWARD_TREND) {
John Lacombe4b1cc7e2008-02-21 08:34:58 -0600186 if (cq_count <= shared_timer->threshold_low &&
187 shared_timer->threshold_low > 4) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800188 shared_timer->threshold_low = shared_timer->threshold_low/2;
189 shared_timer->cq_direction_downward=0;
190 nesdev->currcq_count = 0;
191 spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags);
192 return;
193 }
194 }
195
196 if (cq_count > 1) {
197 nesdev->deepcq_count += cq_count;
198 if (cq_count <= shared_timer->threshold_low) { /* increase timer gently */
199 shared_timer->timer_direction_upward++;
200 shared_timer->timer_direction_downward = 0;
201 } else if (cq_count <= shared_timer->threshold_target) { /* balanced */
202 shared_timer->timer_direction_upward = 0;
203 shared_timer->timer_direction_downward = 0;
204 } else if (cq_count <= shared_timer->threshold_high) { /* decrease timer gently */
205 shared_timer->timer_direction_downward++;
206 shared_timer->timer_direction_upward = 0;
207 } else if (cq_count <= (shared_timer->threshold_high) * 2) {
208 shared_timer->timer_in_use -= 2;
209 shared_timer->timer_direction_upward = 0;
210 shared_timer->timer_direction_downward++;
211 } else {
212 shared_timer->timer_in_use -= 4;
213 shared_timer->timer_direction_upward = 0;
214 shared_timer->timer_direction_downward++;
215 }
216
217 if (shared_timer->timer_direction_upward > 3 ) { /* using history */
218 shared_timer->timer_in_use += 3;
219 shared_timer->timer_direction_upward = 0;
220 shared_timer->timer_direction_downward = 0;
221 }
222 if (shared_timer->timer_direction_downward > 5) { /* using history */
223 shared_timer->timer_in_use -= 4 ;
224 shared_timer->timer_direction_downward = 0;
225 shared_timer->timer_direction_upward = 0;
226 }
227 }
228
229 /* boundary checking */
John Lacombe27ffed62008-09-26 15:08:10 -0500230 if (shared_timer->timer_in_use > shared_timer->threshold_high)
231 shared_timer->timer_in_use = shared_timer->threshold_high;
232 else if (shared_timer->timer_in_use < shared_timer->threshold_low)
233 shared_timer->timer_in_use = shared_timer->threshold_low;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800234
235 nesdev->currcq_count = 0;
236
237 spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags);
238}
239
240
241/**
242 * nes_init_adapter - initialize adapter
243 */
244struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) {
245 struct nes_adapter *nesadapter = NULL;
246 unsigned long num_pds;
247 u32 u32temp;
248 u32 port_count;
249 u16 max_rq_wrs;
250 u16 max_sq_wrs;
251 u32 max_mr;
252 u32 max_256pbl;
253 u32 max_4kpbl;
254 u32 max_qp;
255 u32 max_irrq;
256 u32 max_cq;
257 u32 hte_index_mask;
258 u32 adapter_size;
259 u32 arp_table_size;
260 u16 vendor_id;
Chien Tungb9c367e2009-03-06 15:12:10 -0800261 u16 device_id;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800262 u8 OneG_Mode;
263 u8 func_index;
264
265 /* search the list of existing adapters */
266 list_for_each_entry(nesadapter, &nes_adapter_list, list) {
267 nes_debug(NES_DBG_INIT, "Searching Adapter list for PCI devfn = 0x%X,"
268 " adapter PCI slot/bus = %u/%u, pci devices PCI slot/bus = %u/%u, .\n",
269 nesdev->pcidev->devfn,
270 PCI_SLOT(nesadapter->devfn),
271 nesadapter->bus_number,
272 PCI_SLOT(nesdev->pcidev->devfn),
273 nesdev->pcidev->bus->number );
274 if ((PCI_SLOT(nesadapter->devfn) == PCI_SLOT(nesdev->pcidev->devfn)) &&
275 (nesadapter->bus_number == nesdev->pcidev->bus->number)) {
276 nesadapter->ref_count++;
277 return nesadapter;
278 }
279 }
280
281 /* no adapter found */
282 num_pds = pci_resource_len(nesdev->pcidev, BAR_1) >> PAGE_SHIFT;
283 if ((hw_rev != NE020_REV) && (hw_rev != NE020_REV1)) {
284 nes_debug(NES_DBG_INIT, "NE020 driver detected unknown hardware revision 0x%x\n",
285 hw_rev);
286 return NULL;
287 }
288
289 nes_debug(NES_DBG_INIT, "Determine Soft Reset, QP_control=0x%x, CPU0=0x%x, CPU1=0x%x, CPU2=0x%x\n",
290 nes_read_indexed(nesdev, NES_IDX_QP_CONTROL + PCI_FUNC(nesdev->pcidev->devfn) * 8),
291 nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS),
292 nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS + 4),
293 nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS + 8));
294
295 nes_debug(NES_DBG_INIT, "Reset and init NE020\n");
296
297
298 if ((port_count = nes_reset_adapter_ne020(nesdev, &OneG_Mode)) == 0)
299 return NULL;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800300
301 max_qp = nes_read_indexed(nesdev, NES_IDX_QP_CTX_SIZE);
302 nes_debug(NES_DBG_INIT, "QP_CTX_SIZE=%u\n", max_qp);
303
304 u32temp = nes_read_indexed(nesdev, NES_IDX_QUAD_HASH_TABLE_SIZE);
305 if (max_qp > ((u32)1 << (u32temp & 0x001f))) {
306 nes_debug(NES_DBG_INIT, "Reducing Max QPs to %u due to hash table size = 0x%08X\n",
307 max_qp, u32temp);
308 max_qp = (u32)1 << (u32temp & 0x001f);
309 }
310
311 hte_index_mask = ((u32)1 << ((u32temp & 0x001f)+1))-1;
312 nes_debug(NES_DBG_INIT, "Max QP = %u, hte_index_mask = 0x%08X.\n",
313 max_qp, hte_index_mask);
314
315 u32temp = nes_read_indexed(nesdev, NES_IDX_IRRQ_COUNT);
316
317 max_irrq = 1 << (u32temp & 0x001f);
318
319 if (max_qp > max_irrq) {
320 max_qp = max_irrq;
321 nes_debug(NES_DBG_INIT, "Reducing Max QPs to %u due to Available Q1s.\n",
322 max_qp);
323 }
324
325 /* there should be no reason to allocate more pds than qps */
326 if (num_pds > max_qp)
327 num_pds = max_qp;
328
329 u32temp = nes_read_indexed(nesdev, NES_IDX_MRT_SIZE);
330 max_mr = (u32)8192 << (u32temp & 0x7);
331
332 u32temp = nes_read_indexed(nesdev, NES_IDX_PBL_REGION_SIZE);
333 max_256pbl = (u32)1 << (u32temp & 0x0000001f);
334 max_4kpbl = (u32)1 << ((u32temp >> 16) & 0x0000001f);
335 max_cq = nes_read_indexed(nesdev, NES_IDX_CQ_CTX_SIZE);
336
337 u32temp = nes_read_indexed(nesdev, NES_IDX_ARP_CACHE_SIZE);
338 arp_table_size = 1 << u32temp;
339
340 adapter_size = (sizeof(struct nes_adapter) +
341 (sizeof(unsigned long)-1)) & (~(sizeof(unsigned long)-1));
342 adapter_size += sizeof(unsigned long) * BITS_TO_LONGS(max_qp);
343 adapter_size += sizeof(unsigned long) * BITS_TO_LONGS(max_mr);
344 adapter_size += sizeof(unsigned long) * BITS_TO_LONGS(max_cq);
345 adapter_size += sizeof(unsigned long) * BITS_TO_LONGS(num_pds);
346 adapter_size += sizeof(unsigned long) * BITS_TO_LONGS(arp_table_size);
347 adapter_size += sizeof(struct nes_qp **) * max_qp;
348
349 /* allocate a new adapter struct */
350 nesadapter = kzalloc(adapter_size, GFP_KERNEL);
351 if (nesadapter == NULL) {
352 return NULL;
353 }
354
355 nes_debug(NES_DBG_INIT, "Allocating new nesadapter @ %p, size = %u (actual size = %u).\n",
356 nesadapter, (u32)sizeof(struct nes_adapter), adapter_size);
357
Chien Tungfcb7ad32008-09-30 14:49:44 -0700358 if (nes_read_eeprom_values(nesdev, nesadapter)) {
359 printk(KERN_ERR PFX "Unable to read EEPROM data.\n");
360 kfree(nesadapter);
361 return NULL;
362 }
363
Chien Tungb9c367e2009-03-06 15:12:10 -0800364 nesadapter->vendor_id = (((u32) nesadapter->mac_addr_high) << 8) |
365 (nesadapter->mac_addr_low >> 24);
366
367 pci_bus_read_config_word(nesdev->pcidev->bus, nesdev->pcidev->devfn,
368 PCI_DEVICE_ID, &device_id);
369 nesadapter->vendor_part_id = device_id;
370
Chien Tungfcb7ad32008-09-30 14:49:44 -0700371 if (nes_init_serdes(nesdev, hw_rev, port_count, nesadapter,
372 OneG_Mode)) {
373 kfree(nesadapter);
374 return NULL;
375 }
376 nes_init_csr_ne020(nesdev, hw_rev, port_count);
377
Vadim Makhervaks7e36d3d2008-10-03 12:21:18 -0700378 memset(nesadapter->pft_mcast_map, 255,
379 sizeof nesadapter->pft_mcast_map);
380
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800381 /* populate the new nesadapter */
382 nesadapter->devfn = nesdev->pcidev->devfn;
383 nesadapter->bus_number = nesdev->pcidev->bus->number;
384 nesadapter->ref_count = 1;
385 nesadapter->timer_int_req = 0xffff0000;
386 nesadapter->OneG_Mode = OneG_Mode;
387 nesadapter->doorbell_start = nesdev->doorbell_region;
388
389 /* nesadapter->tick_delta = clk_divisor; */
390 nesadapter->hw_rev = hw_rev;
391 nesadapter->port_count = port_count;
392
393 nesadapter->max_qp = max_qp;
394 nesadapter->hte_index_mask = hte_index_mask;
395 nesadapter->max_irrq = max_irrq;
396 nesadapter->max_mr = max_mr;
397 nesadapter->max_256pbl = max_256pbl - 1;
398 nesadapter->max_4kpbl = max_4kpbl - 1;
399 nesadapter->max_cq = max_cq;
400 nesadapter->free_256pbl = max_256pbl - 1;
401 nesadapter->free_4kpbl = max_4kpbl - 1;
402 nesadapter->max_pd = num_pds;
403 nesadapter->arp_table_size = arp_table_size;
404
405 nesadapter->et_pkt_rate_low = NES_TIMER_ENABLE_LIMIT;
406 if (nes_drv_opt & NES_DRV_OPT_DISABLE_INT_MOD) {
407 nesadapter->et_use_adaptive_rx_coalesce = 0;
408 nesadapter->timer_int_limit = NES_TIMER_INT_LIMIT;
409 nesadapter->et_rx_coalesce_usecs_irq = interrupt_mod_interval;
410 } else {
411 nesadapter->et_use_adaptive_rx_coalesce = 1;
412 nesadapter->timer_int_limit = NES_TIMER_INT_LIMIT_DYNAMIC;
413 nesadapter->et_rx_coalesce_usecs_irq = 0;
Harvey Harrison33718362008-04-16 21:01:10 -0700414 printk(PFX "%s: Using Adaptive Interrupt Moderation\n", __func__);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800415 }
416 /* Setup and enable the periodic timer */
417 if (nesadapter->et_rx_coalesce_usecs_irq)
418 nes_write32(nesdev->regs+NES_PERIODIC_CONTROL, 0x80000000 |
419 ((u32)(nesadapter->et_rx_coalesce_usecs_irq * 8)));
420 else
421 nes_write32(nesdev->regs+NES_PERIODIC_CONTROL, 0x00000000);
422
423 nesadapter->base_pd = 1;
424
425 nesadapter->device_cap_flags =
Steve Wise96f15c02008-07-14 23:48:53 -0700426 IB_DEVICE_LOCAL_DMA_LKEY | IB_DEVICE_MEM_WINDOW;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800427
428 nesadapter->allocated_qps = (unsigned long *)&(((unsigned char *)nesadapter)
429 [(sizeof(struct nes_adapter)+(sizeof(unsigned long)-1))&(~(sizeof(unsigned long)-1))]);
430 nesadapter->allocated_cqs = &nesadapter->allocated_qps[BITS_TO_LONGS(max_qp)];
431 nesadapter->allocated_mrs = &nesadapter->allocated_cqs[BITS_TO_LONGS(max_cq)];
432 nesadapter->allocated_pds = &nesadapter->allocated_mrs[BITS_TO_LONGS(max_mr)];
433 nesadapter->allocated_arps = &nesadapter->allocated_pds[BITS_TO_LONGS(num_pds)];
434 nesadapter->qp_table = (struct nes_qp **)(&nesadapter->allocated_arps[BITS_TO_LONGS(arp_table_size)]);
435
436
437 /* mark the usual suspect QPs and CQs as in use */
438 for (u32temp = 0; u32temp < NES_FIRST_QPN; u32temp++) {
439 set_bit(u32temp, nesadapter->allocated_qps);
440 set_bit(u32temp, nesadapter->allocated_cqs);
441 }
442
443 for (u32temp = 0; u32temp < 20; u32temp++)
444 set_bit(u32temp, nesadapter->allocated_pds);
445 u32temp = nes_read_indexed(nesdev, NES_IDX_QP_MAX_CFG_SIZES);
446
447 max_rq_wrs = ((u32temp >> 8) & 3);
448 switch (max_rq_wrs) {
449 case 0:
450 max_rq_wrs = 4;
451 break;
452 case 1:
453 max_rq_wrs = 16;
454 break;
455 case 2:
456 max_rq_wrs = 32;
457 break;
458 case 3:
459 max_rq_wrs = 512;
460 break;
461 }
462
463 max_sq_wrs = (u32temp & 3);
464 switch (max_sq_wrs) {
465 case 0:
466 max_sq_wrs = 4;
467 break;
468 case 1:
469 max_sq_wrs = 16;
470 break;
471 case 2:
472 max_sq_wrs = 32;
473 break;
474 case 3:
475 max_sq_wrs = 512;
476 break;
477 }
478 nesadapter->max_qp_wr = min(max_rq_wrs, max_sq_wrs);
479 nesadapter->max_irrq_wr = (u32temp >> 16) & 3;
480
481 nesadapter->max_sge = 4;
482 nesadapter->max_cqe = 32767;
483
484 if (nes_read_eeprom_values(nesdev, nesadapter)) {
485 printk(KERN_ERR PFX "Unable to read EEPROM data.\n");
486 kfree(nesadapter);
487 return NULL;
488 }
489
490 u32temp = nes_read_indexed(nesdev, NES_IDX_TCP_TIMER_CONFIG);
491 nes_write_indexed(nesdev, NES_IDX_TCP_TIMER_CONFIG,
492 (u32temp & 0xff000000) | (nesadapter->tcp_timer_core_clk_divisor & 0x00ffffff));
493
494 /* setup port configuration */
495 if (nesadapter->port_count == 1) {
Chien Tungfcb7ad32008-09-30 14:49:44 -0700496 nesadapter->log_port = 0x00000000;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800497 if (nes_drv_opt & NES_DRV_OPT_DUAL_LOGICAL_PORT)
498 nes_write_indexed(nesdev, NES_IDX_TX_POOL_SIZE, 0x00000002);
499 else
500 nes_write_indexed(nesdev, NES_IDX_TX_POOL_SIZE, 0x00000003);
501 } else {
Chien Tungfcb7ad32008-09-30 14:49:44 -0700502 if (nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G) {
503 nesadapter->log_port = 0x000000D8;
504 } else {
505 if (nesadapter->port_count == 2)
506 nesadapter->log_port = 0x00000044;
507 else
508 nesadapter->log_port = 0x000000e4;
509 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800510 nes_write_indexed(nesdev, NES_IDX_TX_POOL_SIZE, 0x00000003);
511 }
512
Chien Tungfcb7ad32008-09-30 14:49:44 -0700513 nes_write_indexed(nesdev, NES_IDX_NIC_LOGPORT_TO_PHYPORT,
514 nesadapter->log_port);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800515 nes_debug(NES_DBG_INIT, "Probe time, LOG2PHY=%u\n",
516 nes_read_indexed(nesdev, NES_IDX_NIC_LOGPORT_TO_PHYPORT));
517
518 spin_lock_init(&nesadapter->resource_lock);
519 spin_lock_init(&nesadapter->phy_lock);
520 spin_lock_init(&nesadapter->pbl_lock);
521 spin_lock_init(&nesadapter->periodic_timer_lock);
522
523 INIT_LIST_HEAD(&nesadapter->nesvnic_list[0]);
524 INIT_LIST_HEAD(&nesadapter->nesvnic_list[1]);
525 INIT_LIST_HEAD(&nesadapter->nesvnic_list[2]);
526 INIT_LIST_HEAD(&nesadapter->nesvnic_list[3]);
527
528 if ((!nesadapter->OneG_Mode) && (nesadapter->port_count == 2)) {
529 u32 pcs_control_status0, pcs_control_status1;
530 u32 reset_value;
531 u32 i = 0;
532 u32 int_cnt = 0;
533 u32 ext_cnt = 0;
534 unsigned long flags;
535 u32 j = 0;
536
537 pcs_control_status0 = nes_read_indexed(nesdev,
538 NES_IDX_PHY_PCS_CONTROL_STATUS0);
539 pcs_control_status1 = nes_read_indexed(nesdev,
540 NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200);
541
542 for (i = 0; i < NES_MAX_LINK_CHECK; i++) {
543 pcs_control_status0 = nes_read_indexed(nesdev,
544 NES_IDX_PHY_PCS_CONTROL_STATUS0);
545 pcs_control_status1 = nes_read_indexed(nesdev,
546 NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200);
547 if ((0x0F000100 == (pcs_control_status0 & 0x0F000100))
548 || (0x0F000100 == (pcs_control_status1 & 0x0F000100)))
549 int_cnt++;
550 msleep(1);
551 }
552 if (int_cnt > 1) {
553 spin_lock_irqsave(&nesadapter->phy_lock, flags);
Chien Tung010db4d2009-04-27 13:27:21 -0700554 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F0C8);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800555 mh_detected++;
556 reset_value = nes_read32(nesdev->regs+NES_SOFTWARE_RESET);
557 reset_value |= 0x0000003d;
558 nes_write32(nesdev->regs+NES_SOFTWARE_RESET, reset_value);
559
560 while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET)
561 & 0x00000040) != 0x00000040) && (j++ < 5000));
562 spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
563
564 pcs_control_status0 = nes_read_indexed(nesdev,
565 NES_IDX_PHY_PCS_CONTROL_STATUS0);
566 pcs_control_status1 = nes_read_indexed(nesdev,
567 NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200);
568
569 for (i = 0; i < NES_MAX_LINK_CHECK; i++) {
570 pcs_control_status0 = nes_read_indexed(nesdev,
571 NES_IDX_PHY_PCS_CONTROL_STATUS0);
572 pcs_control_status1 = nes_read_indexed(nesdev,
573 NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200);
574 if ((0x0F000100 == (pcs_control_status0 & 0x0F000100))
575 || (0x0F000100 == (pcs_control_status1 & 0x0F000100))) {
576 if (++ext_cnt > int_cnt) {
577 spin_lock_irqsave(&nesadapter->phy_lock, flags);
578 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1,
Chien Tung010db4d2009-04-27 13:27:21 -0700579 0x0000F088);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800580 mh_detected++;
581 reset_value = nes_read32(nesdev->regs+NES_SOFTWARE_RESET);
582 reset_value |= 0x0000003d;
583 nes_write32(nesdev->regs+NES_SOFTWARE_RESET, reset_value);
584
585 while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET)
586 & 0x00000040) != 0x00000040) && (j++ < 5000));
587 spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
588 break;
589 }
590 }
591 msleep(1);
592 }
593 }
594 }
595
596 if (nesadapter->hw_rev == NE020_REV) {
597 init_timer(&nesadapter->mh_timer);
598 nesadapter->mh_timer.function = nes_mh_fix;
599 nesadapter->mh_timer.expires = jiffies + (HZ/5); /* 1 second */
600 nesadapter->mh_timer.data = (unsigned long)nesdev;
601 add_timer(&nesadapter->mh_timer);
602 } else {
603 nes_write32(nesdev->regs+NES_INTF_INT_STAT, 0x0f000000);
604 }
605
606 init_timer(&nesadapter->lc_timer);
607 nesadapter->lc_timer.function = nes_clc;
608 nesadapter->lc_timer.expires = jiffies + 3600 * HZ; /* 1 hour */
609 nesadapter->lc_timer.data = (unsigned long)nesdev;
610 add_timer(&nesadapter->lc_timer);
611
612 list_add_tail(&nesadapter->list, &nes_adapter_list);
613
614 for (func_index = 0; func_index < 8; func_index++) {
615 pci_bus_read_config_word(nesdev->pcidev->bus,
616 PCI_DEVFN(PCI_SLOT(nesdev->pcidev->devfn),
617 func_index), 0, &vendor_id);
618 if (vendor_id == 0xffff)
619 break;
620 }
Harvey Harrison33718362008-04-16 21:01:10 -0700621 nes_debug(NES_DBG_INIT, "%s %d functions found for %s.\n", __func__,
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800622 func_index, pci_name(nesdev->pcidev));
623 nesadapter->adapter_fcn_count = func_index;
624
625 return nesadapter;
626}
627
628
629/**
630 * nes_reset_adapter_ne020
631 */
Roland Dreier1a855fbf2008-04-16 21:01:09 -0700632static unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode)
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800633{
634 u32 port_count;
635 u32 u32temp;
636 u32 i;
637
638 u32temp = nes_read32(nesdev->regs+NES_SOFTWARE_RESET);
639 port_count = ((u32temp & 0x00000300) >> 8) + 1;
640 /* TODO: assuming that both SERDES are set the same for now */
641 *OneG_Mode = (u32temp & 0x00003c00) ? 0 : 1;
642 nes_debug(NES_DBG_INIT, "Initial Software Reset = 0x%08X, port_count=%u\n",
643 u32temp, port_count);
644 if (*OneG_Mode)
645 nes_debug(NES_DBG_INIT, "Running in 1G mode.\n");
646 u32temp &= 0xff00ffc0;
647 switch (port_count) {
648 case 1:
649 u32temp |= 0x00ee0000;
650 break;
651 case 2:
652 u32temp |= 0x00cc0000;
653 break;
654 case 4:
655 u32temp |= 0x00000000;
656 break;
657 default:
658 return 0;
659 break;
660 }
661
662 /* check and do full reset if needed */
663 if (nes_read_indexed(nesdev, NES_IDX_QP_CONTROL+(PCI_FUNC(nesdev->pcidev->devfn)*8))) {
664 nes_debug(NES_DBG_INIT, "Issuing Full Soft reset = 0x%08X\n", u32temp | 0xd);
665 nes_write32(nesdev->regs+NES_SOFTWARE_RESET, u32temp | 0xd);
666
667 i = 0;
668 while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET) & 0x00000040) == 0) && i++ < 10000)
669 mdelay(1);
670 if (i >= 10000) {
671 nes_debug(NES_DBG_INIT, "Did not see full soft reset done.\n");
672 return 0;
673 }
Chien Tungbc5698f32008-04-23 11:55:45 -0700674
675 i = 0;
676 while ((nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS) != 0x80) && i++ < 10000)
677 mdelay(1);
678 if (i >= 10000) {
679 printk(KERN_ERR PFX "Internal CPU not ready, status = %02X\n",
680 nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS));
681 return 0;
682 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800683 }
684
685 /* port reset */
686 switch (port_count) {
687 case 1:
688 u32temp |= 0x00ee0010;
689 break;
690 case 2:
691 u32temp |= 0x00cc0030;
692 break;
693 case 4:
694 u32temp |= 0x00000030;
695 break;
696 }
697
698 nes_debug(NES_DBG_INIT, "Issuing Port Soft reset = 0x%08X\n", u32temp | 0xd);
699 nes_write32(nesdev->regs+NES_SOFTWARE_RESET, u32temp | 0xd);
700
701 i = 0;
702 while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET) & 0x00000040) == 0) && i++ < 10000)
703 mdelay(1);
704 if (i >= 10000) {
705 nes_debug(NES_DBG_INIT, "Did not see port soft reset done.\n");
706 return 0;
707 }
708
709 /* serdes 0 */
710 i = 0;
711 while (((u32temp = (nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0)
712 & 0x0000000f)) != 0x0000000f) && i++ < 5000)
713 mdelay(1);
714 if (i >= 5000) {
715 nes_debug(NES_DBG_INIT, "Serdes 0 not ready, status=%x\n", u32temp);
716 return 0;
717 }
718
719 /* serdes 1 */
720 if (port_count > 1) {
721 i = 0;
722 while (((u32temp = (nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS1)
723 & 0x0000000f)) != 0x0000000f) && i++ < 5000)
724 mdelay(1);
725 if (i >= 5000) {
726 nes_debug(NES_DBG_INIT, "Serdes 1 not ready, status=%x\n", u32temp);
727 return 0;
728 }
729 }
730
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800731 return port_count;
732}
733
734
735/**
736 * nes_init_serdes
737 */
Roland Dreier1a855fbf2008-04-16 21:01:09 -0700738static int nes_init_serdes(struct nes_device *nesdev, u8 hw_rev, u8 port_count,
Chien Tungfcb7ad32008-09-30 14:49:44 -0700739 struct nes_adapter *nesadapter, u8 OneG_Mode)
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800740{
741 int i;
742 u32 u32temp;
Chien Tunga4849fc2009-04-08 14:27:18 -0700743 u32 sds;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800744
745 if (hw_rev != NE020_REV) {
746 /* init serdes 0 */
Chien Tunga4849fc2009-04-08 14:27:18 -0700747 if (wide_ppm_offset && (nesadapter->phy_type[0] == NES_PHY_TYPE_CX4))
748 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000FFFAA);
749 else
750 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000000FF);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800751
Chien Tungfcb7ad32008-09-30 14:49:44 -0700752 if (nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G) {
Chien Tunga4849fc2009-04-08 14:27:18 -0700753 sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0);
754 sds |= 0x00000100;
755 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, sds);
756 }
757 if (!OneG_Mode)
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800758 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE0, 0x11110000);
Chien Tunga4849fc2009-04-08 14:27:18 -0700759
760 if (port_count < 2)
761 return 0;
762
763 /* init serdes 1 */
764 switch (nesadapter->phy_type[1]) {
Chien Tung43035652009-04-08 14:27:56 -0700765 case NES_PHY_TYPE_ARGUS:
766 case NES_PHY_TYPE_SFP_D:
Chien Tunga4849fc2009-04-08 14:27:18 -0700767 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP0, 0x00000000);
768 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP1, 0x00000000);
769 break;
770 case NES_PHY_TYPE_CX4:
771 sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1);
772 sds &= 0xFFFFFFBF;
773 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, sds);
774 if (wide_ppm_offset)
775 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000FFFAA);
776 else
777 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000000FF);
778 break;
779 case NES_PHY_TYPE_PUMA_1G:
780 sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1);
781 sds |= 0x000000100;
782 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, sds);
Chien Tungfcb7ad32008-09-30 14:49:44 -0700783 }
Chien Tunga4849fc2009-04-08 14:27:18 -0700784 if (!OneG_Mode)
785 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE1, 0x11110000);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800786 } else {
787 /* init serdes 0 */
788 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, 0x00000008);
789 i = 0;
790 while (((u32temp = (nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0)
791 & 0x0000000f)) != 0x0000000f) && i++ < 5000)
792 mdelay(1);
793 if (i >= 5000) {
794 nes_debug(NES_DBG_PHY, "Init: serdes 0 not ready, status=%x\n", u32temp);
795 return 1;
796 }
797 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP0, 0x000bdef7);
798 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_DRIVE0, 0x9ce73000);
799 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_MODE0, 0x0ff00000);
800 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_SIGDET0, 0x00000000);
801 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_BYPASS0, 0x00000000);
802 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_LOOPBACK_CONTROL0, 0x00000000);
803 if (OneG_Mode)
804 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_EQ_CONTROL0, 0xf0182222);
805 else
806 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_EQ_CONTROL0, 0xf0042222);
807
808 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000000ff);
809 if (port_count > 1) {
810 /* init serdes 1 */
811 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x00000048);
812 i = 0;
813 while (((u32temp = (nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS1)
814 & 0x0000000f)) != 0x0000000f) && (i++ < 5000))
815 mdelay(1);
816 if (i >= 5000) {
Harvey Harrison33718362008-04-16 21:01:10 -0700817 printk("%s: Init: serdes 1 not ready, status=%x\n", __func__, u32temp);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800818 /* return 1; */
819 }
820 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP1, 0x000bdef7);
821 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_DRIVE1, 0x9ce73000);
822 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_MODE1, 0x0ff00000);
823 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_SIGDET1, 0x00000000);
824 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_BYPASS1, 0x00000000);
825 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_LOOPBACK_CONTROL1, 0x00000000);
826 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_EQ_CONTROL1, 0xf0002222);
827 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000000ff);
828 }
829 }
830 return 0;
831}
832
833
834/**
835 * nes_init_csr_ne020
836 * Initialize registers for ne020 hardware
837 */
Roland Dreier1a855fbf2008-04-16 21:01:09 -0700838static void nes_init_csr_ne020(struct nes_device *nesdev, u8 hw_rev, u8 port_count)
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800839{
840 u32 u32temp;
841
842 nes_debug(NES_DBG_INIT, "port_count=%d\n", port_count);
843
844 nes_write_indexed(nesdev, 0x000001E4, 0x00000007);
845 /* nes_write_indexed(nesdev, 0x000001E8, 0x000208C4); */
846 nes_write_indexed(nesdev, 0x000001E8, 0x00020874);
847 nes_write_indexed(nesdev, 0x000001D8, 0x00048002);
848 /* nes_write_indexed(nesdev, 0x000001D8, 0x0004B002); */
849 nes_write_indexed(nesdev, 0x000001FC, 0x00050005);
850 nes_write_indexed(nesdev, 0x00000600, 0x55555555);
851 nes_write_indexed(nesdev, 0x00000604, 0x55555555);
852
853 /* TODO: move these MAC register settings to NIC bringup */
854 nes_write_indexed(nesdev, 0x00002000, 0x00000001);
855 nes_write_indexed(nesdev, 0x00002004, 0x00000001);
856 nes_write_indexed(nesdev, 0x00002008, 0x0000FFFF);
857 nes_write_indexed(nesdev, 0x0000200C, 0x00000001);
858 nes_write_indexed(nesdev, 0x00002010, 0x000003c1);
859 nes_write_indexed(nesdev, 0x0000201C, 0x75345678);
860 if (port_count > 1) {
861 nes_write_indexed(nesdev, 0x00002200, 0x00000001);
862 nes_write_indexed(nesdev, 0x00002204, 0x00000001);
863 nes_write_indexed(nesdev, 0x00002208, 0x0000FFFF);
864 nes_write_indexed(nesdev, 0x0000220C, 0x00000001);
865 nes_write_indexed(nesdev, 0x00002210, 0x000003c1);
866 nes_write_indexed(nesdev, 0x0000221C, 0x75345678);
867 nes_write_indexed(nesdev, 0x00000908, 0x20000001);
868 }
869 if (port_count > 2) {
870 nes_write_indexed(nesdev, 0x00002400, 0x00000001);
871 nes_write_indexed(nesdev, 0x00002404, 0x00000001);
872 nes_write_indexed(nesdev, 0x00002408, 0x0000FFFF);
873 nes_write_indexed(nesdev, 0x0000240C, 0x00000001);
874 nes_write_indexed(nesdev, 0x00002410, 0x000003c1);
875 nes_write_indexed(nesdev, 0x0000241C, 0x75345678);
876 nes_write_indexed(nesdev, 0x00000910, 0x20000001);
877
878 nes_write_indexed(nesdev, 0x00002600, 0x00000001);
879 nes_write_indexed(nesdev, 0x00002604, 0x00000001);
880 nes_write_indexed(nesdev, 0x00002608, 0x0000FFFF);
881 nes_write_indexed(nesdev, 0x0000260C, 0x00000001);
882 nes_write_indexed(nesdev, 0x00002610, 0x000003c1);
883 nes_write_indexed(nesdev, 0x0000261C, 0x75345678);
884 nes_write_indexed(nesdev, 0x00000918, 0x20000001);
885 }
886
887 nes_write_indexed(nesdev, 0x00005000, 0x00018000);
888 /* nes_write_indexed(nesdev, 0x00005000, 0x00010000); */
Chien Tung2b537c22008-09-26 15:08:10 -0500889 nes_write_indexed(nesdev, NES_IDX_WQM_CONFIG1, (wqm_quanta << 1) |
890 0x00000001);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800891 nes_write_indexed(nesdev, 0x00005008, 0x1F1F1F1F);
892 nes_write_indexed(nesdev, 0x00005010, 0x1F1F1F1F);
893 nes_write_indexed(nesdev, 0x00005018, 0x1F1F1F1F);
894 nes_write_indexed(nesdev, 0x00005020, 0x1F1F1F1F);
895 nes_write_indexed(nesdev, 0x00006090, 0xFFFFFFFF);
896
897 /* TODO: move this to code, get from EEPROM */
898 nes_write_indexed(nesdev, 0x00000900, 0x20000001);
899 nes_write_indexed(nesdev, 0x000060C0, 0x0000028e);
900 nes_write_indexed(nesdev, 0x000060C8, 0x00000020);
Glenn Streiff7495ab62008-04-29 13:46:54 -0700901
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800902 nes_write_indexed(nesdev, 0x000001EC, 0x7b2625a0);
903 /* nes_write_indexed(nesdev, 0x000001EC, 0x5f2625a0); */
904
905 if (hw_rev != NE020_REV) {
906 u32temp = nes_read_indexed(nesdev, 0x000008e8);
907 u32temp |= 0x80000000;
908 nes_write_indexed(nesdev, 0x000008e8, u32temp);
909 u32temp = nes_read_indexed(nesdev, 0x000021f8);
910 u32temp &= 0x7fffffff;
911 u32temp |= 0x7fff0010;
912 nes_write_indexed(nesdev, 0x000021f8, u32temp);
913 }
914}
915
916
917/**
918 * nes_destroy_adapter - destroy the adapter structure
919 */
920void nes_destroy_adapter(struct nes_adapter *nesadapter)
921{
922 struct nes_adapter *tmp_adapter;
923
924 list_for_each_entry(tmp_adapter, &nes_adapter_list, list) {
925 nes_debug(NES_DBG_SHUTDOWN, "Nes Adapter list entry = 0x%p.\n",
926 tmp_adapter);
927 }
928
929 nesadapter->ref_count--;
930 if (!nesadapter->ref_count) {
931 if (nesadapter->hw_rev == NE020_REV) {
932 del_timer(&nesadapter->mh_timer);
933 }
934 del_timer(&nesadapter->lc_timer);
935
936 list_del(&nesadapter->list);
937 kfree(nesadapter);
938 }
939}
940
941
942/**
943 * nes_init_cqp
944 */
945int nes_init_cqp(struct nes_device *nesdev)
946{
947 struct nes_adapter *nesadapter = nesdev->nesadapter;
948 struct nes_hw_cqp_qp_context *cqp_qp_context;
949 struct nes_hw_cqp_wqe *cqp_wqe;
950 struct nes_hw_ceq *ceq;
951 struct nes_hw_ceq *nic_ceq;
952 struct nes_hw_aeq *aeq;
953 void *vmem;
954 dma_addr_t pmem;
955 u32 count=0;
956 u32 cqp_head;
957 u64 u64temp;
958 u32 u32temp;
959
960 /* allocate CQP memory */
961 /* Need to add max_cq to the aeq size once cq overflow checking is added back */
962 /* SQ is 512 byte aligned, others are 256 byte aligned */
963 nesdev->cqp_mem_size = 512 +
964 (sizeof(struct nes_hw_cqp_wqe) * NES_CQP_SQ_SIZE) +
965 (sizeof(struct nes_hw_cqe) * NES_CCQ_SIZE) +
966 max(((u32)sizeof(struct nes_hw_ceqe) * NES_CCEQ_SIZE), (u32)256) +
967 max(((u32)sizeof(struct nes_hw_ceqe) * NES_NIC_CEQ_SIZE), (u32)256) +
968 (sizeof(struct nes_hw_aeqe) * nesadapter->max_qp) +
969 sizeof(struct nes_hw_cqp_qp_context);
970
971 nesdev->cqp_vbase = pci_alloc_consistent(nesdev->pcidev, nesdev->cqp_mem_size,
972 &nesdev->cqp_pbase);
973 if (!nesdev->cqp_vbase) {
974 nes_debug(NES_DBG_INIT, "Unable to allocate memory for host descriptor rings\n");
975 return -ENOMEM;
976 }
977 memset(nesdev->cqp_vbase, 0, nesdev->cqp_mem_size);
978
979 /* Allocate a twice the number of CQP requests as the SQ size */
980 nesdev->nes_cqp_requests = kzalloc(sizeof(struct nes_cqp_request) *
981 2 * NES_CQP_SQ_SIZE, GFP_KERNEL);
982 if (nesdev->nes_cqp_requests == NULL) {
983 nes_debug(NES_DBG_INIT, "Unable to allocate memory CQP request entries.\n");
984 pci_free_consistent(nesdev->pcidev, nesdev->cqp_mem_size, nesdev->cqp.sq_vbase,
985 nesdev->cqp.sq_pbase);
986 return -ENOMEM;
987 }
988
989 nes_debug(NES_DBG_INIT, "Allocated CQP structures at %p (phys = %016lX), size = %u.\n",
990 nesdev->cqp_vbase, (unsigned long)nesdev->cqp_pbase, nesdev->cqp_mem_size);
991
992 spin_lock_init(&nesdev->cqp.lock);
993 init_waitqueue_head(&nesdev->cqp.waitq);
994
995 /* Setup Various Structures */
996 vmem = (void *)(((unsigned long)nesdev->cqp_vbase + (512 - 1)) &
997 ~(unsigned long)(512 - 1));
998 pmem = (dma_addr_t)(((unsigned long long)nesdev->cqp_pbase + (512 - 1)) &
999 ~(unsigned long long)(512 - 1));
1000
1001 nesdev->cqp.sq_vbase = vmem;
1002 nesdev->cqp.sq_pbase = pmem;
1003 nesdev->cqp.sq_size = NES_CQP_SQ_SIZE;
1004 nesdev->cqp.sq_head = 0;
1005 nesdev->cqp.sq_tail = 0;
1006 nesdev->cqp.qp_id = PCI_FUNC(nesdev->pcidev->devfn);
1007
1008 vmem += (sizeof(struct nes_hw_cqp_wqe) * nesdev->cqp.sq_size);
1009 pmem += (sizeof(struct nes_hw_cqp_wqe) * nesdev->cqp.sq_size);
1010
1011 nesdev->ccq.cq_vbase = vmem;
1012 nesdev->ccq.cq_pbase = pmem;
1013 nesdev->ccq.cq_size = NES_CCQ_SIZE;
1014 nesdev->ccq.cq_head = 0;
1015 nesdev->ccq.ce_handler = nes_cqp_ce_handler;
1016 nesdev->ccq.cq_number = PCI_FUNC(nesdev->pcidev->devfn);
1017
1018 vmem += (sizeof(struct nes_hw_cqe) * nesdev->ccq.cq_size);
1019 pmem += (sizeof(struct nes_hw_cqe) * nesdev->ccq.cq_size);
1020
1021 nesdev->ceq_index = PCI_FUNC(nesdev->pcidev->devfn);
1022 ceq = &nesadapter->ceq[nesdev->ceq_index];
1023 ceq->ceq_vbase = vmem;
1024 ceq->ceq_pbase = pmem;
1025 ceq->ceq_size = NES_CCEQ_SIZE;
1026 ceq->ceq_head = 0;
1027
1028 vmem += max(((u32)sizeof(struct nes_hw_ceqe) * ceq->ceq_size), (u32)256);
1029 pmem += max(((u32)sizeof(struct nes_hw_ceqe) * ceq->ceq_size), (u32)256);
1030
1031 nesdev->nic_ceq_index = PCI_FUNC(nesdev->pcidev->devfn) + 8;
1032 nic_ceq = &nesadapter->ceq[nesdev->nic_ceq_index];
1033 nic_ceq->ceq_vbase = vmem;
1034 nic_ceq->ceq_pbase = pmem;
1035 nic_ceq->ceq_size = NES_NIC_CEQ_SIZE;
1036 nic_ceq->ceq_head = 0;
1037
1038 vmem += max(((u32)sizeof(struct nes_hw_ceqe) * nic_ceq->ceq_size), (u32)256);
1039 pmem += max(((u32)sizeof(struct nes_hw_ceqe) * nic_ceq->ceq_size), (u32)256);
1040
1041 aeq = &nesadapter->aeq[PCI_FUNC(nesdev->pcidev->devfn)];
1042 aeq->aeq_vbase = vmem;
1043 aeq->aeq_pbase = pmem;
1044 aeq->aeq_size = nesadapter->max_qp;
1045 aeq->aeq_head = 0;
1046
1047 /* Setup QP Context */
1048 vmem += (sizeof(struct nes_hw_aeqe) * aeq->aeq_size);
1049 pmem += (sizeof(struct nes_hw_aeqe) * aeq->aeq_size);
1050
1051 cqp_qp_context = vmem;
1052 cqp_qp_context->context_words[0] =
1053 cpu_to_le32((PCI_FUNC(nesdev->pcidev->devfn) << 12) + (2 << 10));
1054 cqp_qp_context->context_words[1] = 0;
1055 cqp_qp_context->context_words[2] = cpu_to_le32((u32)nesdev->cqp.sq_pbase);
1056 cqp_qp_context->context_words[3] = cpu_to_le32(((u64)nesdev->cqp.sq_pbase) >> 32);
1057
1058
1059 /* Write the address to Create CQP */
1060 if ((sizeof(dma_addr_t) > 4)) {
1061 nes_write_indexed(nesdev,
1062 NES_IDX_CREATE_CQP_HIGH + (PCI_FUNC(nesdev->pcidev->devfn) * 8),
1063 ((u64)pmem) >> 32);
1064 } else {
1065 nes_write_indexed(nesdev,
1066 NES_IDX_CREATE_CQP_HIGH + (PCI_FUNC(nesdev->pcidev->devfn) * 8), 0);
1067 }
1068 nes_write_indexed(nesdev,
1069 NES_IDX_CREATE_CQP_LOW + (PCI_FUNC(nesdev->pcidev->devfn) * 8),
1070 (u32)pmem);
1071
1072 INIT_LIST_HEAD(&nesdev->cqp_avail_reqs);
1073 INIT_LIST_HEAD(&nesdev->cqp_pending_reqs);
1074
1075 for (count = 0; count < 2*NES_CQP_SQ_SIZE; count++) {
1076 init_waitqueue_head(&nesdev->nes_cqp_requests[count].waitq);
1077 list_add_tail(&nesdev->nes_cqp_requests[count].list, &nesdev->cqp_avail_reqs);
1078 }
1079
1080 /* Write Create CCQ WQE */
1081 cqp_head = nesdev->cqp.sq_head++;
1082 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1083 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
1084 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
1085 (NES_CQP_CREATE_CQ | NES_CQP_CQ_CEQ_VALID |
1086 NES_CQP_CQ_CHK_OVERFLOW | ((u32)nesdev->ccq.cq_size << 16)));
1087 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,
1088 (nesdev->ccq.cq_number |
1089 ((u32)nesdev->ceq_index << 16)));
1090 u64temp = (u64)nesdev->ccq.cq_pbase;
1091 set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);
1092 cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] = 0;
1093 u64temp = (unsigned long)&nesdev->ccq;
1094 cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_LOW_IDX] =
1095 cpu_to_le32((u32)(u64temp >> 1));
1096 cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] =
1097 cpu_to_le32(((u32)((u64temp) >> 33)) & 0x7FFFFFFF);
1098 cqp_wqe->wqe_words[NES_CQP_CQ_WQE_DOORBELL_INDEX_HIGH_IDX] = 0;
1099
1100 /* Write Create CEQ WQE */
1101 cqp_head = nesdev->cqp.sq_head++;
1102 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1103 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
1104 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
1105 (NES_CQP_CREATE_CEQ + ((u32)nesdev->ceq_index << 8)));
1106 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_CEQ_WQE_ELEMENT_COUNT_IDX, ceq->ceq_size);
1107 u64temp = (u64)ceq->ceq_pbase;
1108 set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);
1109
1110 /* Write Create AEQ WQE */
1111 cqp_head = nesdev->cqp.sq_head++;
1112 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1113 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
1114 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
1115 (NES_CQP_CREATE_AEQ + ((u32)PCI_FUNC(nesdev->pcidev->devfn) << 8)));
1116 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_AEQ_WQE_ELEMENT_COUNT_IDX, aeq->aeq_size);
1117 u64temp = (u64)aeq->aeq_pbase;
1118 set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);
1119
1120 /* Write Create NIC CEQ WQE */
1121 cqp_head = nesdev->cqp.sq_head++;
1122 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1123 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
1124 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
1125 (NES_CQP_CREATE_CEQ + ((u32)nesdev->nic_ceq_index << 8)));
1126 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_CEQ_WQE_ELEMENT_COUNT_IDX, nic_ceq->ceq_size);
1127 u64temp = (u64)nic_ceq->ceq_pbase;
1128 set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);
1129
1130 /* Poll until CCQP done */
1131 count = 0;
1132 do {
1133 if (count++ > 1000) {
1134 printk(KERN_ERR PFX "Error creating CQP\n");
1135 pci_free_consistent(nesdev->pcidev, nesdev->cqp_mem_size,
1136 nesdev->cqp_vbase, nesdev->cqp_pbase);
1137 return -1;
1138 }
1139 udelay(10);
1140 } while (!(nes_read_indexed(nesdev,
1141 NES_IDX_QP_CONTROL + (PCI_FUNC(nesdev->pcidev->devfn) * 8)) & (1 << 8)));
1142
1143 nes_debug(NES_DBG_INIT, "CQP Status = 0x%08X\n", nes_read_indexed(nesdev,
1144 NES_IDX_QP_CONTROL+(PCI_FUNC(nesdev->pcidev->devfn)*8)));
1145
1146 u32temp = 0x04800000;
1147 nes_write32(nesdev->regs+NES_WQE_ALLOC, u32temp | nesdev->cqp.qp_id);
1148
1149 /* wait for the CCQ, CEQ, and AEQ to get created */
1150 count = 0;
1151 do {
1152 if (count++ > 1000) {
1153 printk(KERN_ERR PFX "Error creating CCQ, CEQ, and AEQ\n");
1154 pci_free_consistent(nesdev->pcidev, nesdev->cqp_mem_size,
1155 nesdev->cqp_vbase, nesdev->cqp_pbase);
1156 return -1;
1157 }
1158 udelay(10);
1159 } while (((nes_read_indexed(nesdev,
1160 NES_IDX_QP_CONTROL+(PCI_FUNC(nesdev->pcidev->devfn)*8)) & (15<<8)) != (15<<8)));
1161
1162 /* dump the QP status value */
1163 nes_debug(NES_DBG_INIT, "QP Status = 0x%08X\n", nes_read_indexed(nesdev,
1164 NES_IDX_QP_CONTROL+(PCI_FUNC(nesdev->pcidev->devfn)*8)));
1165
1166 nesdev->cqp.sq_tail++;
1167
1168 return 0;
1169}
1170
1171
1172/**
1173 * nes_destroy_cqp
1174 */
1175int nes_destroy_cqp(struct nes_device *nesdev)
1176{
1177 struct nes_hw_cqp_wqe *cqp_wqe;
1178 u32 count = 0;
1179 u32 cqp_head;
1180 unsigned long flags;
1181
1182 do {
1183 if (count++ > 1000)
1184 break;
1185 udelay(10);
1186 } while (!(nesdev->cqp.sq_head == nesdev->cqp.sq_tail));
1187
1188 /* Reset CCQ */
1189 nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_RESET |
1190 nesdev->ccq.cq_number);
1191
1192 /* Disable device interrupts */
1193 nes_write32(nesdev->regs+NES_INT_MASK, 0x7fffffff);
1194
1195 spin_lock_irqsave(&nesdev->cqp.lock, flags);
1196
1197 /* Destroy the AEQ */
1198 cqp_head = nesdev->cqp.sq_head++;
1199 nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
1200 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1201 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_AEQ |
1202 ((u32)PCI_FUNC(nesdev->pcidev->devfn) << 8));
1203 cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0;
1204
1205 /* Destroy the NIC CEQ */
1206 cqp_head = nesdev->cqp.sq_head++;
1207 nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
1208 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1209 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_CEQ |
1210 ((u32)nesdev->nic_ceq_index << 8));
1211
1212 /* Destroy the CEQ */
1213 cqp_head = nesdev->cqp.sq_head++;
1214 nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
1215 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1216 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_CEQ |
1217 (nesdev->ceq_index << 8));
1218
1219 /* Destroy the CCQ */
1220 cqp_head = nesdev->cqp.sq_head++;
1221 nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
1222 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1223 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_CQ);
1224 cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesdev->ccq.cq_number |
1225 ((u32)nesdev->ceq_index << 16));
1226
1227 /* Destroy CQP */
1228 cqp_head = nesdev->cqp.sq_head++;
1229 nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
1230 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1231 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_QP |
1232 NES_CQP_QP_TYPE_CQP);
1233 cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesdev->cqp.qp_id);
1234
1235 barrier();
1236 /* Ring doorbell (5 WQEs) */
1237 nes_write32(nesdev->regs+NES_WQE_ALLOC, 0x05800000 | nesdev->cqp.qp_id);
1238
1239 spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
1240
1241 /* wait for the CCQ, CEQ, and AEQ to get destroyed */
1242 count = 0;
1243 do {
1244 if (count++ > 1000) {
1245 printk(KERN_ERR PFX "Function%d: Error destroying CCQ, CEQ, and AEQ\n",
1246 PCI_FUNC(nesdev->pcidev->devfn));
1247 break;
1248 }
1249 udelay(10);
1250 } while (((nes_read_indexed(nesdev,
1251 NES_IDX_QP_CONTROL + (PCI_FUNC(nesdev->pcidev->devfn)*8)) & (15 << 8)) != 0));
1252
1253 /* dump the QP status value */
1254 nes_debug(NES_DBG_SHUTDOWN, "Function%d: QP Status = 0x%08X\n",
1255 PCI_FUNC(nesdev->pcidev->devfn),
1256 nes_read_indexed(nesdev,
1257 NES_IDX_QP_CONTROL+(PCI_FUNC(nesdev->pcidev->devfn)*8)));
1258
1259 kfree(nesdev->nes_cqp_requests);
1260
1261 /* Free the control structures */
1262 pci_free_consistent(nesdev->pcidev, nesdev->cqp_mem_size, nesdev->cqp.sq_vbase,
1263 nesdev->cqp.sq_pbase);
1264
1265 return 0;
1266}
1267
1268
1269/**
1270 * nes_init_phy
1271 */
1272int nes_init_phy(struct nes_device *nesdev)
1273{
1274 struct nes_adapter *nesadapter = nesdev->nesadapter;
1275 u32 counter = 0;
Chien Tung1b949322009-04-08 14:27:09 -07001276 u32 sds;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001277 u32 mac_index = nesdev->mac_index;
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001278 u32 tx_config = 0;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001279 u16 phy_data;
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001280 u32 temp_phy_data = 0;
1281 u32 temp_phy_data2 = 0;
Chien Tung1b949322009-04-08 14:27:09 -07001282 u8 phy_type = nesadapter->phy_type[mac_index];
1283 u8 phy_index = nesadapter->phy_index[mac_index];
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001284
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001285 if ((nesadapter->OneG_Mode) &&
Chien Tung1b949322009-04-08 14:27:09 -07001286 (phy_type != NES_PHY_TYPE_PUMA_1G)) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001287 nes_debug(NES_DBG_PHY, "1G PHY, mac_index = %d.\n", mac_index);
Chien Tung1b949322009-04-08 14:27:09 -07001288 if (phy_type == NES_PHY_TYPE_1G) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001289 tx_config = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG);
Chien Tunge88bd7b2008-09-26 15:08:10 -05001290 tx_config &= 0xFFFFFFE3;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001291 tx_config |= 0x04;
1292 nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config);
1293 }
1294
Chien Tung1b949322009-04-08 14:27:09 -07001295 nes_read_1G_phy_reg(nesdev, 1, phy_index, &phy_data);
1296 nes_write_1G_phy_reg(nesdev, 23, phy_index, 0xb000);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001297
1298 /* Reset the PHY */
Chien Tung1b949322009-04-08 14:27:09 -07001299 nes_write_1G_phy_reg(nesdev, 0, phy_index, 0x8000);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001300 udelay(100);
1301 counter = 0;
1302 do {
Chien Tung1b949322009-04-08 14:27:09 -07001303 nes_read_1G_phy_reg(nesdev, 0, phy_index, &phy_data);
1304 if (counter++ > 100)
1305 break;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001306 } while (phy_data & 0x8000);
1307
1308 /* Setting no phy loopback */
1309 phy_data &= 0xbfff;
1310 phy_data |= 0x1140;
Chien Tung1b949322009-04-08 14:27:09 -07001311 nes_write_1G_phy_reg(nesdev, 0, phy_index, phy_data);
1312 nes_read_1G_phy_reg(nesdev, 0, phy_index, &phy_data);
1313 nes_read_1G_phy_reg(nesdev, 0x17, phy_index, &phy_data);
1314 nes_read_1G_phy_reg(nesdev, 0x1e, phy_index, &phy_data);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001315
1316 /* Setting the interrupt mask */
Chien Tung1b949322009-04-08 14:27:09 -07001317 nes_read_1G_phy_reg(nesdev, 0x19, phy_index, &phy_data);
1318 nes_write_1G_phy_reg(nesdev, 0x19, phy_index, 0xffee);
1319 nes_read_1G_phy_reg(nesdev, 0x19, phy_index, &phy_data);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001320
1321 /* turning on flow control */
Chien Tung1b949322009-04-08 14:27:09 -07001322 nes_read_1G_phy_reg(nesdev, 4, phy_index, &phy_data);
1323 nes_write_1G_phy_reg(nesdev, 4, phy_index, (phy_data & ~(0x03E0)) | 0xc00);
1324 nes_read_1G_phy_reg(nesdev, 4, phy_index, &phy_data);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001325
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001326 /* Clear Half duplex */
Chien Tung1b949322009-04-08 14:27:09 -07001327 nes_read_1G_phy_reg(nesdev, 9, phy_index, &phy_data);
1328 nes_write_1G_phy_reg(nesdev, 9, phy_index, phy_data & ~(0x0100));
1329 nes_read_1G_phy_reg(nesdev, 9, phy_index, &phy_data);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001330
Chien Tung1b949322009-04-08 14:27:09 -07001331 nes_read_1G_phy_reg(nesdev, 0, phy_index, &phy_data);
1332 nes_write_1G_phy_reg(nesdev, 0, phy_index, phy_data | 0x0300);
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001333
Chien Tung1b949322009-04-08 14:27:09 -07001334 return 0;
1335 }
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001336
Chien Tung1b949322009-04-08 14:27:09 -07001337 if ((phy_type == NES_PHY_TYPE_IRIS) ||
Chien Tung43035652009-04-08 14:27:56 -07001338 (phy_type == NES_PHY_TYPE_ARGUS) ||
1339 (phy_type == NES_PHY_TYPE_SFP_D)) {
Chien Tung1b949322009-04-08 14:27:09 -07001340 /* setup 10G MDIO operation */
1341 tx_config = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG);
1342 tx_config &= 0xFFFFFFE3;
1343 tx_config |= 0x15;
1344 nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config);
1345 }
Chien Tung43035652009-04-08 14:27:56 -07001346 if ((phy_type == NES_PHY_TYPE_ARGUS) ||
1347 (phy_type == NES_PHY_TYPE_SFP_D)) {
Chien Tung1b949322009-04-08 14:27:09 -07001348 /* Check firmware heartbeat */
1349 nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee);
1350 temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
1351 udelay(1500);
1352 nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee);
1353 temp_phy_data2 = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001354
Chien Tung1b949322009-04-08 14:27:09 -07001355 if (temp_phy_data != temp_phy_data2)
1356 return 0;
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001357
Chien Tung1b949322009-04-08 14:27:09 -07001358 /* no heartbeat, configure the PHY */
1359 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0x0000, 0x8000);
1360 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc300, 0x0000);
Chien Tung1b949322009-04-08 14:27:09 -07001361 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc316, 0x000A);
1362 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc318, 0x0052);
Chien Tung43035652009-04-08 14:27:56 -07001363 if (phy_type == NES_PHY_TYPE_ARGUS) {
1364 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc302, 0x000C);
1365 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc319, 0x0008);
1366 } else {
1367 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc302, 0x0004);
1368 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc319, 0x0038);
1369 }
Chien Tung1b949322009-04-08 14:27:09 -07001370 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc31a, 0x0098);
1371 nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0026, 0x0E00);
1372 nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0027, 0x0001);
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001373
Chien Tung1b949322009-04-08 14:27:09 -07001374 /* setup LEDs */
1375 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd006, 0x0007);
1376 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd007, 0x000A);
1377 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd008, 0x0009);
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001378
Chien Tung1b949322009-04-08 14:27:09 -07001379 nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0028, 0xA528);
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001380
Chien Tung1b949322009-04-08 14:27:09 -07001381 /* Bring PHY out of reset */
1382 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc300, 0x0002);
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001383
Chien Tung1b949322009-04-08 14:27:09 -07001384 /* Check for heartbeat */
1385 counter = 0;
1386 mdelay(690);
1387 nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee);
1388 temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
1389 do {
1390 if (counter++ > 150) {
1391 nes_debug(NES_DBG_PHY, "No PHY heartbeat\n");
1392 break;
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001393 }
Chien Tung1b949322009-04-08 14:27:09 -07001394 mdelay(1);
1395 nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee);
1396 temp_phy_data2 = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
1397 } while ((temp_phy_data2 == temp_phy_data));
1398
1399 /* wait for tracking */
1400 counter = 0;
1401 do {
1402 nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7fd);
1403 temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
1404 if (counter++ > 300) {
1405 nes_debug(NES_DBG_PHY, "PHY did not track\n");
1406 break;
1407 }
1408 mdelay(10);
1409 } while (((temp_phy_data & 0xff) != 0x50) && ((temp_phy_data & 0xff) != 0x70));
1410
1411 /* setup signal integrity */
1412 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd003, 0x0000);
1413 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xF00D, 0x00FE);
1414 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xF00E, 0x0032);
1415 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xF00F, 0x0002);
1416 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc314, 0x0063);
1417
1418 /* reset serdes */
1419 sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0 +
1420 mac_index * 0x200);
1421 sds |= 0x1;
1422 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0 +
1423 mac_index * 0x200, sds);
1424 sds &= 0xfffffffe;
1425 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0 +
1426 mac_index * 0x200, sds);
1427
1428 counter = 0;
1429 while (((nes_read32(nesdev->regs + NES_SOFTWARE_RESET) & 0x00000040) != 0x00000040)
1430 && (counter++ < 5000))
1431 ;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001432 }
1433 return 0;
1434}
1435
1436
1437/**
1438 * nes_replenish_nic_rq
1439 */
1440static void nes_replenish_nic_rq(struct nes_vnic *nesvnic)
1441{
1442 unsigned long flags;
1443 dma_addr_t bus_address;
1444 struct sk_buff *skb;
1445 struct nes_hw_nic_rq_wqe *nic_rqe;
1446 struct nes_hw_nic *nesnic;
1447 struct nes_device *nesdev;
1448 u32 rx_wqes_posted = 0;
1449
1450 nesnic = &nesvnic->nic;
1451 nesdev = nesvnic->nesdev;
1452 spin_lock_irqsave(&nesnic->rq_lock, flags);
1453 if (nesnic->replenishing_rq !=0) {
1454 if (((nesnic->rq_size-1) == atomic_read(&nesvnic->rx_skbs_needed)) &&
1455 (atomic_read(&nesvnic->rx_skb_timer_running) == 0)) {
1456 atomic_set(&nesvnic->rx_skb_timer_running, 1);
1457 spin_unlock_irqrestore(&nesnic->rq_lock, flags);
1458 nesvnic->rq_wqes_timer.expires = jiffies + (HZ/2); /* 1/2 second */
1459 add_timer(&nesvnic->rq_wqes_timer);
1460 } else
1461 spin_unlock_irqrestore(&nesnic->rq_lock, flags);
1462 return;
1463 }
1464 nesnic->replenishing_rq = 1;
1465 spin_unlock_irqrestore(&nesnic->rq_lock, flags);
1466 do {
1467 skb = dev_alloc_skb(nesvnic->max_frame_size);
1468 if (skb) {
1469 skb->dev = nesvnic->netdev;
1470
1471 bus_address = pci_map_single(nesdev->pcidev,
1472 skb->data, nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
1473
1474 nic_rqe = &nesnic->rq_vbase[nesvnic->nic.rq_head];
1475 nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] =
1476 cpu_to_le32(nesvnic->max_frame_size);
1477 nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_3_2_IDX] = 0;
1478 nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX] =
1479 cpu_to_le32((u32)bus_address);
1480 nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX] =
1481 cpu_to_le32((u32)((u64)bus_address >> 32));
1482 nesnic->rx_skb[nesnic->rq_head] = skb;
1483 nesnic->rq_head++;
1484 nesnic->rq_head &= nesnic->rq_size - 1;
1485 atomic_dec(&nesvnic->rx_skbs_needed);
1486 barrier();
1487 if (++rx_wqes_posted == 255) {
1488 nes_write32(nesdev->regs+NES_WQE_ALLOC, (rx_wqes_posted << 24) | nesnic->qp_id);
1489 rx_wqes_posted = 0;
1490 }
1491 } else {
1492 spin_lock_irqsave(&nesnic->rq_lock, flags);
1493 if (((nesnic->rq_size-1) == atomic_read(&nesvnic->rx_skbs_needed)) &&
1494 (atomic_read(&nesvnic->rx_skb_timer_running) == 0)) {
1495 atomic_set(&nesvnic->rx_skb_timer_running, 1);
1496 spin_unlock_irqrestore(&nesnic->rq_lock, flags);
1497 nesvnic->rq_wqes_timer.expires = jiffies + (HZ/2); /* 1/2 second */
1498 add_timer(&nesvnic->rq_wqes_timer);
1499 } else
1500 spin_unlock_irqrestore(&nesnic->rq_lock, flags);
1501 break;
1502 }
1503 } while (atomic_read(&nesvnic->rx_skbs_needed));
1504 barrier();
1505 if (rx_wqes_posted)
1506 nes_write32(nesdev->regs+NES_WQE_ALLOC, (rx_wqes_posted << 24) | nesnic->qp_id);
1507 nesnic->replenishing_rq = 0;
1508}
1509
1510
1511/**
1512 * nes_rq_wqes_timeout
1513 */
1514static void nes_rq_wqes_timeout(unsigned long parm)
1515{
1516 struct nes_vnic *nesvnic = (struct nes_vnic *)parm;
Harvey Harrison33718362008-04-16 21:01:10 -07001517 printk("%s: Timer fired.\n", __func__);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001518 atomic_set(&nesvnic->rx_skb_timer_running, 0);
1519 if (atomic_read(&nesvnic->rx_skbs_needed))
1520 nes_replenish_nic_rq(nesvnic);
1521}
1522
1523
Faisal Latif37dab412008-04-29 13:46:54 -07001524static int nes_lro_get_skb_hdr(struct sk_buff *skb, void **iphdr,
1525 void **tcph, u64 *hdr_flags, void *priv)
1526{
1527 unsigned int ip_len;
1528 struct iphdr *iph;
1529 skb_reset_network_header(skb);
1530 iph = ip_hdr(skb);
1531 if (iph->protocol != IPPROTO_TCP)
1532 return -1;
1533 ip_len = ip_hdrlen(skb);
1534 skb_set_transport_header(skb, ip_len);
1535 *tcph = tcp_hdr(skb);
1536
1537 *hdr_flags = LRO_IPV4 | LRO_TCP;
1538 *iphdr = iph;
1539 return 0;
1540}
1541
1542
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001543/**
1544 * nes_init_nic_qp
1545 */
1546int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
1547{
1548 struct nes_hw_cqp_wqe *cqp_wqe;
1549 struct nes_hw_nic_sq_wqe *nic_sqe;
1550 struct nes_hw_nic_qp_context *nic_context;
1551 struct sk_buff *skb;
1552 struct nes_hw_nic_rq_wqe *nic_rqe;
1553 struct nes_vnic *nesvnic = netdev_priv(netdev);
1554 unsigned long flags;
1555 void *vmem;
1556 dma_addr_t pmem;
1557 u64 u64temp;
1558 int ret;
1559 u32 cqp_head;
1560 u32 counter;
1561 u32 wqe_count;
1562 u8 jumbomode=0;
1563
1564 /* Allocate fragment, SQ, RQ, and CQ; Reuse CEQ based on the PCI function */
1565 nesvnic->nic_mem_size = 256 +
1566 (NES_NIC_WQ_SIZE * sizeof(struct nes_first_frag)) +
1567 (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_sq_wqe)) +
1568 (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_rq_wqe)) +
1569 (NES_NIC_WQ_SIZE * 2 * sizeof(struct nes_hw_nic_cqe)) +
1570 sizeof(struct nes_hw_nic_qp_context);
1571
1572 nesvnic->nic_vbase = pci_alloc_consistent(nesdev->pcidev, nesvnic->nic_mem_size,
1573 &nesvnic->nic_pbase);
1574 if (!nesvnic->nic_vbase) {
1575 nes_debug(NES_DBG_INIT, "Unable to allocate memory for NIC host descriptor rings\n");
1576 return -ENOMEM;
1577 }
1578 memset(nesvnic->nic_vbase, 0, nesvnic->nic_mem_size);
1579 nes_debug(NES_DBG_INIT, "Allocated NIC QP structures at %p (phys = %016lX), size = %u.\n",
1580 nesvnic->nic_vbase, (unsigned long)nesvnic->nic_pbase, nesvnic->nic_mem_size);
1581
1582 vmem = (void *)(((unsigned long)nesvnic->nic_vbase + (256 - 1)) &
1583 ~(unsigned long)(256 - 1));
1584 pmem = (dma_addr_t)(((unsigned long long)nesvnic->nic_pbase + (256 - 1)) &
1585 ~(unsigned long long)(256 - 1));
1586
1587 /* Setup the first Fragment buffers */
1588 nesvnic->nic.first_frag_vbase = vmem;
1589
1590 for (counter = 0; counter < NES_NIC_WQ_SIZE; counter++) {
1591 nesvnic->nic.frag_paddr[counter] = pmem;
1592 pmem += sizeof(struct nes_first_frag);
1593 }
1594
1595 /* setup the SQ */
1596 vmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_first_frag));
1597
1598 nesvnic->nic.sq_vbase = (void *)vmem;
1599 nesvnic->nic.sq_pbase = pmem;
1600 nesvnic->nic.sq_head = 0;
1601 nesvnic->nic.sq_tail = 0;
1602 nesvnic->nic.sq_size = NES_NIC_WQ_SIZE;
1603 for (counter = 0; counter < NES_NIC_WQ_SIZE; counter++) {
1604 nic_sqe = &nesvnic->nic.sq_vbase[counter];
1605 nic_sqe->wqe_words[NES_NIC_SQ_WQE_MISC_IDX] =
1606 cpu_to_le32(NES_NIC_SQ_WQE_DISABLE_CHKSUM |
1607 NES_NIC_SQ_WQE_COMPLETION);
1608 nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX] =
1609 cpu_to_le32((u32)NES_FIRST_FRAG_SIZE << 16);
1610 nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX] =
1611 cpu_to_le32((u32)nesvnic->nic.frag_paddr[counter]);
1612 nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX] =
1613 cpu_to_le32((u32)((u64)nesvnic->nic.frag_paddr[counter] >> 32));
1614 }
1615
1616 nesvnic->get_cqp_request = nes_get_cqp_request;
1617 nesvnic->post_cqp_request = nes_post_cqp_request;
1618 nesvnic->mcrq_mcast_filter = NULL;
1619
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001620 spin_lock_init(&nesvnic->nic.rq_lock);
1621
1622 /* setup the RQ */
1623 vmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_sq_wqe));
1624 pmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_sq_wqe));
1625
1626
1627 nesvnic->nic.rq_vbase = vmem;
1628 nesvnic->nic.rq_pbase = pmem;
1629 nesvnic->nic.rq_head = 0;
1630 nesvnic->nic.rq_tail = 0;
1631 nesvnic->nic.rq_size = NES_NIC_WQ_SIZE;
1632
1633 /* setup the CQ */
1634 vmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_rq_wqe));
1635 pmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_rq_wqe));
1636
1637 if (nesdev->nesadapter->netdev_count > 2)
1638 nesvnic->mcrq_qp_id = nesvnic->nic_index + 32;
1639 else
1640 nesvnic->mcrq_qp_id = nesvnic->nic.qp_id + 4;
1641
1642 nesvnic->nic_cq.cq_vbase = vmem;
1643 nesvnic->nic_cq.cq_pbase = pmem;
1644 nesvnic->nic_cq.cq_head = 0;
1645 nesvnic->nic_cq.cq_size = NES_NIC_WQ_SIZE * 2;
1646
1647 nesvnic->nic_cq.ce_handler = nes_nic_napi_ce_handler;
1648
1649 /* Send CreateCQ request to CQP */
1650 spin_lock_irqsave(&nesdev->cqp.lock, flags);
1651 cqp_head = nesdev->cqp.sq_head;
1652
1653 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1654 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
1655
1656 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(
1657 NES_CQP_CREATE_CQ | NES_CQP_CQ_CEQ_VALID |
1658 ((u32)nesvnic->nic_cq.cq_size << 16));
1659 cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(
1660 nesvnic->nic_cq.cq_number | ((u32)nesdev->nic_ceq_index << 16));
1661 u64temp = (u64)nesvnic->nic_cq.cq_pbase;
1662 set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);
1663 cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] = 0;
1664 u64temp = (unsigned long)&nesvnic->nic_cq;
1665 cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_LOW_IDX] = cpu_to_le32((u32)(u64temp >> 1));
1666 cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] =
1667 cpu_to_le32(((u32)((u64temp) >> 33)) & 0x7FFFFFFF);
1668 cqp_wqe->wqe_words[NES_CQP_CQ_WQE_DOORBELL_INDEX_HIGH_IDX] = 0;
1669 if (++cqp_head >= nesdev->cqp.sq_size)
1670 cqp_head = 0;
1671 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1672 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
1673
1674 /* Send CreateQP request to CQP */
1675 nic_context = (void *)(&nesvnic->nic_cq.cq_vbase[nesvnic->nic_cq.cq_size]);
1676 nic_context->context_words[NES_NIC_CTX_MISC_IDX] =
1677 cpu_to_le32((u32)NES_NIC_CTX_SIZE |
1678 ((u32)PCI_FUNC(nesdev->pcidev->devfn) << 12));
1679 nes_debug(NES_DBG_INIT, "RX_WINDOW_BUFFER_PAGE_TABLE_SIZE = 0x%08X, RX_WINDOW_BUFFER_SIZE = 0x%08X\n",
1680 nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_PAGE_TABLE_SIZE),
1681 nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_SIZE));
1682 if (nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_SIZE) != 0) {
1683 nic_context->context_words[NES_NIC_CTX_MISC_IDX] |= cpu_to_le32(NES_NIC_BACK_STORE);
1684 }
1685
1686 u64temp = (u64)nesvnic->nic.sq_pbase;
Glenn Streiff7495ab62008-04-29 13:46:54 -07001687 nic_context->context_words[NES_NIC_CTX_SQ_LOW_IDX] = cpu_to_le32((u32)u64temp);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001688 nic_context->context_words[NES_NIC_CTX_SQ_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32));
1689 u64temp = (u64)nesvnic->nic.rq_pbase;
Glenn Streiff7495ab62008-04-29 13:46:54 -07001690 nic_context->context_words[NES_NIC_CTX_RQ_LOW_IDX] = cpu_to_le32((u32)u64temp);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001691 nic_context->context_words[NES_NIC_CTX_RQ_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32));
1692
1693 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_CREATE_QP |
1694 NES_CQP_QP_TYPE_NIC);
1695 cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesvnic->nic.qp_id);
1696 u64temp = (u64)nesvnic->nic_cq.cq_pbase +
1697 (nesvnic->nic_cq.cq_size * sizeof(struct nes_hw_nic_cqe));
1698 set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, u64temp);
1699
1700 if (++cqp_head >= nesdev->cqp.sq_size)
1701 cqp_head = 0;
1702 nesdev->cqp.sq_head = cqp_head;
1703
1704 barrier();
1705
1706 /* Ring doorbell (2 WQEs) */
1707 nes_write32(nesdev->regs+NES_WQE_ALLOC, 0x02800000 | nesdev->cqp.qp_id);
1708
1709 spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
1710 nes_debug(NES_DBG_INIT, "Waiting for create NIC QP%u to complete.\n",
1711 nesvnic->nic.qp_id);
1712
1713 ret = wait_event_timeout(nesdev->cqp.waitq, (nesdev->cqp.sq_tail == cqp_head),
1714 NES_EVENT_TIMEOUT);
1715 nes_debug(NES_DBG_INIT, "Create NIC QP%u completed, wait_event_timeout ret = %u.\n",
1716 nesvnic->nic.qp_id, ret);
1717 if (!ret) {
1718 nes_debug(NES_DBG_INIT, "NIC QP%u create timeout expired\n", nesvnic->nic.qp_id);
1719 pci_free_consistent(nesdev->pcidev, nesvnic->nic_mem_size, nesvnic->nic_vbase,
1720 nesvnic->nic_pbase);
1721 return -EIO;
1722 }
1723
1724 /* Populate the RQ */
1725 for (counter = 0; counter < (NES_NIC_WQ_SIZE - 1); counter++) {
1726 skb = dev_alloc_skb(nesvnic->max_frame_size);
1727 if (!skb) {
1728 nes_debug(NES_DBG_INIT, "%s: out of memory for receive skb\n", netdev->name);
1729
1730 nes_destroy_nic_qp(nesvnic);
1731 return -ENOMEM;
1732 }
1733
1734 skb->dev = netdev;
1735
1736 pmem = pci_map_single(nesdev->pcidev, skb->data,
1737 nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
1738
1739 nic_rqe = &nesvnic->nic.rq_vbase[counter];
1740 nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] = cpu_to_le32(nesvnic->max_frame_size);
1741 nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_3_2_IDX] = 0;
Glenn Streiff7495ab62008-04-29 13:46:54 -07001742 nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX] = cpu_to_le32((u32)pmem);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001743 nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX] = cpu_to_le32((u32)((u64)pmem >> 32));
1744 nesvnic->nic.rx_skb[counter] = skb;
1745 }
1746
1747 wqe_count = NES_NIC_WQ_SIZE - 1;
1748 nesvnic->nic.rq_head = wqe_count;
1749 barrier();
1750 do {
1751 counter = min(wqe_count, ((u32)255));
1752 wqe_count -= counter;
1753 nes_write32(nesdev->regs+NES_WQE_ALLOC, (counter << 24) | nesvnic->nic.qp_id);
1754 } while (wqe_count);
1755 init_timer(&nesvnic->rq_wqes_timer);
1756 nesvnic->rq_wqes_timer.function = nes_rq_wqes_timeout;
1757 nesvnic->rq_wqes_timer.data = (unsigned long)nesvnic;
1758 nes_debug(NES_DBG_INIT, "NAPI support Enabled\n");
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001759 if (nesdev->nesadapter->et_use_adaptive_rx_coalesce)
1760 {
1761 nes_nic_init_timer(nesdev);
1762 if (netdev->mtu > 1500)
1763 jumbomode = 1;
Faisal Latif37dab412008-04-29 13:46:54 -07001764 nes_nic_init_timer_defaults(nesdev, jumbomode);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001765 }
Roland Dreierdd378182008-05-13 11:27:25 -07001766 nesvnic->lro_mgr.max_aggr = nes_lro_max_aggr;
Glenn Streiff7495ab62008-04-29 13:46:54 -07001767 nesvnic->lro_mgr.max_desc = NES_MAX_LRO_DESCRIPTORS;
1768 nesvnic->lro_mgr.lro_arr = nesvnic->lro_desc;
Faisal Latif37dab412008-04-29 13:46:54 -07001769 nesvnic->lro_mgr.get_skb_header = nes_lro_get_skb_hdr;
Glenn Streiff7495ab62008-04-29 13:46:54 -07001770 nesvnic->lro_mgr.features = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID;
1771 nesvnic->lro_mgr.dev = netdev;
1772 nesvnic->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY;
Faisal Latif37dab412008-04-29 13:46:54 -07001773 nesvnic->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001774 return 0;
1775}
1776
1777
1778/**
1779 * nes_destroy_nic_qp
1780 */
1781void nes_destroy_nic_qp(struct nes_vnic *nesvnic)
1782{
Bob Sharp7a8d1402008-09-26 15:08:10 -05001783 u64 u64temp;
1784 dma_addr_t bus_address;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001785 struct nes_device *nesdev = nesvnic->nesdev;
1786 struct nes_hw_cqp_wqe *cqp_wqe;
Bob Sharp7a8d1402008-09-26 15:08:10 -05001787 struct nes_hw_nic_sq_wqe *nic_sqe;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001788 struct nes_hw_nic_rq_wqe *nic_rqe;
Bob Sharp7a8d1402008-09-26 15:08:10 -05001789 __le16 *wqe_fragment_length;
1790 u16 wqe_fragment_index;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001791 u64 wqe_frag;
1792 u32 cqp_head;
1793 unsigned long flags;
1794 int ret;
1795
1796 /* Free remaining NIC receive buffers */
1797 while (nesvnic->nic.rq_head != nesvnic->nic.rq_tail) {
Glenn Streiff7495ab62008-04-29 13:46:54 -07001798 nic_rqe = &nesvnic->nic.rq_vbase[nesvnic->nic.rq_tail];
Bob Sharp7a8d1402008-09-26 15:08:10 -05001799 wqe_frag = (u64)le32_to_cpu(
1800 nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]);
1801 wqe_frag |= ((u64)le32_to_cpu(
1802 nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX]))<<32;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001803 pci_unmap_single(nesdev->pcidev, (dma_addr_t)wqe_frag,
1804 nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
1805 dev_kfree_skb(nesvnic->nic.rx_skb[nesvnic->nic.rq_tail++]);
1806 nesvnic->nic.rq_tail &= (nesvnic->nic.rq_size - 1);
1807 }
1808
Bob Sharp7a8d1402008-09-26 15:08:10 -05001809 /* Free remaining NIC transmit buffers */
1810 while (nesvnic->nic.sq_head != nesvnic->nic.sq_tail) {
1811 nic_sqe = &nesvnic->nic.sq_vbase[nesvnic->nic.sq_tail];
1812 wqe_fragment_index = 1;
1813 wqe_fragment_length = (__le16 *)
1814 &nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX];
1815 /* bump past the vlan tag */
1816 wqe_fragment_length++;
1817 if (le16_to_cpu(wqe_fragment_length[wqe_fragment_index]) != 0) {
1818 u64temp = (u64)le32_to_cpu(
1819 nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX+
1820 wqe_fragment_index*2]);
1821 u64temp += ((u64)le32_to_cpu(
1822 nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX
1823 + wqe_fragment_index*2]))<<32;
1824 bus_address = (dma_addr_t)u64temp;
1825 if (test_and_clear_bit(nesvnic->nic.sq_tail,
1826 nesvnic->nic.first_frag_overflow)) {
1827 pci_unmap_single(nesdev->pcidev,
1828 bus_address,
1829 le16_to_cpu(wqe_fragment_length[
1830 wqe_fragment_index++]),
1831 PCI_DMA_TODEVICE);
1832 }
1833 for (; wqe_fragment_index < 5; wqe_fragment_index++) {
1834 if (wqe_fragment_length[wqe_fragment_index]) {
1835 u64temp = le32_to_cpu(
1836 nic_sqe->wqe_words[
1837 NES_NIC_SQ_WQE_FRAG0_LOW_IDX+
1838 wqe_fragment_index*2]);
1839 u64temp += ((u64)le32_to_cpu(
1840 nic_sqe->wqe_words[
1841 NES_NIC_SQ_WQE_FRAG0_HIGH_IDX+
1842 wqe_fragment_index*2]))<<32;
1843 bus_address = (dma_addr_t)u64temp;
1844 pci_unmap_page(nesdev->pcidev,
1845 bus_address,
1846 le16_to_cpu(
1847 wqe_fragment_length[
1848 wqe_fragment_index]),
1849 PCI_DMA_TODEVICE);
1850 } else
1851 break;
1852 }
1853 }
1854 if (nesvnic->nic.tx_skb[nesvnic->nic.sq_tail])
1855 dev_kfree_skb(
1856 nesvnic->nic.tx_skb[nesvnic->nic.sq_tail]);
1857
1858 nesvnic->nic.sq_tail = (++nesvnic->nic.sq_tail)
1859 & (nesvnic->nic.sq_size - 1);
1860 }
1861
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001862 spin_lock_irqsave(&nesdev->cqp.lock, flags);
1863
1864 /* Destroy NIC QP */
1865 cqp_head = nesdev->cqp.sq_head;
1866 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1867 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
1868
1869 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
1870 (NES_CQP_DESTROY_QP | NES_CQP_QP_TYPE_NIC));
1871 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,
1872 nesvnic->nic.qp_id);
1873
1874 if (++cqp_head >= nesdev->cqp.sq_size)
1875 cqp_head = 0;
1876
1877 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1878
1879 /* Destroy NIC CQ */
1880 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
1881 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
1882 (NES_CQP_DESTROY_CQ | ((u32)nesvnic->nic_cq.cq_size << 16)));
1883 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,
1884 (nesvnic->nic_cq.cq_number | ((u32)nesdev->nic_ceq_index << 16)));
1885
1886 if (++cqp_head >= nesdev->cqp.sq_size)
1887 cqp_head = 0;
1888
1889 nesdev->cqp.sq_head = cqp_head;
1890 barrier();
1891
1892 /* Ring doorbell (2 WQEs) */
1893 nes_write32(nesdev->regs+NES_WQE_ALLOC, 0x02800000 | nesdev->cqp.qp_id);
1894
1895 spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
1896 nes_debug(NES_DBG_SHUTDOWN, "Waiting for CQP, cqp_head=%u, cqp.sq_head=%u,"
1897 " cqp.sq_tail=%u, cqp.sq_size=%u\n",
1898 cqp_head, nesdev->cqp.sq_head,
1899 nesdev->cqp.sq_tail, nesdev->cqp.sq_size);
1900
1901 ret = wait_event_timeout(nesdev->cqp.waitq, (nesdev->cqp.sq_tail == cqp_head),
1902 NES_EVENT_TIMEOUT);
1903
1904 nes_debug(NES_DBG_SHUTDOWN, "Destroy NIC QP returned, wait_event_timeout ret = %u, cqp_head=%u,"
1905 " cqp.sq_head=%u, cqp.sq_tail=%u\n",
1906 ret, cqp_head, nesdev->cqp.sq_head, nesdev->cqp.sq_tail);
1907 if (!ret) {
1908 nes_debug(NES_DBG_SHUTDOWN, "NIC QP%u destroy timeout expired\n",
1909 nesvnic->nic.qp_id);
1910 }
1911
1912 pci_free_consistent(nesdev->pcidev, nesvnic->nic_mem_size, nesvnic->nic_vbase,
1913 nesvnic->nic_pbase);
1914}
1915
1916/**
1917 * nes_napi_isr
1918 */
1919int nes_napi_isr(struct nes_device *nesdev)
1920{
1921 struct nes_adapter *nesadapter = nesdev->nesadapter;
1922 u32 int_stat;
1923
1924 if (nesdev->napi_isr_ran) {
1925 /* interrupt status has already been read in ISR */
1926 int_stat = nesdev->int_stat;
1927 } else {
1928 int_stat = nes_read32(nesdev->regs + NES_INT_STAT);
1929 nesdev->int_stat = int_stat;
1930 nesdev->napi_isr_ran = 1;
1931 }
1932
1933 int_stat &= nesdev->int_req;
1934 /* iff NIC, process here, else wait for DPC */
1935 if ((int_stat) && ((int_stat & 0x0000ff00) == int_stat)) {
1936 nesdev->napi_isr_ran = 0;
Glenn Streiff7495ab62008-04-29 13:46:54 -07001937 nes_write32(nesdev->regs + NES_INT_STAT,
1938 (int_stat &
1939 ~(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 -08001940
1941 /* Process the CEQs */
1942 nes_process_ceq(nesdev, &nesdev->nesadapter->ceq[nesdev->nic_ceq_index]);
1943
1944 if (unlikely((((nesadapter->et_rx_coalesce_usecs_irq) &&
Glenn Streiff7495ab62008-04-29 13:46:54 -07001945 (!nesadapter->et_use_adaptive_rx_coalesce)) ||
1946 ((nesadapter->et_use_adaptive_rx_coalesce) &&
1947 (nesdev->deepcq_count > nesadapter->et_pkt_rate_low))))) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001948 if ((nesdev->int_req & NES_INT_TIMER) == 0) {
1949 /* Enable Periodic timer interrupts */
1950 nesdev->int_req |= NES_INT_TIMER;
1951 /* ack any pending periodic timer interrupts so we don't get an immediate interrupt */
1952 /* TODO: need to also ack other unused periodic timer values, get from nesadapter */
1953 nes_write32(nesdev->regs+NES_TIMER_STAT,
1954 nesdev->timer_int_req | ~(nesdev->nesadapter->timer_int_req));
1955 nes_write32(nesdev->regs+NES_INTF_INT_MASK,
1956 ~(nesdev->intf_int_req | NES_INTF_PERIODIC_TIMER));
1957 }
1958
1959 if (unlikely(nesadapter->et_use_adaptive_rx_coalesce))
1960 {
1961 nes_nic_init_timer(nesdev);
1962 }
1963 /* Enable interrupts, except CEQs */
1964 nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff | (~nesdev->int_req));
1965 } else {
1966 /* Enable interrupts, make sure timer is off */
1967 nesdev->int_req &= ~NES_INT_TIMER;
1968 nes_write32(nesdev->regs+NES_INTF_INT_MASK, ~(nesdev->intf_int_req));
1969 nes_write32(nesdev->regs+NES_INT_MASK, ~nesdev->int_req);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001970 }
1971 nesdev->deepcq_count = 0;
1972 return 1;
1973 } else {
1974 return 0;
1975 }
1976}
1977
Chien Tung9d156942008-09-26 15:08:10 -05001978static void process_critical_error(struct nes_device *nesdev)
1979{
1980 u32 debug_error;
1981 u32 nes_idx_debug_error_masks0 = 0;
1982 u16 error_module = 0;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001983
Chien Tung9d156942008-09-26 15:08:10 -05001984 debug_error = nes_read_indexed(nesdev, NES_IDX_DEBUG_ERROR_CONTROL_STATUS);
1985 printk(KERN_ERR PFX "Critical Error reported by device!!! 0x%02X\n",
1986 (u16)debug_error);
1987 nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_CONTROL_STATUS,
1988 0x01010000 | (debug_error & 0x0000ffff));
1989 if (crit_err_count++ > 10)
1990 nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS1, 1 << 0x17);
Chien Tunge2f5e732008-10-08 14:43:29 -07001991 error_module = (u16) (debug_error & 0x1F00) >> 8;
Chien Tung9d156942008-09-26 15:08:10 -05001992 if (++nesdev->nesadapter->crit_error_count[error_module-1] >=
1993 nes_max_critical_error_count) {
1994 printk(KERN_ERR PFX "Masking off critical error for module "
1995 "0x%02X\n", (u16)error_module);
1996 nes_idx_debug_error_masks0 = nes_read_indexed(nesdev,
1997 NES_IDX_DEBUG_ERROR_MASKS0);
1998 nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS0,
1999 nes_idx_debug_error_masks0 | (1 << error_module));
2000 }
2001}
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002002/**
2003 * nes_dpc
2004 */
2005void nes_dpc(unsigned long param)
2006{
2007 struct nes_device *nesdev = (struct nes_device *)param;
2008 struct nes_adapter *nesadapter = nesdev->nesadapter;
2009 u32 counter;
2010 u32 loop_counter = 0;
2011 u32 int_status_bit;
2012 u32 int_stat;
2013 u32 timer_stat;
2014 u32 temp_int_stat;
2015 u32 intf_int_stat;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002016 u32 processed_intf_int = 0;
2017 u16 processed_timer_int = 0;
2018 u16 completion_ints = 0;
2019 u16 timer_ints = 0;
2020
2021 /* nes_debug(NES_DBG_ISR, "\n"); */
2022
2023 do {
2024 timer_stat = 0;
2025 if (nesdev->napi_isr_ran) {
2026 nesdev->napi_isr_ran = 0;
2027 int_stat = nesdev->int_stat;
2028 } else
2029 int_stat = nes_read32(nesdev->regs+NES_INT_STAT);
2030 if (processed_intf_int != 0)
2031 int_stat &= nesdev->int_req & ~NES_INT_INTF;
2032 else
2033 int_stat &= nesdev->int_req;
2034 if (processed_timer_int == 0) {
2035 processed_timer_int = 1;
2036 if (int_stat & NES_INT_TIMER) {
2037 timer_stat = nes_read32(nesdev->regs + NES_TIMER_STAT);
2038 if ((timer_stat & nesdev->timer_int_req) == 0) {
2039 int_stat &= ~NES_INT_TIMER;
2040 }
2041 }
2042 } else {
2043 int_stat &= ~NES_INT_TIMER;
2044 }
2045
2046 if (int_stat) {
Glenn Streiff7495ab62008-04-29 13:46:54 -07002047 if (int_stat & ~(NES_INT_INTF | NES_INT_TIMER | NES_INT_MAC0|
2048 NES_INT_MAC1|NES_INT_MAC2 | NES_INT_MAC3)) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002049 /* Ack the interrupts */
2050 nes_write32(nesdev->regs+NES_INT_STAT,
Glenn Streiff7495ab62008-04-29 13:46:54 -07002051 (int_stat & ~(NES_INT_INTF | NES_INT_TIMER | NES_INT_MAC0|
2052 NES_INT_MAC1 | NES_INT_MAC2 | NES_INT_MAC3)));
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002053 }
2054
2055 temp_int_stat = int_stat;
2056 for (counter = 0, int_status_bit = 1; counter < 16; counter++) {
2057 if (int_stat & int_status_bit) {
2058 nes_process_ceq(nesdev, &nesadapter->ceq[counter]);
2059 temp_int_stat &= ~int_status_bit;
2060 completion_ints = 1;
2061 }
2062 if (!(temp_int_stat & 0x0000ffff))
2063 break;
2064 int_status_bit <<= 1;
2065 }
2066
2067 /* Process the AEQ for this pci function */
2068 int_status_bit = 1 << (16 + PCI_FUNC(nesdev->pcidev->devfn));
2069 if (int_stat & int_status_bit) {
2070 nes_process_aeq(nesdev, &nesadapter->aeq[PCI_FUNC(nesdev->pcidev->devfn)]);
2071 }
2072
2073 /* Process the MAC interrupt for this pci function */
2074 int_status_bit = 1 << (24 + nesdev->mac_index);
2075 if (int_stat & int_status_bit) {
2076 nes_process_mac_intr(nesdev, nesdev->mac_index);
2077 }
2078
2079 if (int_stat & NES_INT_TIMER) {
2080 if (timer_stat & nesdev->timer_int_req) {
2081 nes_write32(nesdev->regs + NES_TIMER_STAT,
2082 (timer_stat & nesdev->timer_int_req) |
2083 ~(nesdev->nesadapter->timer_int_req));
2084 timer_ints = 1;
2085 }
2086 }
2087
2088 if (int_stat & NES_INT_INTF) {
2089 processed_intf_int = 1;
2090 intf_int_stat = nes_read32(nesdev->regs+NES_INTF_INT_STAT);
2091 intf_int_stat &= nesdev->intf_int_req;
2092 if (NES_INTF_INT_CRITERR & intf_int_stat) {
Chien Tung9d156942008-09-26 15:08:10 -05002093 process_critical_error(nesdev);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002094 }
2095 if (NES_INTF_INT_PCIERR & intf_int_stat) {
2096 printk(KERN_ERR PFX "PCI Error reported by device!!!\n");
2097 BUG();
2098 }
2099 if (NES_INTF_INT_AEQ_OFLOW & intf_int_stat) {
2100 printk(KERN_ERR PFX "AEQ Overflow reported by device!!!\n");
2101 BUG();
2102 }
2103 nes_write32(nesdev->regs+NES_INTF_INT_STAT, intf_int_stat);
2104 }
2105
2106 if (int_stat & NES_INT_TSW) {
2107 }
2108 }
2109 /* Don't use the interface interrupt bit stay in loop */
Glenn Streiff7495ab62008-04-29 13:46:54 -07002110 int_stat &= ~NES_INT_INTF | NES_INT_TIMER | NES_INT_MAC0 |
2111 NES_INT_MAC1 | NES_INT_MAC2 | NES_INT_MAC3;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002112 } while ((int_stat != 0) && (loop_counter++ < MAX_DPC_ITERATIONS));
2113
2114 if (timer_ints == 1) {
2115 if ((nesadapter->et_rx_coalesce_usecs_irq) || (nesadapter->et_use_adaptive_rx_coalesce)) {
2116 if (completion_ints == 0) {
2117 nesdev->timer_only_int_count++;
2118 if (nesdev->timer_only_int_count>=nesadapter->timer_int_limit) {
2119 nesdev->timer_only_int_count = 0;
2120 nesdev->int_req &= ~NES_INT_TIMER;
2121 nes_write32(nesdev->regs + NES_INTF_INT_MASK, ~(nesdev->intf_int_req));
Glenn Streiff7495ab62008-04-29 13:46:54 -07002122 nes_write32(nesdev->regs + NES_INT_MASK, ~nesdev->int_req);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002123 } else {
Glenn Streiff7495ab62008-04-29 13:46:54 -07002124 nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff | (~nesdev->int_req));
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002125 }
2126 } else {
2127 if (unlikely(nesadapter->et_use_adaptive_rx_coalesce))
2128 {
2129 nes_nic_init_timer(nesdev);
2130 }
2131 nesdev->timer_only_int_count = 0;
Glenn Streiff7495ab62008-04-29 13:46:54 -07002132 nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff | (~nesdev->int_req));
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002133 }
2134 } else {
2135 nesdev->timer_only_int_count = 0;
2136 nesdev->int_req &= ~NES_INT_TIMER;
2137 nes_write32(nesdev->regs+NES_INTF_INT_MASK, ~(nesdev->intf_int_req));
2138 nes_write32(nesdev->regs+NES_TIMER_STAT,
2139 nesdev->timer_int_req | ~(nesdev->nesadapter->timer_int_req));
2140 nes_write32(nesdev->regs+NES_INT_MASK, ~nesdev->int_req);
2141 }
2142 } else {
2143 if ( (completion_ints == 1) &&
2144 (((nesadapter->et_rx_coalesce_usecs_irq) &&
2145 (!nesadapter->et_use_adaptive_rx_coalesce)) ||
2146 ((nesdev->deepcq_count > nesadapter->et_pkt_rate_low) &&
2147 (nesadapter->et_use_adaptive_rx_coalesce) )) ) {
2148 /* nes_debug(NES_DBG_ISR, "Enabling periodic timer interrupt.\n" ); */
2149 nesdev->timer_only_int_count = 0;
2150 nesdev->int_req |= NES_INT_TIMER;
2151 nes_write32(nesdev->regs+NES_TIMER_STAT,
2152 nesdev->timer_int_req | ~(nesdev->nesadapter->timer_int_req));
2153 nes_write32(nesdev->regs+NES_INTF_INT_MASK,
2154 ~(nesdev->intf_int_req | NES_INTF_PERIODIC_TIMER));
2155 nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff | (~nesdev->int_req));
2156 } else {
2157 nes_write32(nesdev->regs+NES_INT_MASK, ~nesdev->int_req);
2158 }
2159 }
2160 nesdev->deepcq_count = 0;
2161}
2162
2163
2164/**
2165 * nes_process_ceq
2166 */
Roland Dreier1a855fbf2008-04-16 21:01:09 -07002167static void nes_process_ceq(struct nes_device *nesdev, struct nes_hw_ceq *ceq)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002168{
2169 u64 u64temp;
2170 struct nes_hw_cq *cq;
2171 u32 head;
2172 u32 ceq_size;
2173
2174 /* nes_debug(NES_DBG_CQ, "\n"); */
2175 head = ceq->ceq_head;
2176 ceq_size = ceq->ceq_size;
2177
2178 do {
2179 if (le32_to_cpu(ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_HIGH_IDX]) &
2180 NES_CEQE_VALID) {
Glenn Streiff7495ab62008-04-29 13:46:54 -07002181 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 -08002182 ((u64)(le32_to_cpu(ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_LOW_IDX])));
2183 u64temp <<= 1;
2184 cq = *((struct nes_hw_cq **)&u64temp);
2185 /* nes_debug(NES_DBG_CQ, "pCQ = %p\n", cq); */
2186 barrier();
2187 ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_HIGH_IDX] = 0;
2188
2189 /* call the event handler */
2190 cq->ce_handler(nesdev, cq);
2191
2192 if (++head >= ceq_size)
2193 head = 0;
2194 } else {
2195 break;
2196 }
2197
2198 } while (1);
2199
2200 ceq->ceq_head = head;
2201}
2202
2203
2204/**
2205 * nes_process_aeq
2206 */
Roland Dreier1a855fbf2008-04-16 21:01:09 -07002207static void nes_process_aeq(struct nes_device *nesdev, struct nes_hw_aeq *aeq)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002208{
Glenn Streiff7495ab62008-04-29 13:46:54 -07002209 /* u64 u64temp; */
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002210 u32 head;
2211 u32 aeq_size;
2212 u32 aeqe_misc;
2213 u32 aeqe_cq_id;
2214 struct nes_hw_aeqe volatile *aeqe;
2215
2216 head = aeq->aeq_head;
2217 aeq_size = aeq->aeq_size;
2218
2219 do {
2220 aeqe = &aeq->aeq_vbase[head];
2221 if ((le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]) & NES_AEQE_VALID) == 0)
2222 break;
2223 aeqe_misc = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]);
2224 aeqe_cq_id = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]);
2225 if (aeqe_misc & (NES_AEQE_QP|NES_AEQE_CQ)) {
2226 if (aeqe_cq_id >= NES_FIRST_QPN) {
2227 /* dealing with an accelerated QP related AE */
Glenn Streiff7495ab62008-04-29 13:46:54 -07002228 /*
2229 * u64temp = (((u64)(le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX]))) << 32) |
2230 * ((u64)(le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX])));
2231 */
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002232 nes_process_iwarp_aeqe(nesdev, (struct nes_hw_aeqe *)aeqe);
2233 } else {
2234 /* TODO: dealing with a CQP related AE */
2235 nes_debug(NES_DBG_AEQ, "Processing CQP related AE, misc = 0x%04X\n",
2236 (u16)(aeqe_misc >> 16));
2237 }
2238 }
2239
2240 aeqe->aeqe_words[NES_AEQE_MISC_IDX] = 0;
2241
2242 if (++head >= aeq_size)
2243 head = 0;
Don Woodfd877782009-03-06 15:12:11 -08002244
2245 nes_write32(nesdev->regs + NES_AEQ_ALLOC, 1 << 16);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002246 }
2247 while (1);
2248 aeq->aeq_head = head;
2249}
2250
2251static void nes_reset_link(struct nes_device *nesdev, u32 mac_index)
2252{
2253 struct nes_adapter *nesadapter = nesdev->nesadapter;
2254 u32 reset_value;
2255 u32 i=0;
2256 u32 u32temp;
2257
2258 if (nesadapter->hw_rev == NE020_REV) {
2259 return;
2260 }
2261 mh_detected++;
2262
2263 reset_value = nes_read32(nesdev->regs+NES_SOFTWARE_RESET);
2264
2265 if ((mac_index == 0) || ((mac_index == 1) && (nesadapter->OneG_Mode)))
2266 reset_value |= 0x0000001d;
2267 else
2268 reset_value |= 0x0000002d;
2269
2270 if (4 <= (nesadapter->link_interrupt_count[mac_index] / ((u16)NES_MAX_LINK_INTERRUPTS))) {
2271 if ((!nesadapter->OneG_Mode) && (nesadapter->port_count == 2)) {
2272 nesadapter->link_interrupt_count[0] = 0;
2273 nesadapter->link_interrupt_count[1] = 0;
2274 u32temp = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1);
2275 if (0x00000040 & u32temp)
2276 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F088);
2277 else
2278 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F0C8);
2279
2280 reset_value |= 0x0000003d;
2281 }
2282 nesadapter->link_interrupt_count[mac_index] = 0;
2283 }
2284
2285 nes_write32(nesdev->regs+NES_SOFTWARE_RESET, reset_value);
2286
2287 while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET)
2288 & 0x00000040) != 0x00000040) && (i++ < 5000));
2289
2290 if (0x0000003d == (reset_value & 0x0000003d)) {
2291 u32 pcs_control_status0, pcs_control_status1;
2292
2293 for (i = 0; i < 10; i++) {
2294 pcs_control_status0 = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0);
2295 pcs_control_status1 = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200);
2296 if (((0x0F000000 == (pcs_control_status0 & 0x0F000000))
2297 && (pcs_control_status0 & 0x00100000))
2298 || ((0x0F000000 == (pcs_control_status1 & 0x0F000000))
2299 && (pcs_control_status1 & 0x00100000)))
2300 continue;
2301 else
2302 break;
2303 }
2304 if (10 == i) {
2305 u32temp = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1);
2306 if (0x00000040 & u32temp)
2307 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F088);
2308 else
2309 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F0C8);
2310
2311 nes_write32(nesdev->regs+NES_SOFTWARE_RESET, reset_value);
2312
2313 while (((nes_read32(nesdev->regs + NES_SOFTWARE_RESET)
2314 & 0x00000040) != 0x00000040) && (i++ < 5000));
2315 }
2316 }
2317}
2318
2319/**
2320 * nes_process_mac_intr
2321 */
Roland Dreier1a855fbf2008-04-16 21:01:09 -07002322static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002323{
2324 unsigned long flags;
2325 u32 pcs_control_status;
2326 struct nes_adapter *nesadapter = nesdev->nesadapter;
2327 struct nes_vnic *nesvnic;
2328 u32 mac_status;
2329 u32 mac_index = nesdev->mac_index;
2330 u32 u32temp;
2331 u16 phy_data;
2332 u16 temp_phy_data;
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002333 u32 pcs_val = 0x0f0f0000;
2334 u32 pcs_mask = 0x0f1f0000;
Chien Tunga4849fc2009-04-08 14:27:18 -07002335 u32 cdr_ctrl;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002336
2337 spin_lock_irqsave(&nesadapter->phy_lock, flags);
2338 if (nesadapter->mac_sw_state[mac_number] != NES_MAC_SW_IDLE) {
2339 spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
2340 return;
2341 }
2342 nesadapter->mac_sw_state[mac_number] = NES_MAC_SW_INTERRUPT;
2343 spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
2344
2345 /* ack the MAC interrupt */
2346 mac_status = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (mac_index * 0x200));
2347 /* Clear the interrupt */
2348 nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (mac_index * 0x200), mac_status);
2349
2350 nes_debug(NES_DBG_PHY, "MAC%u interrupt status = 0x%X.\n", mac_number, mac_status);
2351
2352 if (mac_status & (NES_MAC_INT_LINK_STAT_CHG | NES_MAC_INT_XGMII_EXT)) {
2353 nesdev->link_status_interrupts++;
2354 if (0 == (++nesadapter->link_interrupt_count[mac_index] % ((u16)NES_MAX_LINK_INTERRUPTS))) {
2355 spin_lock_irqsave(&nesadapter->phy_lock, flags);
2356 nes_reset_link(nesdev, mac_index);
2357 spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
2358 }
2359 /* read the PHY interrupt status register */
Chien Tungfcb7ad32008-09-30 14:49:44 -07002360 if ((nesadapter->OneG_Mode) &&
2361 (nesadapter->phy_type[mac_index] != NES_PHY_TYPE_PUMA_1G)) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002362 do {
2363 nes_read_1G_phy_reg(nesdev, 0x1a,
2364 nesadapter->phy_index[mac_index], &phy_data);
2365 nes_debug(NES_DBG_PHY, "Phy%d data from register 0x1a = 0x%X.\n",
2366 nesadapter->phy_index[mac_index], phy_data);
2367 } while (phy_data&0x8000);
2368
2369 temp_phy_data = 0;
2370 do {
2371 nes_read_1G_phy_reg(nesdev, 0x11,
2372 nesadapter->phy_index[mac_index], &phy_data);
2373 nes_debug(NES_DBG_PHY, "Phy%d data from register 0x11 = 0x%X.\n",
2374 nesadapter->phy_index[mac_index], phy_data);
2375 if (temp_phy_data == phy_data)
2376 break;
2377 temp_phy_data = phy_data;
2378 } while (1);
2379
2380 nes_read_1G_phy_reg(nesdev, 0x1e,
2381 nesadapter->phy_index[mac_index], &phy_data);
2382 nes_debug(NES_DBG_PHY, "Phy%d data from register 0x1e = 0x%X.\n",
2383 nesadapter->phy_index[mac_index], phy_data);
2384
2385 nes_read_1G_phy_reg(nesdev, 1,
2386 nesadapter->phy_index[mac_index], &phy_data);
2387 nes_debug(NES_DBG_PHY, "1G phy%u data from register 1 = 0x%X\n",
2388 nesadapter->phy_index[mac_index], phy_data);
2389
2390 if (temp_phy_data & 0x1000) {
2391 nes_debug(NES_DBG_PHY, "The Link is up according to the PHY\n");
2392 phy_data = 4;
2393 } else {
2394 nes_debug(NES_DBG_PHY, "The Link is down according to the PHY\n");
2395 }
2396 }
2397 nes_debug(NES_DBG_PHY, "Eth SERDES Common Status: 0=0x%08X, 1=0x%08X\n",
2398 nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0),
2399 nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0+0x200));
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002400
2401 if (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_PUMA_1G) {
2402 switch (mac_index) {
2403 case 1:
2404 case 3:
2405 pcs_control_status = nes_read_indexed(nesdev,
2406 NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200);
2407 break;
2408 default:
2409 pcs_control_status = nes_read_indexed(nesdev,
2410 NES_IDX_PHY_PCS_CONTROL_STATUS0);
2411 break;
2412 }
2413 } else {
2414 pcs_control_status = nes_read_indexed(nesdev,
2415 NES_IDX_PHY_PCS_CONTROL_STATUS0 + ((mac_index & 1) * 0x200));
2416 pcs_control_status = nes_read_indexed(nesdev,
2417 NES_IDX_PHY_PCS_CONTROL_STATUS0 + ((mac_index & 1) * 0x200));
2418 }
2419
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002420 nes_debug(NES_DBG_PHY, "PCS PHY Control/Status%u: 0x%08X\n",
2421 mac_index, pcs_control_status);
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002422 if ((nesadapter->OneG_Mode) &&
2423 (nesadapter->phy_type[mac_index] != NES_PHY_TYPE_PUMA_1G)) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002424 u32temp = 0x01010000;
2425 if (nesadapter->port_count > 2) {
2426 u32temp |= 0x02020000;
2427 }
2428 if ((pcs_control_status & u32temp)!= u32temp) {
2429 phy_data = 0;
2430 nes_debug(NES_DBG_PHY, "PCS says the link is down\n");
2431 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002432 } else {
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002433 switch (nesadapter->phy_type[mac_index]) {
2434 case NES_PHY_TYPE_IRIS:
2435 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 1);
2436 temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
2437 u32temp = 20;
2438 do {
2439 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 1);
2440 phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
2441 if ((phy_data == temp_phy_data) || (!(--u32temp)))
2442 break;
2443 temp_phy_data = phy_data;
2444 } while (1);
2445 nes_debug(NES_DBG_PHY, "%s: Phy data = 0x%04X, link was %s.\n",
2446 __func__, phy_data, nesadapter->mac_link_down[mac_index] ? "DOWN" : "UP");
2447 break;
2448
2449 case NES_PHY_TYPE_ARGUS:
Chien Tung43035652009-04-08 14:27:56 -07002450 case NES_PHY_TYPE_SFP_D:
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002451 /* clear the alarms */
2452 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0x0008);
2453 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0xc001);
2454 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0xc002);
2455 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0xc005);
2456 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0xc006);
2457 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9003);
2458 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9004);
2459 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9005);
2460 /* check link status */
Chien Tung1b949322009-04-08 14:27:09 -07002461 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9003);
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002462 temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002463
Chien Tung1b949322009-04-08 14:27:09 -07002464 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 3, 0x0021);
2465 nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
2466 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 3, 0x0021);
2467 phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
2468
2469 phy_data = (!temp_phy_data && (phy_data == 0x8000)) ? 0x4 : 0x0;
2470
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002471 nes_debug(NES_DBG_PHY, "%s: Phy data = 0x%04X, link was %s.\n",
Chien Tung1b949322009-04-08 14:27:09 -07002472 __func__, phy_data, nesadapter->mac_link_down[mac_index] ? "DOWN" : "UP");
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002473 break;
2474
2475 case NES_PHY_TYPE_PUMA_1G:
2476 if (mac_index < 2)
2477 pcs_val = pcs_mask = 0x01010000;
2478 else
2479 pcs_val = pcs_mask = 0x02020000;
2480 /* fall through */
2481 default:
2482 phy_data = (pcs_val == (pcs_control_status & pcs_mask)) ? 0x4 : 0x0;
2483 break;
2484 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002485 }
2486
2487 if (phy_data & 0x0004) {
Chien Tunga4849fc2009-04-08 14:27:18 -07002488 if (wide_ppm_offset &&
2489 (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_CX4) &&
2490 (nesadapter->hw_rev != NE020_REV)) {
2491 cdr_ctrl = nes_read_indexed(nesdev,
2492 NES_IDX_ETH_SERDES_CDR_CONTROL0 +
2493 mac_index * 0x200);
2494 nes_write_indexed(nesdev,
2495 NES_IDX_ETH_SERDES_CDR_CONTROL0 +
2496 mac_index * 0x200,
2497 cdr_ctrl | 0x000F0000);
2498 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002499 nesadapter->mac_link_down[mac_index] = 0;
2500 list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) {
2501 nes_debug(NES_DBG_PHY, "The Link is UP!!. linkup was %d\n",
2502 nesvnic->linkup);
2503 if (nesvnic->linkup == 0) {
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002504 printk(PFX "The Link is now up for port %s, netdev %p.\n",
2505 nesvnic->netdev->name, nesvnic->netdev);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002506 if (netif_queue_stopped(nesvnic->netdev))
2507 netif_start_queue(nesvnic->netdev);
2508 nesvnic->linkup = 1;
2509 netif_carrier_on(nesvnic->netdev);
2510 }
2511 }
2512 } else {
Chien Tunga4849fc2009-04-08 14:27:18 -07002513 if (wide_ppm_offset &&
2514 (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_CX4) &&
2515 (nesadapter->hw_rev != NE020_REV)) {
2516 cdr_ctrl = nes_read_indexed(nesdev,
2517 NES_IDX_ETH_SERDES_CDR_CONTROL0 +
2518 mac_index * 0x200);
2519 nes_write_indexed(nesdev,
2520 NES_IDX_ETH_SERDES_CDR_CONTROL0 +
2521 mac_index * 0x200,
2522 cdr_ctrl & 0xFFF0FFFF);
2523 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002524 nesadapter->mac_link_down[mac_index] = 1;
2525 list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) {
2526 nes_debug(NES_DBG_PHY, "The Link is Down!!. linkup was %d\n",
2527 nesvnic->linkup);
2528 if (nesvnic->linkup == 1) {
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002529 printk(PFX "The Link is now down for port %s, netdev %p.\n",
2530 nesvnic->netdev->name, nesvnic->netdev);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002531 if (!(netif_queue_stopped(nesvnic->netdev)))
2532 netif_stop_queue(nesvnic->netdev);
2533 nesvnic->linkup = 0;
2534 netif_carrier_off(nesvnic->netdev);
2535 }
2536 }
2537 }
2538 }
2539
2540 nesadapter->mac_sw_state[mac_number] = NES_MAC_SW_IDLE;
2541}
2542
2543
2544
Roland Dreier1a855fbf2008-04-16 21:01:09 -07002545static void nes_nic_napi_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002546{
2547 struct nes_vnic *nesvnic = container_of(cq, struct nes_vnic, nic_cq);
2548
Ben Hutchings288379f2009-01-19 16:43:59 -08002549 napi_schedule(&nesvnic->napi);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002550}
2551
2552
2553/* The MAX_RQES_TO_PROCESS defines how many max read requests to complete before
2554* getting out of nic_ce_handler
2555*/
2556#define MAX_RQES_TO_PROCESS 384
2557
2558/**
2559 * nes_nic_ce_handler
2560 */
2561void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
2562{
2563 u64 u64temp;
2564 dma_addr_t bus_address;
2565 struct nes_hw_nic *nesnic;
2566 struct nes_vnic *nesvnic = container_of(cq, struct nes_vnic, nic_cq);
2567 struct nes_adapter *nesadapter = nesdev->nesadapter;
2568 struct nes_hw_nic_rq_wqe *nic_rqe;
2569 struct nes_hw_nic_sq_wqe *nic_sqe;
2570 struct sk_buff *skb;
2571 struct sk_buff *rx_skb;
2572 __le16 *wqe_fragment_length;
2573 u32 head;
2574 u32 cq_size;
2575 u32 rx_pkt_size;
2576 u32 cqe_count=0;
2577 u32 cqe_errv;
2578 u32 cqe_misc;
2579 u16 wqe_fragment_index = 1; /* first fragment (0) is used by copy buffer */
2580 u16 vlan_tag;
2581 u16 pkt_type;
2582 u16 rqes_processed = 0;
2583 u8 sq_cqes = 0;
Faisal Latif37dab412008-04-29 13:46:54 -07002584 u8 nes_use_lro = 0;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002585
2586 head = cq->cq_head;
2587 cq_size = cq->cq_size;
2588 cq->cqes_pending = 1;
Faisal Latif37dab412008-04-29 13:46:54 -07002589 if (nesvnic->netdev->features & NETIF_F_LRO)
2590 nes_use_lro = 1;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002591 do {
2592 if (le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX]) &
2593 NES_NIC_CQE_VALID) {
2594 nesnic = &nesvnic->nic;
2595 cqe_misc = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX]);
2596 if (cqe_misc & NES_NIC_CQE_SQ) {
2597 sq_cqes++;
2598 wqe_fragment_index = 1;
2599 nic_sqe = &nesnic->sq_vbase[nesnic->sq_tail];
2600 skb = nesnic->tx_skb[nesnic->sq_tail];
2601 wqe_fragment_length = (__le16 *)&nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX];
2602 /* bump past the vlan tag */
2603 wqe_fragment_length++;
2604 if (le16_to_cpu(wqe_fragment_length[wqe_fragment_index]) != 0) {
Glenn Streiff7495ab62008-04-29 13:46:54 -07002605 u64temp = (u64) le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX +
2606 wqe_fragment_index * 2]);
2607 u64temp += ((u64)le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX +
2608 wqe_fragment_index * 2])) << 32;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002609 bus_address = (dma_addr_t)u64temp;
2610 if (test_and_clear_bit(nesnic->sq_tail, nesnic->first_frag_overflow)) {
2611 pci_unmap_single(nesdev->pcidev,
2612 bus_address,
2613 le16_to_cpu(wqe_fragment_length[wqe_fragment_index++]),
2614 PCI_DMA_TODEVICE);
2615 }
2616 for (; wqe_fragment_index < 5; wqe_fragment_index++) {
2617 if (wqe_fragment_length[wqe_fragment_index]) {
Glenn Streiff7495ab62008-04-29 13:46:54 -07002618 u64temp = le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX +
2619 wqe_fragment_index * 2]);
2620 u64temp += ((u64)le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX
2621 + wqe_fragment_index * 2])) <<32;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002622 bus_address = (dma_addr_t)u64temp;
2623 pci_unmap_page(nesdev->pcidev,
2624 bus_address,
2625 le16_to_cpu(wqe_fragment_length[wqe_fragment_index]),
2626 PCI_DMA_TODEVICE);
2627 } else
2628 break;
2629 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002630 }
Faisal Latif28699752009-03-06 15:12:11 -08002631 if (skb)
2632 dev_kfree_skb_any(skb);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002633 nesnic->sq_tail++;
2634 nesnic->sq_tail &= nesnic->sq_size-1;
2635 if (sq_cqes > 128) {
2636 barrier();
2637 /* restart the queue if it had been stopped */
2638 if (netif_queue_stopped(nesvnic->netdev))
2639 netif_wake_queue(nesvnic->netdev);
2640 sq_cqes = 0;
2641 }
2642 } else {
2643 rqes_processed ++;
2644
2645 cq->rx_cqes_completed++;
2646 cq->rx_pkts_indicated++;
2647 rx_pkt_size = cqe_misc & 0x0000ffff;
2648 nic_rqe = &nesnic->rq_vbase[nesnic->rq_tail];
2649 /* Get the skb */
2650 rx_skb = nesnic->rx_skb[nesnic->rq_tail];
2651 nic_rqe = &nesnic->rq_vbase[nesvnic->nic.rq_tail];
2652 bus_address = (dma_addr_t)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]);
2653 bus_address += ((u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX])) << 32;
2654 pci_unmap_single(nesdev->pcidev, bus_address,
2655 nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
2656 /* rx_skb->tail = rx_skb->data + rx_pkt_size; */
2657 /* rx_skb->len = rx_pkt_size; */
2658 rx_skb->len = 0; /* TODO: see if this is necessary */
2659 skb_put(rx_skb, rx_pkt_size);
2660 rx_skb->protocol = eth_type_trans(rx_skb, nesvnic->netdev);
2661 nesnic->rq_tail++;
2662 nesnic->rq_tail &= nesnic->rq_size - 1;
2663
2664 atomic_inc(&nesvnic->rx_skbs_needed);
2665 if (atomic_read(&nesvnic->rx_skbs_needed) > (nesvnic->nic.rq_size>>1)) {
2666 nes_write32(nesdev->regs+NES_CQE_ALLOC,
2667 cq->cq_number | (cqe_count << 16));
Glenn Streiff7495ab62008-04-29 13:46:54 -07002668 /* nesadapter->tune_timer.cq_count += cqe_count; */
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002669 nesdev->currcq_count += cqe_count;
2670 cqe_count = 0;
2671 nes_replenish_nic_rq(nesvnic);
2672 }
2673 pkt_type = (u16)(le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_TAG_PKT_TYPE_IDX]));
2674 cqe_errv = (cqe_misc & NES_NIC_CQE_ERRV_MASK) >> NES_NIC_CQE_ERRV_SHIFT;
2675 rx_skb->ip_summed = CHECKSUM_NONE;
2676
2677 if ((NES_PKT_TYPE_TCPV4_BITS == (pkt_type & NES_PKT_TYPE_TCPV4_MASK)) ||
2678 (NES_PKT_TYPE_UDPV4_BITS == (pkt_type & NES_PKT_TYPE_UDPV4_MASK))) {
2679 if ((cqe_errv &
2680 (NES_NIC_ERRV_BITS_IPV4_CSUM_ERR | NES_NIC_ERRV_BITS_TCPUDP_CSUM_ERR |
2681 NES_NIC_ERRV_BITS_IPH_ERR | NES_NIC_ERRV_BITS_WQE_OVERRUN)) == 0) {
2682 if (nesvnic->rx_checksum_disabled == 0) {
2683 rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
2684 }
2685 } else
2686 nes_debug(NES_DBG_CQ, "%s: unsuccessfully checksummed TCP or UDP packet."
2687 " errv = 0x%X, pkt_type = 0x%X.\n",
2688 nesvnic->netdev->name, cqe_errv, pkt_type);
2689
2690 } else if ((pkt_type & NES_PKT_TYPE_IPV4_MASK) == NES_PKT_TYPE_IPV4_BITS) {
2691 if ((cqe_errv &
2692 (NES_NIC_ERRV_BITS_IPV4_CSUM_ERR | NES_NIC_ERRV_BITS_IPH_ERR |
2693 NES_NIC_ERRV_BITS_WQE_OVERRUN)) == 0) {
2694 if (nesvnic->rx_checksum_disabled == 0) {
2695 rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
2696 /* nes_debug(NES_DBG_CQ, "%s: Reporting successfully checksummed IPv4 packet.\n",
2697 nesvnic->netdev->name); */
2698 }
2699 } else
2700 nes_debug(NES_DBG_CQ, "%s: unsuccessfully checksummed TCP or UDP packet."
2701 " errv = 0x%X, pkt_type = 0x%X.\n",
2702 nesvnic->netdev->name, cqe_errv, pkt_type);
2703 }
2704 /* nes_debug(NES_DBG_CQ, "pkt_type=%x, APBVT_MASK=%x\n",
2705 pkt_type, (pkt_type & NES_PKT_TYPE_APBVT_MASK)); */
2706
2707 if ((pkt_type & NES_PKT_TYPE_APBVT_MASK) == NES_PKT_TYPE_APBVT_BITS) {
Faisal Latif4a14f6a2008-11-21 20:50:49 -06002708 if (nes_cm_recv(rx_skb, nesvnic->netdev))
2709 rx_skb = NULL;
2710 }
2711 if (rx_skb == NULL)
2712 goto skip_rx_indicate0;
2713
2714
2715 if ((cqe_misc & NES_NIC_CQE_TAG_VALID) &&
2716 (nesvnic->vlan_grp != NULL)) {
2717 vlan_tag = (u16)(le32_to_cpu(
2718 cq->cq_vbase[head].cqe_words[NES_NIC_CQE_TAG_PKT_TYPE_IDX])
2719 >> 16);
2720 nes_debug(NES_DBG_CQ, "%s: Reporting stripped VLAN packet. Tag = 0x%04X\n",
2721 nesvnic->netdev->name, vlan_tag);
2722 if (nes_use_lro)
2723 lro_vlan_hwaccel_receive_skb(&nesvnic->lro_mgr, rx_skb,
2724 nesvnic->vlan_grp, vlan_tag, NULL);
2725 else
2726 nes_vlan_rx(rx_skb, nesvnic->vlan_grp, vlan_tag);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002727 } else {
Faisal Latif4a14f6a2008-11-21 20:50:49 -06002728 if (nes_use_lro)
2729 lro_receive_skb(&nesvnic->lro_mgr, rx_skb, NULL);
2730 else
2731 nes_netif_rx(rx_skb);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002732 }
2733
Faisal Latif4a14f6a2008-11-21 20:50:49 -06002734skip_rx_indicate0:
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002735 nesvnic->netdev->last_rx = jiffies;
2736 /* nesvnic->netstats.rx_packets++; */
2737 /* nesvnic->netstats.rx_bytes += rx_pkt_size; */
2738 }
2739
2740 cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX] = 0;
2741 /* Accounting... */
2742 cqe_count++;
2743 if (++head >= cq_size)
2744 head = 0;
2745 if (cqe_count == 255) {
2746 /* Replenish Nic CQ */
2747 nes_write32(nesdev->regs+NES_CQE_ALLOC,
2748 cq->cq_number | (cqe_count << 16));
Glenn Streiff7495ab62008-04-29 13:46:54 -07002749 /* nesdev->nesadapter->tune_timer.cq_count += cqe_count; */
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002750 nesdev->currcq_count += cqe_count;
2751 cqe_count = 0;
2752 }
2753
2754 if (cq->rx_cqes_completed >= nesvnic->budget)
2755 break;
2756 } else {
2757 cq->cqes_pending = 0;
2758 break;
2759 }
2760
2761 } while (1);
2762
Faisal Latif37dab412008-04-29 13:46:54 -07002763 if (nes_use_lro)
2764 lro_flush_all(&nesvnic->lro_mgr);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002765 if (sq_cqes) {
2766 barrier();
2767 /* restart the queue if it had been stopped */
2768 if (netif_queue_stopped(nesvnic->netdev))
2769 netif_wake_queue(nesvnic->netdev);
2770 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002771 cq->cq_head = head;
2772 /* nes_debug(NES_DBG_CQ, "CQ%u Processed = %u cqes, new head = %u.\n",
2773 cq->cq_number, cqe_count, cq->cq_head); */
2774 cq->cqe_allocs_pending = cqe_count;
2775 if (unlikely(nesadapter->et_use_adaptive_rx_coalesce))
2776 {
Glenn Streiff7495ab62008-04-29 13:46:54 -07002777 /* nesdev->nesadapter->tune_timer.cq_count += cqe_count; */
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002778 nesdev->currcq_count += cqe_count;
2779 nes_nic_tune_timer(nesdev);
2780 }
2781 if (atomic_read(&nesvnic->rx_skbs_needed))
2782 nes_replenish_nic_rq(nesvnic);
Faisal Latif37dab412008-04-29 13:46:54 -07002783}
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002784
2785
2786/**
2787 * nes_cqp_ce_handler
2788 */
Roland Dreier1a855fbf2008-04-16 21:01:09 -07002789static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002790{
2791 u64 u64temp;
2792 unsigned long flags;
2793 struct nes_hw_cqp *cqp = NULL;
2794 struct nes_cqp_request *cqp_request;
2795 struct nes_hw_cqp_wqe *cqp_wqe;
2796 u32 head;
2797 u32 cq_size;
2798 u32 cqe_count=0;
2799 u32 error_code;
2800 /* u32 counter; */
2801
2802 head = cq->cq_head;
2803 cq_size = cq->cq_size;
2804
2805 do {
2806 /* process the CQE */
2807 /* nes_debug(NES_DBG_CQP, "head=%u cqe_words=%08X\n", head,
2808 le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX])); */
2809
2810 if (le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_VALID) {
2811 u64temp = (((u64)(le32_to_cpu(cq->cq_vbase[head].
Glenn Streiff7495ab62008-04-29 13:46:54 -07002812 cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX]))) << 32) |
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002813 ((u64)(le32_to_cpu(cq->cq_vbase[head].
2814 cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX])));
2815 cqp = *((struct nes_hw_cqp **)&u64temp);
2816
2817 error_code = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_ERROR_CODE_IDX]);
2818 if (error_code) {
2819 nes_debug(NES_DBG_CQP, "Bad Completion code for opcode 0x%02X from CQP,"
2820 " Major/Minor codes = 0x%04X:%04X.\n",
2821 le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX])&0x3f,
2822 (u16)(error_code >> 16),
2823 (u16)error_code);
2824 nes_debug(NES_DBG_CQP, "cqp: qp_id=%u, sq_head=%u, sq_tail=%u\n",
2825 cqp->qp_id, cqp->sq_head, cqp->sq_tail);
2826 }
2827
2828 u64temp = (((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail].
Glenn Streiff7495ab62008-04-29 13:46:54 -07002829 wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX]))) << 32) |
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002830 ((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail].
2831 wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX])));
2832 cqp_request = *((struct nes_cqp_request **)&u64temp);
2833 if (cqp_request) {
2834 if (cqp_request->waiting) {
2835 /* nes_debug(NES_DBG_CQP, "%s: Waking up requestor\n"); */
2836 cqp_request->major_code = (u16)(error_code >> 16);
2837 cqp_request->minor_code = (u16)error_code;
2838 barrier();
2839 cqp_request->request_done = 1;
2840 wake_up(&cqp_request->waitq);
Roland Dreier1ff66e82008-07-14 23:48:49 -07002841 nes_put_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002842 } else {
Roland Dreier1ff66e82008-07-14 23:48:49 -07002843 if (cqp_request->callback)
2844 cqp_request->cqp_callback(nesdev, cqp_request);
2845 nes_free_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002846 }
2847 } else {
2848 wake_up(&nesdev->cqp.waitq);
2849 }
2850
2851 cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX] = 0;
Glenn Streiff7495ab62008-04-29 13:46:54 -07002852 nes_write32(nesdev->regs + NES_CQE_ALLOC, cq->cq_number | (1 << 16));
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002853 if (++cqp->sq_tail >= cqp->sq_size)
2854 cqp->sq_tail = 0;
2855
2856 /* Accounting... */
2857 cqe_count++;
2858 if (++head >= cq_size)
2859 head = 0;
2860 } else {
2861 break;
2862 }
2863 } while (1);
2864 cq->cq_head = head;
2865
2866 spin_lock_irqsave(&nesdev->cqp.lock, flags);
2867 while ((!list_empty(&nesdev->cqp_pending_reqs)) &&
2868 ((((nesdev->cqp.sq_tail+nesdev->cqp.sq_size)-nesdev->cqp.sq_head) &
2869 (nesdev->cqp.sq_size - 1)) != 1)) {
2870 cqp_request = list_entry(nesdev->cqp_pending_reqs.next,
2871 struct nes_cqp_request, list);
2872 list_del_init(&cqp_request->list);
2873 head = nesdev->cqp.sq_head++;
2874 nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
2875 cqp_wqe = &nesdev->cqp.sq_vbase[head];
2876 memcpy(cqp_wqe, &cqp_request->cqp_wqe, sizeof(*cqp_wqe));
2877 barrier();
2878 cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] =
2879 cpu_to_le32((u32)((unsigned long)cqp_request));
2880 cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] =
2881 cpu_to_le32((u32)(upper_32_bits((unsigned long)cqp_request)));
2882 nes_debug(NES_DBG_CQP, "CQP request %p (opcode 0x%02X) put on CQPs SQ wqe%u.\n",
2883 cqp_request, le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f, head);
2884 /* Ring doorbell (1 WQEs) */
2885 barrier();
2886 nes_write32(nesdev->regs+NES_WQE_ALLOC, 0x01800000 | nesdev->cqp.qp_id);
2887 }
2888 spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
2889
2890 /* Arm the CCQ */
2891 nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT |
2892 cq->cq_number);
2893 nes_read32(nesdev->regs+NES_CQE_ALLOC);
2894}
2895
2896
2897/**
2898 * nes_process_iwarp_aeqe
2899 */
Roland Dreier1a855fbf2008-04-16 21:01:09 -07002900static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
2901 struct nes_hw_aeqe *aeqe)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002902{
2903 u64 context;
2904 u64 aeqe_context = 0;
2905 unsigned long flags;
2906 struct nes_qp *nesqp;
2907 int resource_allocated;
2908 /* struct iw_cm_id *cm_id; */
2909 struct nes_adapter *nesadapter = nesdev->nesadapter;
2910 struct ib_event ibevent;
2911 /* struct iw_cm_event cm_event; */
2912 u32 aeq_info;
2913 u32 next_iwarp_state = 0;
2914 u16 async_event_id;
2915 u8 tcp_state;
2916 u8 iwarp_state;
2917
2918 nes_debug(NES_DBG_AEQ, "\n");
2919 aeq_info = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]);
2920 if ((NES_AEQE_INBOUND_RDMA&aeq_info) || (!(NES_AEQE_QP&aeq_info))) {
Glenn Streiff7495ab62008-04-29 13:46:54 -07002921 context = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX]);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002922 context += ((u64)le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX])) << 32;
2923 } else {
2924 aeqe_context = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX]);
2925 aeqe_context += ((u64)le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX])) << 32;
2926 context = (unsigned long)nesadapter->qp_table[le32_to_cpu(
Glenn Streiff7495ab62008-04-29 13:46:54 -07002927 aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]) - NES_FIRST_QPN];
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002928 BUG_ON(!context);
2929 }
2930
2931 async_event_id = (u16)aeq_info;
2932 tcp_state = (aeq_info & NES_AEQE_TCP_STATE_MASK) >> NES_AEQE_TCP_STATE_SHIFT;
2933 iwarp_state = (aeq_info & NES_AEQE_IWARP_STATE_MASK) >> NES_AEQE_IWARP_STATE_SHIFT;
2934 nes_debug(NES_DBG_AEQ, "aeid = 0x%04X, qp-cq id = %d, aeqe = %p,"
2935 " Tcp state = %s, iWARP state = %s\n",
2936 async_event_id,
2937 le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]), aeqe,
2938 nes_tcp_state_str[tcp_state], nes_iwarp_state_str[iwarp_state]);
2939
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002940 switch (async_event_id) {
2941 case NES_AEQE_AEID_LLP_FIN_RECEIVED:
2942 nesqp = *((struct nes_qp **)&context);
2943 if (atomic_inc_return(&nesqp->close_timer_started) == 1) {
2944 nesqp->cm_id->add_ref(nesqp->cm_id);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002945 schedule_nes_timer(nesqp->cm_node, (struct sk_buff *)nesqp,
2946 NES_TIMER_TYPE_CLOSE, 1, 0);
2947 nes_debug(NES_DBG_AEQ, "QP%u Not decrementing QP refcount (%d),"
2948 " need ae to finish up, original_last_aeq = 0x%04X."
2949 " last_aeq = 0x%04X, scheduling timer. TCP state = %d\n",
2950 nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),
2951 async_event_id, nesqp->last_aeq, tcp_state);
2952 }
2953 if ((tcp_state != NES_AEQE_TCP_STATE_CLOSE_WAIT) ||
2954 (nesqp->ibqp_state != IB_QPS_RTS)) {
2955 /* FIN Received but tcp state or IB state moved on,
2956 should expect a close complete */
2957 return;
2958 }
2959 case NES_AEQE_AEID_LLP_CLOSE_COMPLETE:
2960 case NES_AEQE_AEID_LLP_CONNECTION_RESET:
2961 case NES_AEQE_AEID_TERMINATE_SENT:
2962 case NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE:
2963 case NES_AEQE_AEID_RESET_SENT:
2964 nesqp = *((struct nes_qp **)&context);
2965 if (async_event_id == NES_AEQE_AEID_RESET_SENT) {
2966 tcp_state = NES_AEQE_TCP_STATE_CLOSED;
2967 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002968 spin_lock_irqsave(&nesqp->lock, flags);
2969 nesqp->hw_iwarp_state = iwarp_state;
2970 nesqp->hw_tcp_state = tcp_state;
2971 nesqp->last_aeq = async_event_id;
2972
2973 if ((tcp_state == NES_AEQE_TCP_STATE_CLOSED) ||
2974 (tcp_state == NES_AEQE_TCP_STATE_TIME_WAIT)) {
2975 nesqp->hte_added = 0;
2976 spin_unlock_irqrestore(&nesqp->lock, flags);
2977 nes_debug(NES_DBG_AEQ, "issuing hw modifyqp for QP%u to remove hte\n",
2978 nesqp->hwqp.qp_id);
2979 nes_hw_modify_qp(nesdev, nesqp,
2980 NES_CQP_QP_IWARP_STATE_ERROR | NES_CQP_QP_DEL_HTE, 0);
2981 spin_lock_irqsave(&nesqp->lock, flags);
2982 }
2983
2984 if ((nesqp->ibqp_state == IB_QPS_RTS) &&
2985 ((tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) ||
2986 (async_event_id == NES_AEQE_AEID_LLP_CONNECTION_RESET))) {
2987 switch (nesqp->hw_iwarp_state) {
2988 case NES_AEQE_IWARP_STATE_RTS:
2989 next_iwarp_state = NES_CQP_QP_IWARP_STATE_CLOSING;
2990 nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_CLOSING;
2991 break;
2992 case NES_AEQE_IWARP_STATE_TERMINATE:
2993 next_iwarp_state = NES_CQP_QP_IWARP_STATE_TERMINATE;
2994 nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_TERMINATE;
2995 if (async_event_id == NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE) {
2996 next_iwarp_state |= 0x02000000;
2997 nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
2998 }
2999 break;
3000 default:
3001 next_iwarp_state = 0;
3002 }
3003 spin_unlock_irqrestore(&nesqp->lock, flags);
3004 if (next_iwarp_state) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003005 nes_debug(NES_DBG_AEQ, "issuing hw modifyqp for QP%u. next state = 0x%08X,"
3006 " also added another reference\n",
3007 nesqp->hwqp.qp_id, next_iwarp_state);
3008 nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0);
3009 }
3010 nes_cm_disconn(nesqp);
3011 } else {
3012 if (async_event_id == NES_AEQE_AEID_LLP_FIN_RECEIVED) {
3013 /* FIN Received but ib state not RTS,
3014 close complete will be on its way */
3015 spin_unlock_irqrestore(&nesqp->lock, flags);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003016 return;
3017 }
3018 spin_unlock_irqrestore(&nesqp->lock, flags);
3019 if (async_event_id == NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE) {
3020 next_iwarp_state = NES_CQP_QP_IWARP_STATE_TERMINATE | 0x02000000;
3021 nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
3022 nes_debug(NES_DBG_AEQ, "issuing hw modifyqp for QP%u. next state = 0x%08X,"
3023 " also added another reference\n",
3024 nesqp->hwqp.qp_id, next_iwarp_state);
3025 nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0);
3026 }
3027 nes_cm_disconn(nesqp);
3028 }
3029 break;
3030 case NES_AEQE_AEID_LLP_TERMINATE_RECEIVED:
3031 nesqp = *((struct nes_qp **)&context);
3032 spin_lock_irqsave(&nesqp->lock, flags);
3033 nesqp->hw_iwarp_state = iwarp_state;
3034 nesqp->hw_tcp_state = tcp_state;
3035 nesqp->last_aeq = async_event_id;
3036 spin_unlock_irqrestore(&nesqp->lock, flags);
3037 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_LLP_TERMINATE_RECEIVED"
3038 " event on QP%u \n Q2 Data:\n",
3039 nesqp->hwqp.qp_id);
3040 if (nesqp->ibqp.event_handler) {
3041 ibevent.device = nesqp->ibqp.device;
3042 ibevent.element.qp = &nesqp->ibqp;
3043 ibevent.event = IB_EVENT_QP_FATAL;
3044 nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
3045 }
3046 if ((tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) ||
3047 ((nesqp->ibqp_state == IB_QPS_RTS)&&
3048 (async_event_id == NES_AEQE_AEID_LLP_CONNECTION_RESET))) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003049 nes_cm_disconn(nesqp);
3050 } else {
3051 nesqp->in_disconnect = 0;
3052 wake_up(&nesqp->kick_waitq);
3053 }
3054 break;
3055 case NES_AEQE_AEID_LLP_TOO_MANY_RETRIES:
3056 nesqp = *((struct nes_qp **)&context);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003057 spin_lock_irqsave(&nesqp->lock, flags);
3058 nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_ERROR;
3059 nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
3060 nesqp->last_aeq = async_event_id;
3061 if (nesqp->cm_id) {
3062 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_LLP_TOO_MANY_RETRIES"
3063 " event on QP%u, remote IP = 0x%08X \n",
3064 nesqp->hwqp.qp_id,
3065 ntohl(nesqp->cm_id->remote_addr.sin_addr.s_addr));
3066 } else {
3067 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_LLP_TOO_MANY_RETRIES"
3068 " event on QP%u \n",
3069 nesqp->hwqp.qp_id);
3070 }
3071 spin_unlock_irqrestore(&nesqp->lock, flags);
3072 next_iwarp_state = NES_CQP_QP_IWARP_STATE_ERROR | NES_CQP_QP_RESET;
3073 nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0);
3074 if (nesqp->ibqp.event_handler) {
3075 ibevent.device = nesqp->ibqp.device;
3076 ibevent.element.qp = &nesqp->ibqp;
3077 ibevent.event = IB_EVENT_QP_FATAL;
3078 nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
3079 }
3080 break;
3081 case NES_AEQE_AEID_AMP_BAD_STAG_INDEX:
3082 if (NES_AEQE_INBOUND_RDMA&aeq_info) {
3083 nesqp = nesadapter->qp_table[le32_to_cpu(
3084 aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX])-NES_FIRST_QPN];
3085 } else {
3086 /* TODO: get the actual WQE and mask off wqe index */
3087 context &= ~((u64)511);
3088 nesqp = *((struct nes_qp **)&context);
3089 }
3090 spin_lock_irqsave(&nesqp->lock, flags);
3091 nesqp->hw_iwarp_state = iwarp_state;
3092 nesqp->hw_tcp_state = tcp_state;
3093 nesqp->last_aeq = async_event_id;
3094 spin_unlock_irqrestore(&nesqp->lock, flags);
3095 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_AMP_BAD_STAG_INDEX event on QP%u\n",
3096 nesqp->hwqp.qp_id);
3097 if (nesqp->ibqp.event_handler) {
3098 ibevent.device = nesqp->ibqp.device;
3099 ibevent.element.qp = &nesqp->ibqp;
3100 ibevent.event = IB_EVENT_QP_ACCESS_ERR;
3101 nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
3102 }
3103 break;
3104 case NES_AEQE_AEID_AMP_UNALLOCATED_STAG:
3105 nesqp = *((struct nes_qp **)&context);
3106 spin_lock_irqsave(&nesqp->lock, flags);
3107 nesqp->hw_iwarp_state = iwarp_state;
3108 nesqp->hw_tcp_state = tcp_state;
3109 nesqp->last_aeq = async_event_id;
3110 spin_unlock_irqrestore(&nesqp->lock, flags);
3111 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_AMP_UNALLOCATED_STAG event on QP%u\n",
3112 nesqp->hwqp.qp_id);
3113 if (nesqp->ibqp.event_handler) {
3114 ibevent.device = nesqp->ibqp.device;
3115 ibevent.element.qp = &nesqp->ibqp;
3116 ibevent.event = IB_EVENT_QP_ACCESS_ERR;
3117 nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
3118 }
3119 break;
3120 case NES_AEQE_AEID_PRIV_OPERATION_DENIED:
3121 nesqp = nesadapter->qp_table[le32_to_cpu(aeqe->aeqe_words
3122 [NES_AEQE_COMP_QP_CQ_ID_IDX])-NES_FIRST_QPN];
3123 spin_lock_irqsave(&nesqp->lock, flags);
3124 nesqp->hw_iwarp_state = iwarp_state;
3125 nesqp->hw_tcp_state = tcp_state;
3126 nesqp->last_aeq = async_event_id;
3127 spin_unlock_irqrestore(&nesqp->lock, flags);
3128 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_PRIV_OPERATION_DENIED event on QP%u,"
3129 " nesqp = %p, AE reported %p\n",
3130 nesqp->hwqp.qp_id, nesqp, *((struct nes_qp **)&context));
3131 if (nesqp->ibqp.event_handler) {
3132 ibevent.device = nesqp->ibqp.device;
3133 ibevent.element.qp = &nesqp->ibqp;
3134 ibevent.event = IB_EVENT_QP_ACCESS_ERR;
3135 nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
3136 }
3137 break;
3138 case NES_AEQE_AEID_CQ_OPERATION_ERROR:
3139 context <<= 1;
3140 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_CQ_OPERATION_ERROR event on CQ%u, %p\n",
3141 le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]), (void *)(unsigned long)context);
3142 resource_allocated = nes_is_resource_allocated(nesadapter, nesadapter->allocated_cqs,
3143 le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]));
3144 if (resource_allocated) {
3145 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 -07003146 __func__, le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]));
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003147 }
3148 break;
3149 case NES_AEQE_AEID_DDP_UBE_DDP_MESSAGE_TOO_LONG_FOR_AVAILABLE_BUFFER:
3150 nesqp = nesadapter->qp_table[le32_to_cpu(
3151 aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX])-NES_FIRST_QPN];
3152 spin_lock_irqsave(&nesqp->lock, flags);
3153 nesqp->hw_iwarp_state = iwarp_state;
3154 nesqp->hw_tcp_state = tcp_state;
3155 nesqp->last_aeq = async_event_id;
3156 spin_unlock_irqrestore(&nesqp->lock, flags);
3157 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_DDP_UBE_DDP_MESSAGE_TOO_LONG"
3158 "_FOR_AVAILABLE_BUFFER event on QP%u\n",
3159 nesqp->hwqp.qp_id);
3160 if (nesqp->ibqp.event_handler) {
3161 ibevent.device = nesqp->ibqp.device;
3162 ibevent.element.qp = &nesqp->ibqp;
3163 ibevent.event = IB_EVENT_QP_ACCESS_ERR;
3164 nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
3165 }
3166 /* tell cm to disconnect, cm will queue work to thread */
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003167 nes_cm_disconn(nesqp);
3168 break;
3169 case NES_AEQE_AEID_DDP_UBE_INVALID_MSN_NO_BUFFER_AVAILABLE:
3170 nesqp = *((struct nes_qp **)&context);
3171 spin_lock_irqsave(&nesqp->lock, flags);
3172 nesqp->hw_iwarp_state = iwarp_state;
3173 nesqp->hw_tcp_state = tcp_state;
3174 nesqp->last_aeq = async_event_id;
3175 spin_unlock_irqrestore(&nesqp->lock, flags);
3176 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_DDP_UBE_INVALID_MSN"
3177 "_NO_BUFFER_AVAILABLE event on QP%u\n",
3178 nesqp->hwqp.qp_id);
3179 if (nesqp->ibqp.event_handler) {
3180 ibevent.device = nesqp->ibqp.device;
3181 ibevent.element.qp = &nesqp->ibqp;
3182 ibevent.event = IB_EVENT_QP_FATAL;
3183 nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
3184 }
3185 /* tell cm to disconnect, cm will queue work to thread */
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003186 nes_cm_disconn(nesqp);
3187 break;
3188 case NES_AEQE_AEID_LLP_RECEIVED_MPA_CRC_ERROR:
3189 nesqp = *((struct nes_qp **)&context);
3190 spin_lock_irqsave(&nesqp->lock, flags);
3191 nesqp->hw_iwarp_state = iwarp_state;
3192 nesqp->hw_tcp_state = tcp_state;
3193 nesqp->last_aeq = async_event_id;
3194 spin_unlock_irqrestore(&nesqp->lock, flags);
3195 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_LLP_RECEIVED_MPA_CRC_ERROR"
3196 " event on QP%u \n Q2 Data:\n",
3197 nesqp->hwqp.qp_id);
3198 if (nesqp->ibqp.event_handler) {
3199 ibevent.device = nesqp->ibqp.device;
3200 ibevent.element.qp = &nesqp->ibqp;
3201 ibevent.event = IB_EVENT_QP_FATAL;
3202 nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
3203 }
3204 /* tell cm to disconnect, cm will queue work to thread */
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003205 nes_cm_disconn(nesqp);
3206 break;
3207 /* TODO: additional AEs need to be here */
Faisal Latif1bb28492008-09-26 15:08:10 -05003208 case NES_AEQE_AEID_AMP_BOUNDS_VIOLATION:
3209 nesqp = *((struct nes_qp **)&context);
3210 spin_lock_irqsave(&nesqp->lock, flags);
3211 nesqp->hw_iwarp_state = iwarp_state;
3212 nesqp->hw_tcp_state = tcp_state;
3213 nesqp->last_aeq = async_event_id;
3214 spin_unlock_irqrestore(&nesqp->lock, flags);
3215 if (nesqp->ibqp.event_handler) {
3216 ibevent.device = nesqp->ibqp.device;
3217 ibevent.element.qp = &nesqp->ibqp;
3218 ibevent.event = IB_EVENT_QP_ACCESS_ERR;
3219 nesqp->ibqp.event_handler(&ibevent,
3220 nesqp->ibqp.qp_context);
3221 }
3222 nes_cm_disconn(nesqp);
3223 break;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003224 default:
3225 nes_debug(NES_DBG_AEQ, "Processing an iWARP related AE for QP, misc = 0x%04X\n",
3226 async_event_id);
3227 break;
3228 }
3229
3230}
3231
3232
3233/**
3234 * nes_iwarp_ce_handler
3235 */
3236void nes_iwarp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *hw_cq)
3237{
3238 struct nes_cq *nescq = container_of(hw_cq, struct nes_cq, hw_cq);
3239
3240 /* nes_debug(NES_DBG_CQ, "Processing completion event for iWARP CQ%u.\n",
3241 nescq->hw_cq.cq_number); */
3242 nes_write32(nesdev->regs+NES_CQ_ACK, nescq->hw_cq.cq_number);
3243
3244 if (nescq->ibcq.comp_handler)
3245 nescq->ibcq.comp_handler(&nescq->ibcq, nescq->ibcq.cq_context);
3246
3247 return;
3248}
3249
3250
3251/**
3252 * nes_manage_apbvt()
3253 */
3254int nes_manage_apbvt(struct nes_vnic *nesvnic, u32 accel_local_port,
3255 u32 nic_index, u32 add_port)
3256{
3257 struct nes_device *nesdev = nesvnic->nesdev;
3258 struct nes_hw_cqp_wqe *cqp_wqe;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003259 struct nes_cqp_request *cqp_request;
3260 int ret = 0;
3261 u16 major_code;
3262
3263 /* Send manage APBVT request to CQP */
3264 cqp_request = nes_get_cqp_request(nesdev);
3265 if (cqp_request == NULL) {
3266 nes_debug(NES_DBG_QP, "Failed to get a cqp_request.\n");
3267 return -ENOMEM;
3268 }
3269 cqp_request->waiting = 1;
3270 cqp_wqe = &cqp_request->cqp_wqe;
3271
3272 nes_debug(NES_DBG_QP, "%s APBV for local port=%u(0x%04x), nic_index=%u\n",
3273 (add_port == NES_MANAGE_APBVT_ADD) ? "ADD" : "DEL",
3274 accel_local_port, accel_local_port, nic_index);
3275
3276 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
3277 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, (NES_CQP_MANAGE_APBVT |
3278 ((add_port == NES_MANAGE_APBVT_ADD) ? NES_CQP_APBVT_ADD : 0)));
3279 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,
3280 ((nic_index << NES_CQP_APBVT_NIC_SHIFT) | accel_local_port));
3281
3282 nes_debug(NES_DBG_QP, "Waiting for CQP completion for APBVT.\n");
3283
3284 atomic_set(&cqp_request->refcount, 2);
Roland Dreier8294f292008-07-14 23:48:49 -07003285 nes_post_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003286
3287 if (add_port == NES_MANAGE_APBVT_ADD)
3288 ret = wait_event_timeout(cqp_request->waitq, (cqp_request->request_done != 0),
3289 NES_EVENT_TIMEOUT);
3290 nes_debug(NES_DBG_QP, "Completed, ret=%u, CQP Major:Minor codes = 0x%04X:0x%04X\n",
3291 ret, cqp_request->major_code, cqp_request->minor_code);
3292 major_code = cqp_request->major_code;
Roland Dreier1ff66e82008-07-14 23:48:49 -07003293
3294 nes_put_cqp_request(nesdev, cqp_request);
3295
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003296 if (!ret)
3297 return -ETIME;
3298 else if (major_code)
3299 return -EIO;
3300 else
3301 return 0;
3302}
3303
3304
3305/**
3306 * nes_manage_arp_cache
3307 */
3308void nes_manage_arp_cache(struct net_device *netdev, unsigned char *mac_addr,
3309 u32 ip_addr, u32 action)
3310{
3311 struct nes_hw_cqp_wqe *cqp_wqe;
3312 struct nes_vnic *nesvnic = netdev_priv(netdev);
3313 struct nes_device *nesdev;
3314 struct nes_cqp_request *cqp_request;
3315 int arp_index;
3316
3317 nesdev = nesvnic->nesdev;
3318 arp_index = nes_arp_table(nesdev, ip_addr, mac_addr, action);
3319 if (arp_index == -1) {
3320 return;
3321 }
3322
3323 /* update the ARP entry */
3324 cqp_request = nes_get_cqp_request(nesdev);
3325 if (cqp_request == NULL) {
3326 nes_debug(NES_DBG_NETDEV, "Failed to get a cqp_request.\n");
3327 return;
3328 }
3329 cqp_request->waiting = 0;
3330 cqp_wqe = &cqp_request->cqp_wqe;
3331 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
3332
3333 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(
3334 NES_CQP_MANAGE_ARP_CACHE | NES_CQP_ARP_PERM);
3335 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= cpu_to_le32(
3336 (u32)PCI_FUNC(nesdev->pcidev->devfn) << NES_CQP_ARP_AEQ_INDEX_SHIFT);
3337 cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(arp_index);
3338
3339 if (action == NES_ARP_ADD) {
3340 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= cpu_to_le32(NES_CQP_ARP_VALID);
3341 cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_ADDR_LOW_IDX] = cpu_to_le32(
3342 (((u32)mac_addr[2]) << 24) | (((u32)mac_addr[3]) << 16) |
Glenn Streiff7495ab62008-04-29 13:46:54 -07003343 (((u32)mac_addr[4]) << 8) | (u32)mac_addr[5]);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003344 cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_HIGH_IDX] = cpu_to_le32(
3345 (((u32)mac_addr[0]) << 16) | (u32)mac_addr[1]);
3346 } else {
3347 cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_ADDR_LOW_IDX] = 0;
3348 cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_HIGH_IDX] = 0;
3349 }
3350
3351 nes_debug(NES_DBG_NETDEV, "Not waiting for CQP, cqp.sq_head=%u, cqp.sq_tail=%u\n",
3352 nesdev->cqp.sq_head, nesdev->cqp.sq_tail);
3353
3354 atomic_set(&cqp_request->refcount, 1);
Roland Dreier8294f292008-07-14 23:48:49 -07003355 nes_post_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003356}
3357
3358
3359/**
3360 * flush_wqes
3361 */
3362void flush_wqes(struct nes_device *nesdev, struct nes_qp *nesqp,
3363 u32 which_wq, u32 wait_completion)
3364{
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003365 struct nes_cqp_request *cqp_request;
3366 struct nes_hw_cqp_wqe *cqp_wqe;
3367 int ret;
3368
3369 cqp_request = nes_get_cqp_request(nesdev);
3370 if (cqp_request == NULL) {
3371 nes_debug(NES_DBG_QP, "Failed to get a cqp_request.\n");
3372 return;
3373 }
3374 if (wait_completion) {
3375 cqp_request->waiting = 1;
3376 atomic_set(&cqp_request->refcount, 2);
3377 } else {
3378 cqp_request->waiting = 0;
3379 }
3380 cqp_wqe = &cqp_request->cqp_wqe;
3381 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
3382
3383 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] =
3384 cpu_to_le32(NES_CQP_FLUSH_WQES | which_wq);
3385 cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesqp->hwqp.qp_id);
3386
Roland Dreier8294f292008-07-14 23:48:49 -07003387 nes_post_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003388
3389 if (wait_completion) {
3390 /* Wait for CQP */
3391 ret = wait_event_timeout(cqp_request->waitq, (cqp_request->request_done != 0),
3392 NES_EVENT_TIMEOUT);
3393 nes_debug(NES_DBG_QP, "Flush SQ QP WQEs completed, ret=%u,"
3394 " CQP Major:Minor codes = 0x%04X:0x%04X\n",
3395 ret, cqp_request->major_code, cqp_request->minor_code);
Roland Dreier1ff66e82008-07-14 23:48:49 -07003396 nes_put_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003397 }
3398}