blob: 2aa021655e33248e2ee1e05e51c6e8d311174faa [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 */
Chien Tung366835e2009-04-27 13:28:41 -0700764 if (!(OneG_Mode && (nesadapter->phy_type[1] != NES_PHY_TYPE_PUMA_1G)))
765 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000000FF);
766
Chien Tunga4849fc2009-04-08 14:27:18 -0700767 switch (nesadapter->phy_type[1]) {
Chien Tung43035652009-04-08 14:27:56 -0700768 case NES_PHY_TYPE_ARGUS:
769 case NES_PHY_TYPE_SFP_D:
Chien Tunga4849fc2009-04-08 14:27:18 -0700770 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP0, 0x00000000);
771 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP1, 0x00000000);
772 break;
773 case NES_PHY_TYPE_CX4:
Chien Tunga4849fc2009-04-08 14:27:18 -0700774 if (wide_ppm_offset)
775 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000FFFAA);
Chien Tunga4849fc2009-04-08 14:27:18 -0700776 break;
777 case NES_PHY_TYPE_PUMA_1G:
778 sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1);
779 sds |= 0x000000100;
780 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, sds);
Chien Tungfcb7ad32008-09-30 14:49:44 -0700781 }
Chien Tung366835e2009-04-27 13:28:41 -0700782 if (!OneG_Mode) {
Chien Tunga4849fc2009-04-08 14:27:18 -0700783 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE1, 0x11110000);
Chien Tung366835e2009-04-27 13:28:41 -0700784 sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1);
785 sds &= 0xFFFFFFBF;
786 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, sds);
787 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800788 } else {
789 /* init serdes 0 */
790 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, 0x00000008);
791 i = 0;
792 while (((u32temp = (nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0)
793 & 0x0000000f)) != 0x0000000f) && i++ < 5000)
794 mdelay(1);
795 if (i >= 5000) {
796 nes_debug(NES_DBG_PHY, "Init: serdes 0 not ready, status=%x\n", u32temp);
797 return 1;
798 }
799 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP0, 0x000bdef7);
800 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_DRIVE0, 0x9ce73000);
801 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_MODE0, 0x0ff00000);
802 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_SIGDET0, 0x00000000);
803 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_BYPASS0, 0x00000000);
804 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_LOOPBACK_CONTROL0, 0x00000000);
805 if (OneG_Mode)
806 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_EQ_CONTROL0, 0xf0182222);
807 else
808 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_EQ_CONTROL0, 0xf0042222);
809
810 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000000ff);
811 if (port_count > 1) {
812 /* init serdes 1 */
813 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x00000048);
814 i = 0;
815 while (((u32temp = (nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS1)
816 & 0x0000000f)) != 0x0000000f) && (i++ < 5000))
817 mdelay(1);
818 if (i >= 5000) {
Harvey Harrison33718362008-04-16 21:01:10 -0700819 printk("%s: Init: serdes 1 not ready, status=%x\n", __func__, u32temp);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800820 /* return 1; */
821 }
822 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP1, 0x000bdef7);
823 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_DRIVE1, 0x9ce73000);
824 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_MODE1, 0x0ff00000);
825 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_SIGDET1, 0x00000000);
826 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_BYPASS1, 0x00000000);
827 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_LOOPBACK_CONTROL1, 0x00000000);
828 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_EQ_CONTROL1, 0xf0002222);
829 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000000ff);
830 }
831 }
832 return 0;
833}
834
835
836/**
837 * nes_init_csr_ne020
838 * Initialize registers for ne020 hardware
839 */
Roland Dreier1a855fbf2008-04-16 21:01:09 -0700840static void nes_init_csr_ne020(struct nes_device *nesdev, u8 hw_rev, u8 port_count)
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800841{
842 u32 u32temp;
843
844 nes_debug(NES_DBG_INIT, "port_count=%d\n", port_count);
845
846 nes_write_indexed(nesdev, 0x000001E4, 0x00000007);
847 /* nes_write_indexed(nesdev, 0x000001E8, 0x000208C4); */
848 nes_write_indexed(nesdev, 0x000001E8, 0x00020874);
849 nes_write_indexed(nesdev, 0x000001D8, 0x00048002);
850 /* nes_write_indexed(nesdev, 0x000001D8, 0x0004B002); */
851 nes_write_indexed(nesdev, 0x000001FC, 0x00050005);
852 nes_write_indexed(nesdev, 0x00000600, 0x55555555);
853 nes_write_indexed(nesdev, 0x00000604, 0x55555555);
854
855 /* TODO: move these MAC register settings to NIC bringup */
856 nes_write_indexed(nesdev, 0x00002000, 0x00000001);
857 nes_write_indexed(nesdev, 0x00002004, 0x00000001);
858 nes_write_indexed(nesdev, 0x00002008, 0x0000FFFF);
859 nes_write_indexed(nesdev, 0x0000200C, 0x00000001);
860 nes_write_indexed(nesdev, 0x00002010, 0x000003c1);
861 nes_write_indexed(nesdev, 0x0000201C, 0x75345678);
862 if (port_count > 1) {
863 nes_write_indexed(nesdev, 0x00002200, 0x00000001);
864 nes_write_indexed(nesdev, 0x00002204, 0x00000001);
865 nes_write_indexed(nesdev, 0x00002208, 0x0000FFFF);
866 nes_write_indexed(nesdev, 0x0000220C, 0x00000001);
867 nes_write_indexed(nesdev, 0x00002210, 0x000003c1);
868 nes_write_indexed(nesdev, 0x0000221C, 0x75345678);
869 nes_write_indexed(nesdev, 0x00000908, 0x20000001);
870 }
871 if (port_count > 2) {
872 nes_write_indexed(nesdev, 0x00002400, 0x00000001);
873 nes_write_indexed(nesdev, 0x00002404, 0x00000001);
874 nes_write_indexed(nesdev, 0x00002408, 0x0000FFFF);
875 nes_write_indexed(nesdev, 0x0000240C, 0x00000001);
876 nes_write_indexed(nesdev, 0x00002410, 0x000003c1);
877 nes_write_indexed(nesdev, 0x0000241C, 0x75345678);
878 nes_write_indexed(nesdev, 0x00000910, 0x20000001);
879
880 nes_write_indexed(nesdev, 0x00002600, 0x00000001);
881 nes_write_indexed(nesdev, 0x00002604, 0x00000001);
882 nes_write_indexed(nesdev, 0x00002608, 0x0000FFFF);
883 nes_write_indexed(nesdev, 0x0000260C, 0x00000001);
884 nes_write_indexed(nesdev, 0x00002610, 0x000003c1);
885 nes_write_indexed(nesdev, 0x0000261C, 0x75345678);
886 nes_write_indexed(nesdev, 0x00000918, 0x20000001);
887 }
888
889 nes_write_indexed(nesdev, 0x00005000, 0x00018000);
890 /* nes_write_indexed(nesdev, 0x00005000, 0x00010000); */
Chien Tung2b537c22008-09-26 15:08:10 -0500891 nes_write_indexed(nesdev, NES_IDX_WQM_CONFIG1, (wqm_quanta << 1) |
892 0x00000001);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800893 nes_write_indexed(nesdev, 0x00005008, 0x1F1F1F1F);
894 nes_write_indexed(nesdev, 0x00005010, 0x1F1F1F1F);
895 nes_write_indexed(nesdev, 0x00005018, 0x1F1F1F1F);
896 nes_write_indexed(nesdev, 0x00005020, 0x1F1F1F1F);
897 nes_write_indexed(nesdev, 0x00006090, 0xFFFFFFFF);
898
899 /* TODO: move this to code, get from EEPROM */
900 nes_write_indexed(nesdev, 0x00000900, 0x20000001);
901 nes_write_indexed(nesdev, 0x000060C0, 0x0000028e);
902 nes_write_indexed(nesdev, 0x000060C8, 0x00000020);
Glenn Streiff7495ab62008-04-29 13:46:54 -0700903
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800904 nes_write_indexed(nesdev, 0x000001EC, 0x7b2625a0);
905 /* nes_write_indexed(nesdev, 0x000001EC, 0x5f2625a0); */
906
907 if (hw_rev != NE020_REV) {
908 u32temp = nes_read_indexed(nesdev, 0x000008e8);
909 u32temp |= 0x80000000;
910 nes_write_indexed(nesdev, 0x000008e8, u32temp);
911 u32temp = nes_read_indexed(nesdev, 0x000021f8);
912 u32temp &= 0x7fffffff;
913 u32temp |= 0x7fff0010;
914 nes_write_indexed(nesdev, 0x000021f8, u32temp);
Chien Tunge998c252009-04-27 13:29:42 -0700915 if (port_count > 1) {
916 u32temp = nes_read_indexed(nesdev, 0x000023f8);
917 u32temp &= 0x7fffffff;
918 u32temp |= 0x7fff0010;
919 nes_write_indexed(nesdev, 0x000023f8, u32temp);
920 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800921 }
922}
923
924
925/**
926 * nes_destroy_adapter - destroy the adapter structure
927 */
928void nes_destroy_adapter(struct nes_adapter *nesadapter)
929{
930 struct nes_adapter *tmp_adapter;
931
932 list_for_each_entry(tmp_adapter, &nes_adapter_list, list) {
933 nes_debug(NES_DBG_SHUTDOWN, "Nes Adapter list entry = 0x%p.\n",
934 tmp_adapter);
935 }
936
937 nesadapter->ref_count--;
938 if (!nesadapter->ref_count) {
939 if (nesadapter->hw_rev == NE020_REV) {
940 del_timer(&nesadapter->mh_timer);
941 }
942 del_timer(&nesadapter->lc_timer);
943
944 list_del(&nesadapter->list);
945 kfree(nesadapter);
946 }
947}
948
949
950/**
951 * nes_init_cqp
952 */
953int nes_init_cqp(struct nes_device *nesdev)
954{
955 struct nes_adapter *nesadapter = nesdev->nesadapter;
956 struct nes_hw_cqp_qp_context *cqp_qp_context;
957 struct nes_hw_cqp_wqe *cqp_wqe;
958 struct nes_hw_ceq *ceq;
959 struct nes_hw_ceq *nic_ceq;
960 struct nes_hw_aeq *aeq;
961 void *vmem;
962 dma_addr_t pmem;
963 u32 count=0;
964 u32 cqp_head;
965 u64 u64temp;
966 u32 u32temp;
967
968 /* allocate CQP memory */
969 /* Need to add max_cq to the aeq size once cq overflow checking is added back */
970 /* SQ is 512 byte aligned, others are 256 byte aligned */
971 nesdev->cqp_mem_size = 512 +
972 (sizeof(struct nes_hw_cqp_wqe) * NES_CQP_SQ_SIZE) +
973 (sizeof(struct nes_hw_cqe) * NES_CCQ_SIZE) +
974 max(((u32)sizeof(struct nes_hw_ceqe) * NES_CCEQ_SIZE), (u32)256) +
975 max(((u32)sizeof(struct nes_hw_ceqe) * NES_NIC_CEQ_SIZE), (u32)256) +
976 (sizeof(struct nes_hw_aeqe) * nesadapter->max_qp) +
977 sizeof(struct nes_hw_cqp_qp_context);
978
979 nesdev->cqp_vbase = pci_alloc_consistent(nesdev->pcidev, nesdev->cqp_mem_size,
980 &nesdev->cqp_pbase);
981 if (!nesdev->cqp_vbase) {
982 nes_debug(NES_DBG_INIT, "Unable to allocate memory for host descriptor rings\n");
983 return -ENOMEM;
984 }
985 memset(nesdev->cqp_vbase, 0, nesdev->cqp_mem_size);
986
987 /* Allocate a twice the number of CQP requests as the SQ size */
988 nesdev->nes_cqp_requests = kzalloc(sizeof(struct nes_cqp_request) *
989 2 * NES_CQP_SQ_SIZE, GFP_KERNEL);
990 if (nesdev->nes_cqp_requests == NULL) {
991 nes_debug(NES_DBG_INIT, "Unable to allocate memory CQP request entries.\n");
992 pci_free_consistent(nesdev->pcidev, nesdev->cqp_mem_size, nesdev->cqp.sq_vbase,
993 nesdev->cqp.sq_pbase);
994 return -ENOMEM;
995 }
996
997 nes_debug(NES_DBG_INIT, "Allocated CQP structures at %p (phys = %016lX), size = %u.\n",
998 nesdev->cqp_vbase, (unsigned long)nesdev->cqp_pbase, nesdev->cqp_mem_size);
999
1000 spin_lock_init(&nesdev->cqp.lock);
1001 init_waitqueue_head(&nesdev->cqp.waitq);
1002
1003 /* Setup Various Structures */
1004 vmem = (void *)(((unsigned long)nesdev->cqp_vbase + (512 - 1)) &
1005 ~(unsigned long)(512 - 1));
1006 pmem = (dma_addr_t)(((unsigned long long)nesdev->cqp_pbase + (512 - 1)) &
1007 ~(unsigned long long)(512 - 1));
1008
1009 nesdev->cqp.sq_vbase = vmem;
1010 nesdev->cqp.sq_pbase = pmem;
1011 nesdev->cqp.sq_size = NES_CQP_SQ_SIZE;
1012 nesdev->cqp.sq_head = 0;
1013 nesdev->cqp.sq_tail = 0;
1014 nesdev->cqp.qp_id = PCI_FUNC(nesdev->pcidev->devfn);
1015
1016 vmem += (sizeof(struct nes_hw_cqp_wqe) * nesdev->cqp.sq_size);
1017 pmem += (sizeof(struct nes_hw_cqp_wqe) * nesdev->cqp.sq_size);
1018
1019 nesdev->ccq.cq_vbase = vmem;
1020 nesdev->ccq.cq_pbase = pmem;
1021 nesdev->ccq.cq_size = NES_CCQ_SIZE;
1022 nesdev->ccq.cq_head = 0;
1023 nesdev->ccq.ce_handler = nes_cqp_ce_handler;
1024 nesdev->ccq.cq_number = PCI_FUNC(nesdev->pcidev->devfn);
1025
1026 vmem += (sizeof(struct nes_hw_cqe) * nesdev->ccq.cq_size);
1027 pmem += (sizeof(struct nes_hw_cqe) * nesdev->ccq.cq_size);
1028
1029 nesdev->ceq_index = PCI_FUNC(nesdev->pcidev->devfn);
1030 ceq = &nesadapter->ceq[nesdev->ceq_index];
1031 ceq->ceq_vbase = vmem;
1032 ceq->ceq_pbase = pmem;
1033 ceq->ceq_size = NES_CCEQ_SIZE;
1034 ceq->ceq_head = 0;
1035
1036 vmem += max(((u32)sizeof(struct nes_hw_ceqe) * ceq->ceq_size), (u32)256);
1037 pmem += max(((u32)sizeof(struct nes_hw_ceqe) * ceq->ceq_size), (u32)256);
1038
1039 nesdev->nic_ceq_index = PCI_FUNC(nesdev->pcidev->devfn) + 8;
1040 nic_ceq = &nesadapter->ceq[nesdev->nic_ceq_index];
1041 nic_ceq->ceq_vbase = vmem;
1042 nic_ceq->ceq_pbase = pmem;
1043 nic_ceq->ceq_size = NES_NIC_CEQ_SIZE;
1044 nic_ceq->ceq_head = 0;
1045
1046 vmem += max(((u32)sizeof(struct nes_hw_ceqe) * nic_ceq->ceq_size), (u32)256);
1047 pmem += max(((u32)sizeof(struct nes_hw_ceqe) * nic_ceq->ceq_size), (u32)256);
1048
1049 aeq = &nesadapter->aeq[PCI_FUNC(nesdev->pcidev->devfn)];
1050 aeq->aeq_vbase = vmem;
1051 aeq->aeq_pbase = pmem;
1052 aeq->aeq_size = nesadapter->max_qp;
1053 aeq->aeq_head = 0;
1054
1055 /* Setup QP Context */
1056 vmem += (sizeof(struct nes_hw_aeqe) * aeq->aeq_size);
1057 pmem += (sizeof(struct nes_hw_aeqe) * aeq->aeq_size);
1058
1059 cqp_qp_context = vmem;
1060 cqp_qp_context->context_words[0] =
1061 cpu_to_le32((PCI_FUNC(nesdev->pcidev->devfn) << 12) + (2 << 10));
1062 cqp_qp_context->context_words[1] = 0;
1063 cqp_qp_context->context_words[2] = cpu_to_le32((u32)nesdev->cqp.sq_pbase);
1064 cqp_qp_context->context_words[3] = cpu_to_le32(((u64)nesdev->cqp.sq_pbase) >> 32);
1065
1066
1067 /* Write the address to Create CQP */
1068 if ((sizeof(dma_addr_t) > 4)) {
1069 nes_write_indexed(nesdev,
1070 NES_IDX_CREATE_CQP_HIGH + (PCI_FUNC(nesdev->pcidev->devfn) * 8),
1071 ((u64)pmem) >> 32);
1072 } else {
1073 nes_write_indexed(nesdev,
1074 NES_IDX_CREATE_CQP_HIGH + (PCI_FUNC(nesdev->pcidev->devfn) * 8), 0);
1075 }
1076 nes_write_indexed(nesdev,
1077 NES_IDX_CREATE_CQP_LOW + (PCI_FUNC(nesdev->pcidev->devfn) * 8),
1078 (u32)pmem);
1079
1080 INIT_LIST_HEAD(&nesdev->cqp_avail_reqs);
1081 INIT_LIST_HEAD(&nesdev->cqp_pending_reqs);
1082
1083 for (count = 0; count < 2*NES_CQP_SQ_SIZE; count++) {
1084 init_waitqueue_head(&nesdev->nes_cqp_requests[count].waitq);
1085 list_add_tail(&nesdev->nes_cqp_requests[count].list, &nesdev->cqp_avail_reqs);
1086 }
1087
1088 /* Write Create CCQ WQE */
1089 cqp_head = nesdev->cqp.sq_head++;
1090 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1091 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
1092 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
1093 (NES_CQP_CREATE_CQ | NES_CQP_CQ_CEQ_VALID |
1094 NES_CQP_CQ_CHK_OVERFLOW | ((u32)nesdev->ccq.cq_size << 16)));
1095 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,
1096 (nesdev->ccq.cq_number |
1097 ((u32)nesdev->ceq_index << 16)));
1098 u64temp = (u64)nesdev->ccq.cq_pbase;
1099 set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);
1100 cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] = 0;
1101 u64temp = (unsigned long)&nesdev->ccq;
1102 cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_LOW_IDX] =
1103 cpu_to_le32((u32)(u64temp >> 1));
1104 cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] =
1105 cpu_to_le32(((u32)((u64temp) >> 33)) & 0x7FFFFFFF);
1106 cqp_wqe->wqe_words[NES_CQP_CQ_WQE_DOORBELL_INDEX_HIGH_IDX] = 0;
1107
1108 /* Write Create CEQ WQE */
1109 cqp_head = nesdev->cqp.sq_head++;
1110 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1111 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
1112 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
1113 (NES_CQP_CREATE_CEQ + ((u32)nesdev->ceq_index << 8)));
1114 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_CEQ_WQE_ELEMENT_COUNT_IDX, ceq->ceq_size);
1115 u64temp = (u64)ceq->ceq_pbase;
1116 set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);
1117
1118 /* Write Create AEQ WQE */
1119 cqp_head = nesdev->cqp.sq_head++;
1120 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1121 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
1122 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
1123 (NES_CQP_CREATE_AEQ + ((u32)PCI_FUNC(nesdev->pcidev->devfn) << 8)));
1124 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_AEQ_WQE_ELEMENT_COUNT_IDX, aeq->aeq_size);
1125 u64temp = (u64)aeq->aeq_pbase;
1126 set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);
1127
1128 /* Write Create NIC CEQ WQE */
1129 cqp_head = nesdev->cqp.sq_head++;
1130 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1131 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
1132 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
1133 (NES_CQP_CREATE_CEQ + ((u32)nesdev->nic_ceq_index << 8)));
1134 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_CEQ_WQE_ELEMENT_COUNT_IDX, nic_ceq->ceq_size);
1135 u64temp = (u64)nic_ceq->ceq_pbase;
1136 set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);
1137
1138 /* Poll until CCQP done */
1139 count = 0;
1140 do {
1141 if (count++ > 1000) {
1142 printk(KERN_ERR PFX "Error creating CQP\n");
1143 pci_free_consistent(nesdev->pcidev, nesdev->cqp_mem_size,
1144 nesdev->cqp_vbase, nesdev->cqp_pbase);
1145 return -1;
1146 }
1147 udelay(10);
1148 } while (!(nes_read_indexed(nesdev,
1149 NES_IDX_QP_CONTROL + (PCI_FUNC(nesdev->pcidev->devfn) * 8)) & (1 << 8)));
1150
1151 nes_debug(NES_DBG_INIT, "CQP Status = 0x%08X\n", nes_read_indexed(nesdev,
1152 NES_IDX_QP_CONTROL+(PCI_FUNC(nesdev->pcidev->devfn)*8)));
1153
1154 u32temp = 0x04800000;
1155 nes_write32(nesdev->regs+NES_WQE_ALLOC, u32temp | nesdev->cqp.qp_id);
1156
1157 /* wait for the CCQ, CEQ, and AEQ to get created */
1158 count = 0;
1159 do {
1160 if (count++ > 1000) {
1161 printk(KERN_ERR PFX "Error creating CCQ, CEQ, and AEQ\n");
1162 pci_free_consistent(nesdev->pcidev, nesdev->cqp_mem_size,
1163 nesdev->cqp_vbase, nesdev->cqp_pbase);
1164 return -1;
1165 }
1166 udelay(10);
1167 } while (((nes_read_indexed(nesdev,
1168 NES_IDX_QP_CONTROL+(PCI_FUNC(nesdev->pcidev->devfn)*8)) & (15<<8)) != (15<<8)));
1169
1170 /* dump the QP status value */
1171 nes_debug(NES_DBG_INIT, "QP Status = 0x%08X\n", nes_read_indexed(nesdev,
1172 NES_IDX_QP_CONTROL+(PCI_FUNC(nesdev->pcidev->devfn)*8)));
1173
1174 nesdev->cqp.sq_tail++;
1175
1176 return 0;
1177}
1178
1179
1180/**
1181 * nes_destroy_cqp
1182 */
1183int nes_destroy_cqp(struct nes_device *nesdev)
1184{
1185 struct nes_hw_cqp_wqe *cqp_wqe;
1186 u32 count = 0;
1187 u32 cqp_head;
1188 unsigned long flags;
1189
1190 do {
1191 if (count++ > 1000)
1192 break;
1193 udelay(10);
1194 } while (!(nesdev->cqp.sq_head == nesdev->cqp.sq_tail));
1195
1196 /* Reset CCQ */
1197 nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_RESET |
1198 nesdev->ccq.cq_number);
1199
1200 /* Disable device interrupts */
1201 nes_write32(nesdev->regs+NES_INT_MASK, 0x7fffffff);
1202
1203 spin_lock_irqsave(&nesdev->cqp.lock, flags);
1204
1205 /* Destroy the AEQ */
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_AEQ |
1210 ((u32)PCI_FUNC(nesdev->pcidev->devfn) << 8));
1211 cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0;
1212
1213 /* Destroy the NIC CEQ */
1214 cqp_head = nesdev->cqp.sq_head++;
1215 nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
1216 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1217 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_CEQ |
1218 ((u32)nesdev->nic_ceq_index << 8));
1219
1220 /* Destroy the CEQ */
1221 cqp_head = nesdev->cqp.sq_head++;
1222 nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
1223 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1224 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_CEQ |
1225 (nesdev->ceq_index << 8));
1226
1227 /* Destroy the CCQ */
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_CQ);
1232 cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesdev->ccq.cq_number |
1233 ((u32)nesdev->ceq_index << 16));
1234
1235 /* Destroy CQP */
1236 cqp_head = nesdev->cqp.sq_head++;
1237 nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
1238 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1239 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_QP |
1240 NES_CQP_QP_TYPE_CQP);
1241 cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesdev->cqp.qp_id);
1242
1243 barrier();
1244 /* Ring doorbell (5 WQEs) */
1245 nes_write32(nesdev->regs+NES_WQE_ALLOC, 0x05800000 | nesdev->cqp.qp_id);
1246
1247 spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
1248
1249 /* wait for the CCQ, CEQ, and AEQ to get destroyed */
1250 count = 0;
1251 do {
1252 if (count++ > 1000) {
1253 printk(KERN_ERR PFX "Function%d: Error destroying CCQ, CEQ, and AEQ\n",
1254 PCI_FUNC(nesdev->pcidev->devfn));
1255 break;
1256 }
1257 udelay(10);
1258 } while (((nes_read_indexed(nesdev,
1259 NES_IDX_QP_CONTROL + (PCI_FUNC(nesdev->pcidev->devfn)*8)) & (15 << 8)) != 0));
1260
1261 /* dump the QP status value */
1262 nes_debug(NES_DBG_SHUTDOWN, "Function%d: QP Status = 0x%08X\n",
1263 PCI_FUNC(nesdev->pcidev->devfn),
1264 nes_read_indexed(nesdev,
1265 NES_IDX_QP_CONTROL+(PCI_FUNC(nesdev->pcidev->devfn)*8)));
1266
1267 kfree(nesdev->nes_cqp_requests);
1268
1269 /* Free the control structures */
1270 pci_free_consistent(nesdev->pcidev, nesdev->cqp_mem_size, nesdev->cqp.sq_vbase,
1271 nesdev->cqp.sq_pbase);
1272
1273 return 0;
1274}
1275
1276
1277/**
1278 * nes_init_phy
1279 */
1280int nes_init_phy(struct nes_device *nesdev)
1281{
1282 struct nes_adapter *nesadapter = nesdev->nesadapter;
1283 u32 counter = 0;
Chien Tung1b949322009-04-08 14:27:09 -07001284 u32 sds;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001285 u32 mac_index = nesdev->mac_index;
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001286 u32 tx_config = 0;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001287 u16 phy_data;
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001288 u32 temp_phy_data = 0;
1289 u32 temp_phy_data2 = 0;
Chien Tung1b949322009-04-08 14:27:09 -07001290 u8 phy_type = nesadapter->phy_type[mac_index];
1291 u8 phy_index = nesadapter->phy_index[mac_index];
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001292
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001293 if ((nesadapter->OneG_Mode) &&
Chien Tung1b949322009-04-08 14:27:09 -07001294 (phy_type != NES_PHY_TYPE_PUMA_1G)) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001295 nes_debug(NES_DBG_PHY, "1G PHY, mac_index = %d.\n", mac_index);
Chien Tung1b949322009-04-08 14:27:09 -07001296 if (phy_type == NES_PHY_TYPE_1G) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001297 tx_config = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG);
Chien Tunge88bd7b2008-09-26 15:08:10 -05001298 tx_config &= 0xFFFFFFE3;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001299 tx_config |= 0x04;
1300 nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config);
1301 }
1302
Chien Tung1b949322009-04-08 14:27:09 -07001303 nes_read_1G_phy_reg(nesdev, 1, phy_index, &phy_data);
1304 nes_write_1G_phy_reg(nesdev, 23, phy_index, 0xb000);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001305
1306 /* Reset the PHY */
Chien Tung1b949322009-04-08 14:27:09 -07001307 nes_write_1G_phy_reg(nesdev, 0, phy_index, 0x8000);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001308 udelay(100);
1309 counter = 0;
1310 do {
Chien Tung1b949322009-04-08 14:27:09 -07001311 nes_read_1G_phy_reg(nesdev, 0, phy_index, &phy_data);
1312 if (counter++ > 100)
1313 break;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001314 } while (phy_data & 0x8000);
1315
1316 /* Setting no phy loopback */
1317 phy_data &= 0xbfff;
1318 phy_data |= 0x1140;
Chien Tung1b949322009-04-08 14:27:09 -07001319 nes_write_1G_phy_reg(nesdev, 0, phy_index, phy_data);
1320 nes_read_1G_phy_reg(nesdev, 0, phy_index, &phy_data);
1321 nes_read_1G_phy_reg(nesdev, 0x17, phy_index, &phy_data);
1322 nes_read_1G_phy_reg(nesdev, 0x1e, phy_index, &phy_data);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001323
1324 /* Setting the interrupt mask */
Chien Tung1b949322009-04-08 14:27:09 -07001325 nes_read_1G_phy_reg(nesdev, 0x19, phy_index, &phy_data);
1326 nes_write_1G_phy_reg(nesdev, 0x19, phy_index, 0xffee);
1327 nes_read_1G_phy_reg(nesdev, 0x19, phy_index, &phy_data);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001328
1329 /* turning on flow control */
Chien Tung1b949322009-04-08 14:27:09 -07001330 nes_read_1G_phy_reg(nesdev, 4, phy_index, &phy_data);
1331 nes_write_1G_phy_reg(nesdev, 4, phy_index, (phy_data & ~(0x03E0)) | 0xc00);
1332 nes_read_1G_phy_reg(nesdev, 4, phy_index, &phy_data);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001333
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001334 /* Clear Half duplex */
Chien Tung1b949322009-04-08 14:27:09 -07001335 nes_read_1G_phy_reg(nesdev, 9, phy_index, &phy_data);
1336 nes_write_1G_phy_reg(nesdev, 9, phy_index, phy_data & ~(0x0100));
1337 nes_read_1G_phy_reg(nesdev, 9, phy_index, &phy_data);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001338
Chien Tung1b949322009-04-08 14:27:09 -07001339 nes_read_1G_phy_reg(nesdev, 0, phy_index, &phy_data);
1340 nes_write_1G_phy_reg(nesdev, 0, phy_index, phy_data | 0x0300);
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001341
Chien Tung1b949322009-04-08 14:27:09 -07001342 return 0;
1343 }
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001344
Chien Tung1b949322009-04-08 14:27:09 -07001345 if ((phy_type == NES_PHY_TYPE_IRIS) ||
Chien Tung43035652009-04-08 14:27:56 -07001346 (phy_type == NES_PHY_TYPE_ARGUS) ||
1347 (phy_type == NES_PHY_TYPE_SFP_D)) {
Chien Tung1b949322009-04-08 14:27:09 -07001348 /* setup 10G MDIO operation */
1349 tx_config = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG);
1350 tx_config &= 0xFFFFFFE3;
1351 tx_config |= 0x15;
1352 nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config);
1353 }
Chien Tung43035652009-04-08 14:27:56 -07001354 if ((phy_type == NES_PHY_TYPE_ARGUS) ||
1355 (phy_type == NES_PHY_TYPE_SFP_D)) {
Chien Tung1b949322009-04-08 14:27:09 -07001356 /* Check firmware heartbeat */
1357 nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee);
1358 temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
1359 udelay(1500);
1360 nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee);
1361 temp_phy_data2 = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001362
Chien Tung1b949322009-04-08 14:27:09 -07001363 if (temp_phy_data != temp_phy_data2)
1364 return 0;
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001365
Chien Tung1b949322009-04-08 14:27:09 -07001366 /* no heartbeat, configure the PHY */
1367 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0x0000, 0x8000);
1368 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc300, 0x0000);
Chien Tung1b949322009-04-08 14:27:09 -07001369 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc316, 0x000A);
1370 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc318, 0x0052);
Chien Tung43035652009-04-08 14:27:56 -07001371 if (phy_type == NES_PHY_TYPE_ARGUS) {
1372 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc302, 0x000C);
1373 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc319, 0x0008);
1374 } else {
1375 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc302, 0x0004);
1376 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc319, 0x0038);
1377 }
Chien Tung1b949322009-04-08 14:27:09 -07001378 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc31a, 0x0098);
1379 nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0026, 0x0E00);
1380 nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0027, 0x0001);
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001381
Chien Tung1b949322009-04-08 14:27:09 -07001382 /* setup LEDs */
1383 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd006, 0x0007);
1384 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd007, 0x000A);
1385 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd008, 0x0009);
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001386
Chien Tung1b949322009-04-08 14:27:09 -07001387 nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0028, 0xA528);
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001388
Chien Tung1b949322009-04-08 14:27:09 -07001389 /* Bring PHY out of reset */
1390 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc300, 0x0002);
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001391
Chien Tung1b949322009-04-08 14:27:09 -07001392 /* Check for heartbeat */
1393 counter = 0;
1394 mdelay(690);
1395 nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee);
1396 temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
1397 do {
1398 if (counter++ > 150) {
1399 nes_debug(NES_DBG_PHY, "No PHY heartbeat\n");
1400 break;
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001401 }
Chien Tung1b949322009-04-08 14:27:09 -07001402 mdelay(1);
1403 nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee);
1404 temp_phy_data2 = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
1405 } while ((temp_phy_data2 == temp_phy_data));
1406
1407 /* wait for tracking */
1408 counter = 0;
1409 do {
1410 nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7fd);
1411 temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
1412 if (counter++ > 300) {
1413 nes_debug(NES_DBG_PHY, "PHY did not track\n");
1414 break;
1415 }
1416 mdelay(10);
1417 } while (((temp_phy_data & 0xff) != 0x50) && ((temp_phy_data & 0xff) != 0x70));
1418
1419 /* setup signal integrity */
1420 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd003, 0x0000);
1421 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xF00D, 0x00FE);
1422 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xF00E, 0x0032);
1423 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xF00F, 0x0002);
1424 nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc314, 0x0063);
1425
1426 /* reset serdes */
1427 sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0 +
1428 mac_index * 0x200);
1429 sds |= 0x1;
1430 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0 +
1431 mac_index * 0x200, sds);
1432 sds &= 0xfffffffe;
1433 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0 +
1434 mac_index * 0x200, sds);
1435
1436 counter = 0;
1437 while (((nes_read32(nesdev->regs + NES_SOFTWARE_RESET) & 0x00000040) != 0x00000040)
1438 && (counter++ < 5000))
1439 ;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001440 }
1441 return 0;
1442}
1443
1444
1445/**
1446 * nes_replenish_nic_rq
1447 */
1448static void nes_replenish_nic_rq(struct nes_vnic *nesvnic)
1449{
1450 unsigned long flags;
1451 dma_addr_t bus_address;
1452 struct sk_buff *skb;
1453 struct nes_hw_nic_rq_wqe *nic_rqe;
1454 struct nes_hw_nic *nesnic;
1455 struct nes_device *nesdev;
1456 u32 rx_wqes_posted = 0;
1457
1458 nesnic = &nesvnic->nic;
1459 nesdev = nesvnic->nesdev;
1460 spin_lock_irqsave(&nesnic->rq_lock, flags);
1461 if (nesnic->replenishing_rq !=0) {
1462 if (((nesnic->rq_size-1) == atomic_read(&nesvnic->rx_skbs_needed)) &&
1463 (atomic_read(&nesvnic->rx_skb_timer_running) == 0)) {
1464 atomic_set(&nesvnic->rx_skb_timer_running, 1);
1465 spin_unlock_irqrestore(&nesnic->rq_lock, flags);
1466 nesvnic->rq_wqes_timer.expires = jiffies + (HZ/2); /* 1/2 second */
1467 add_timer(&nesvnic->rq_wqes_timer);
1468 } else
1469 spin_unlock_irqrestore(&nesnic->rq_lock, flags);
1470 return;
1471 }
1472 nesnic->replenishing_rq = 1;
1473 spin_unlock_irqrestore(&nesnic->rq_lock, flags);
1474 do {
1475 skb = dev_alloc_skb(nesvnic->max_frame_size);
1476 if (skb) {
1477 skb->dev = nesvnic->netdev;
1478
1479 bus_address = pci_map_single(nesdev->pcidev,
1480 skb->data, nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
1481
1482 nic_rqe = &nesnic->rq_vbase[nesvnic->nic.rq_head];
1483 nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] =
1484 cpu_to_le32(nesvnic->max_frame_size);
1485 nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_3_2_IDX] = 0;
1486 nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX] =
1487 cpu_to_le32((u32)bus_address);
1488 nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX] =
1489 cpu_to_le32((u32)((u64)bus_address >> 32));
1490 nesnic->rx_skb[nesnic->rq_head] = skb;
1491 nesnic->rq_head++;
1492 nesnic->rq_head &= nesnic->rq_size - 1;
1493 atomic_dec(&nesvnic->rx_skbs_needed);
1494 barrier();
1495 if (++rx_wqes_posted == 255) {
1496 nes_write32(nesdev->regs+NES_WQE_ALLOC, (rx_wqes_posted << 24) | nesnic->qp_id);
1497 rx_wqes_posted = 0;
1498 }
1499 } else {
1500 spin_lock_irqsave(&nesnic->rq_lock, flags);
1501 if (((nesnic->rq_size-1) == atomic_read(&nesvnic->rx_skbs_needed)) &&
1502 (atomic_read(&nesvnic->rx_skb_timer_running) == 0)) {
1503 atomic_set(&nesvnic->rx_skb_timer_running, 1);
1504 spin_unlock_irqrestore(&nesnic->rq_lock, flags);
1505 nesvnic->rq_wqes_timer.expires = jiffies + (HZ/2); /* 1/2 second */
1506 add_timer(&nesvnic->rq_wqes_timer);
1507 } else
1508 spin_unlock_irqrestore(&nesnic->rq_lock, flags);
1509 break;
1510 }
1511 } while (atomic_read(&nesvnic->rx_skbs_needed));
1512 barrier();
1513 if (rx_wqes_posted)
1514 nes_write32(nesdev->regs+NES_WQE_ALLOC, (rx_wqes_posted << 24) | nesnic->qp_id);
1515 nesnic->replenishing_rq = 0;
1516}
1517
1518
1519/**
1520 * nes_rq_wqes_timeout
1521 */
1522static void nes_rq_wqes_timeout(unsigned long parm)
1523{
1524 struct nes_vnic *nesvnic = (struct nes_vnic *)parm;
Harvey Harrison33718362008-04-16 21:01:10 -07001525 printk("%s: Timer fired.\n", __func__);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001526 atomic_set(&nesvnic->rx_skb_timer_running, 0);
1527 if (atomic_read(&nesvnic->rx_skbs_needed))
1528 nes_replenish_nic_rq(nesvnic);
1529}
1530
1531
Faisal Latif37dab412008-04-29 13:46:54 -07001532static int nes_lro_get_skb_hdr(struct sk_buff *skb, void **iphdr,
1533 void **tcph, u64 *hdr_flags, void *priv)
1534{
1535 unsigned int ip_len;
1536 struct iphdr *iph;
1537 skb_reset_network_header(skb);
1538 iph = ip_hdr(skb);
1539 if (iph->protocol != IPPROTO_TCP)
1540 return -1;
1541 ip_len = ip_hdrlen(skb);
1542 skb_set_transport_header(skb, ip_len);
1543 *tcph = tcp_hdr(skb);
1544
1545 *hdr_flags = LRO_IPV4 | LRO_TCP;
1546 *iphdr = iph;
1547 return 0;
1548}
1549
1550
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001551/**
1552 * nes_init_nic_qp
1553 */
1554int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
1555{
1556 struct nes_hw_cqp_wqe *cqp_wqe;
1557 struct nes_hw_nic_sq_wqe *nic_sqe;
1558 struct nes_hw_nic_qp_context *nic_context;
1559 struct sk_buff *skb;
1560 struct nes_hw_nic_rq_wqe *nic_rqe;
1561 struct nes_vnic *nesvnic = netdev_priv(netdev);
1562 unsigned long flags;
1563 void *vmem;
1564 dma_addr_t pmem;
1565 u64 u64temp;
1566 int ret;
1567 u32 cqp_head;
1568 u32 counter;
1569 u32 wqe_count;
1570 u8 jumbomode=0;
1571
1572 /* Allocate fragment, SQ, RQ, and CQ; Reuse CEQ based on the PCI function */
1573 nesvnic->nic_mem_size = 256 +
1574 (NES_NIC_WQ_SIZE * sizeof(struct nes_first_frag)) +
1575 (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_sq_wqe)) +
1576 (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_rq_wqe)) +
1577 (NES_NIC_WQ_SIZE * 2 * sizeof(struct nes_hw_nic_cqe)) +
1578 sizeof(struct nes_hw_nic_qp_context);
1579
1580 nesvnic->nic_vbase = pci_alloc_consistent(nesdev->pcidev, nesvnic->nic_mem_size,
1581 &nesvnic->nic_pbase);
1582 if (!nesvnic->nic_vbase) {
1583 nes_debug(NES_DBG_INIT, "Unable to allocate memory for NIC host descriptor rings\n");
1584 return -ENOMEM;
1585 }
1586 memset(nesvnic->nic_vbase, 0, nesvnic->nic_mem_size);
1587 nes_debug(NES_DBG_INIT, "Allocated NIC QP structures at %p (phys = %016lX), size = %u.\n",
1588 nesvnic->nic_vbase, (unsigned long)nesvnic->nic_pbase, nesvnic->nic_mem_size);
1589
1590 vmem = (void *)(((unsigned long)nesvnic->nic_vbase + (256 - 1)) &
1591 ~(unsigned long)(256 - 1));
1592 pmem = (dma_addr_t)(((unsigned long long)nesvnic->nic_pbase + (256 - 1)) &
1593 ~(unsigned long long)(256 - 1));
1594
1595 /* Setup the first Fragment buffers */
1596 nesvnic->nic.first_frag_vbase = vmem;
1597
1598 for (counter = 0; counter < NES_NIC_WQ_SIZE; counter++) {
1599 nesvnic->nic.frag_paddr[counter] = pmem;
1600 pmem += sizeof(struct nes_first_frag);
1601 }
1602
1603 /* setup the SQ */
1604 vmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_first_frag));
1605
1606 nesvnic->nic.sq_vbase = (void *)vmem;
1607 nesvnic->nic.sq_pbase = pmem;
1608 nesvnic->nic.sq_head = 0;
1609 nesvnic->nic.sq_tail = 0;
1610 nesvnic->nic.sq_size = NES_NIC_WQ_SIZE;
1611 for (counter = 0; counter < NES_NIC_WQ_SIZE; counter++) {
1612 nic_sqe = &nesvnic->nic.sq_vbase[counter];
1613 nic_sqe->wqe_words[NES_NIC_SQ_WQE_MISC_IDX] =
1614 cpu_to_le32(NES_NIC_SQ_WQE_DISABLE_CHKSUM |
1615 NES_NIC_SQ_WQE_COMPLETION);
1616 nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX] =
1617 cpu_to_le32((u32)NES_FIRST_FRAG_SIZE << 16);
1618 nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX] =
1619 cpu_to_le32((u32)nesvnic->nic.frag_paddr[counter]);
1620 nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX] =
1621 cpu_to_le32((u32)((u64)nesvnic->nic.frag_paddr[counter] >> 32));
1622 }
1623
1624 nesvnic->get_cqp_request = nes_get_cqp_request;
1625 nesvnic->post_cqp_request = nes_post_cqp_request;
1626 nesvnic->mcrq_mcast_filter = NULL;
1627
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001628 spin_lock_init(&nesvnic->nic.rq_lock);
1629
1630 /* setup the RQ */
1631 vmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_sq_wqe));
1632 pmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_sq_wqe));
1633
1634
1635 nesvnic->nic.rq_vbase = vmem;
1636 nesvnic->nic.rq_pbase = pmem;
1637 nesvnic->nic.rq_head = 0;
1638 nesvnic->nic.rq_tail = 0;
1639 nesvnic->nic.rq_size = NES_NIC_WQ_SIZE;
1640
1641 /* setup the CQ */
1642 vmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_rq_wqe));
1643 pmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_rq_wqe));
1644
1645 if (nesdev->nesadapter->netdev_count > 2)
1646 nesvnic->mcrq_qp_id = nesvnic->nic_index + 32;
1647 else
1648 nesvnic->mcrq_qp_id = nesvnic->nic.qp_id + 4;
1649
1650 nesvnic->nic_cq.cq_vbase = vmem;
1651 nesvnic->nic_cq.cq_pbase = pmem;
1652 nesvnic->nic_cq.cq_head = 0;
1653 nesvnic->nic_cq.cq_size = NES_NIC_WQ_SIZE * 2;
1654
1655 nesvnic->nic_cq.ce_handler = nes_nic_napi_ce_handler;
1656
1657 /* Send CreateCQ request to CQP */
1658 spin_lock_irqsave(&nesdev->cqp.lock, flags);
1659 cqp_head = nesdev->cqp.sq_head;
1660
1661 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1662 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
1663
1664 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(
1665 NES_CQP_CREATE_CQ | NES_CQP_CQ_CEQ_VALID |
1666 ((u32)nesvnic->nic_cq.cq_size << 16));
1667 cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(
1668 nesvnic->nic_cq.cq_number | ((u32)nesdev->nic_ceq_index << 16));
1669 u64temp = (u64)nesvnic->nic_cq.cq_pbase;
1670 set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);
1671 cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] = 0;
1672 u64temp = (unsigned long)&nesvnic->nic_cq;
1673 cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_LOW_IDX] = cpu_to_le32((u32)(u64temp >> 1));
1674 cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] =
1675 cpu_to_le32(((u32)((u64temp) >> 33)) & 0x7FFFFFFF);
1676 cqp_wqe->wqe_words[NES_CQP_CQ_WQE_DOORBELL_INDEX_HIGH_IDX] = 0;
1677 if (++cqp_head >= nesdev->cqp.sq_size)
1678 cqp_head = 0;
1679 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1680 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
1681
1682 /* Send CreateQP request to CQP */
1683 nic_context = (void *)(&nesvnic->nic_cq.cq_vbase[nesvnic->nic_cq.cq_size]);
1684 nic_context->context_words[NES_NIC_CTX_MISC_IDX] =
1685 cpu_to_le32((u32)NES_NIC_CTX_SIZE |
1686 ((u32)PCI_FUNC(nesdev->pcidev->devfn) << 12));
1687 nes_debug(NES_DBG_INIT, "RX_WINDOW_BUFFER_PAGE_TABLE_SIZE = 0x%08X, RX_WINDOW_BUFFER_SIZE = 0x%08X\n",
1688 nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_PAGE_TABLE_SIZE),
1689 nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_SIZE));
1690 if (nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_SIZE) != 0) {
1691 nic_context->context_words[NES_NIC_CTX_MISC_IDX] |= cpu_to_le32(NES_NIC_BACK_STORE);
1692 }
1693
1694 u64temp = (u64)nesvnic->nic.sq_pbase;
Glenn Streiff7495ab62008-04-29 13:46:54 -07001695 nic_context->context_words[NES_NIC_CTX_SQ_LOW_IDX] = cpu_to_le32((u32)u64temp);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001696 nic_context->context_words[NES_NIC_CTX_SQ_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32));
1697 u64temp = (u64)nesvnic->nic.rq_pbase;
Glenn Streiff7495ab62008-04-29 13:46:54 -07001698 nic_context->context_words[NES_NIC_CTX_RQ_LOW_IDX] = cpu_to_le32((u32)u64temp);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001699 nic_context->context_words[NES_NIC_CTX_RQ_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32));
1700
1701 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_CREATE_QP |
1702 NES_CQP_QP_TYPE_NIC);
1703 cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesvnic->nic.qp_id);
1704 u64temp = (u64)nesvnic->nic_cq.cq_pbase +
1705 (nesvnic->nic_cq.cq_size * sizeof(struct nes_hw_nic_cqe));
1706 set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, u64temp);
1707
1708 if (++cqp_head >= nesdev->cqp.sq_size)
1709 cqp_head = 0;
1710 nesdev->cqp.sq_head = cqp_head;
1711
1712 barrier();
1713
1714 /* Ring doorbell (2 WQEs) */
1715 nes_write32(nesdev->regs+NES_WQE_ALLOC, 0x02800000 | nesdev->cqp.qp_id);
1716
1717 spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
1718 nes_debug(NES_DBG_INIT, "Waiting for create NIC QP%u to complete.\n",
1719 nesvnic->nic.qp_id);
1720
1721 ret = wait_event_timeout(nesdev->cqp.waitq, (nesdev->cqp.sq_tail == cqp_head),
1722 NES_EVENT_TIMEOUT);
1723 nes_debug(NES_DBG_INIT, "Create NIC QP%u completed, wait_event_timeout ret = %u.\n",
1724 nesvnic->nic.qp_id, ret);
1725 if (!ret) {
1726 nes_debug(NES_DBG_INIT, "NIC QP%u create timeout expired\n", nesvnic->nic.qp_id);
1727 pci_free_consistent(nesdev->pcidev, nesvnic->nic_mem_size, nesvnic->nic_vbase,
1728 nesvnic->nic_pbase);
1729 return -EIO;
1730 }
1731
1732 /* Populate the RQ */
1733 for (counter = 0; counter < (NES_NIC_WQ_SIZE - 1); counter++) {
1734 skb = dev_alloc_skb(nesvnic->max_frame_size);
1735 if (!skb) {
1736 nes_debug(NES_DBG_INIT, "%s: out of memory for receive skb\n", netdev->name);
1737
1738 nes_destroy_nic_qp(nesvnic);
1739 return -ENOMEM;
1740 }
1741
1742 skb->dev = netdev;
1743
1744 pmem = pci_map_single(nesdev->pcidev, skb->data,
1745 nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
1746
1747 nic_rqe = &nesvnic->nic.rq_vbase[counter];
1748 nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] = cpu_to_le32(nesvnic->max_frame_size);
1749 nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_3_2_IDX] = 0;
Glenn Streiff7495ab62008-04-29 13:46:54 -07001750 nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX] = cpu_to_le32((u32)pmem);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001751 nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX] = cpu_to_le32((u32)((u64)pmem >> 32));
1752 nesvnic->nic.rx_skb[counter] = skb;
1753 }
1754
1755 wqe_count = NES_NIC_WQ_SIZE - 1;
1756 nesvnic->nic.rq_head = wqe_count;
1757 barrier();
1758 do {
1759 counter = min(wqe_count, ((u32)255));
1760 wqe_count -= counter;
1761 nes_write32(nesdev->regs+NES_WQE_ALLOC, (counter << 24) | nesvnic->nic.qp_id);
1762 } while (wqe_count);
1763 init_timer(&nesvnic->rq_wqes_timer);
1764 nesvnic->rq_wqes_timer.function = nes_rq_wqes_timeout;
1765 nesvnic->rq_wqes_timer.data = (unsigned long)nesvnic;
1766 nes_debug(NES_DBG_INIT, "NAPI support Enabled\n");
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001767 if (nesdev->nesadapter->et_use_adaptive_rx_coalesce)
1768 {
1769 nes_nic_init_timer(nesdev);
1770 if (netdev->mtu > 1500)
1771 jumbomode = 1;
Faisal Latif37dab412008-04-29 13:46:54 -07001772 nes_nic_init_timer_defaults(nesdev, jumbomode);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001773 }
Roland Dreierdd378182008-05-13 11:27:25 -07001774 nesvnic->lro_mgr.max_aggr = nes_lro_max_aggr;
Glenn Streiff7495ab62008-04-29 13:46:54 -07001775 nesvnic->lro_mgr.max_desc = NES_MAX_LRO_DESCRIPTORS;
1776 nesvnic->lro_mgr.lro_arr = nesvnic->lro_desc;
Faisal Latif37dab412008-04-29 13:46:54 -07001777 nesvnic->lro_mgr.get_skb_header = nes_lro_get_skb_hdr;
Glenn Streiff7495ab62008-04-29 13:46:54 -07001778 nesvnic->lro_mgr.features = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID;
1779 nesvnic->lro_mgr.dev = netdev;
1780 nesvnic->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY;
Faisal Latif37dab412008-04-29 13:46:54 -07001781 nesvnic->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001782 return 0;
1783}
1784
1785
1786/**
1787 * nes_destroy_nic_qp
1788 */
1789void nes_destroy_nic_qp(struct nes_vnic *nesvnic)
1790{
Bob Sharp7a8d1402008-09-26 15:08:10 -05001791 u64 u64temp;
1792 dma_addr_t bus_address;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001793 struct nes_device *nesdev = nesvnic->nesdev;
1794 struct nes_hw_cqp_wqe *cqp_wqe;
Bob Sharp7a8d1402008-09-26 15:08:10 -05001795 struct nes_hw_nic_sq_wqe *nic_sqe;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001796 struct nes_hw_nic_rq_wqe *nic_rqe;
Bob Sharp7a8d1402008-09-26 15:08:10 -05001797 __le16 *wqe_fragment_length;
1798 u16 wqe_fragment_index;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001799 u64 wqe_frag;
1800 u32 cqp_head;
1801 unsigned long flags;
1802 int ret;
1803
1804 /* Free remaining NIC receive buffers */
1805 while (nesvnic->nic.rq_head != nesvnic->nic.rq_tail) {
Glenn Streiff7495ab62008-04-29 13:46:54 -07001806 nic_rqe = &nesvnic->nic.rq_vbase[nesvnic->nic.rq_tail];
Bob Sharp7a8d1402008-09-26 15:08:10 -05001807 wqe_frag = (u64)le32_to_cpu(
1808 nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]);
1809 wqe_frag |= ((u64)le32_to_cpu(
1810 nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX]))<<32;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001811 pci_unmap_single(nesdev->pcidev, (dma_addr_t)wqe_frag,
1812 nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
1813 dev_kfree_skb(nesvnic->nic.rx_skb[nesvnic->nic.rq_tail++]);
1814 nesvnic->nic.rq_tail &= (nesvnic->nic.rq_size - 1);
1815 }
1816
Bob Sharp7a8d1402008-09-26 15:08:10 -05001817 /* Free remaining NIC transmit buffers */
1818 while (nesvnic->nic.sq_head != nesvnic->nic.sq_tail) {
1819 nic_sqe = &nesvnic->nic.sq_vbase[nesvnic->nic.sq_tail];
1820 wqe_fragment_index = 1;
1821 wqe_fragment_length = (__le16 *)
1822 &nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX];
1823 /* bump past the vlan tag */
1824 wqe_fragment_length++;
1825 if (le16_to_cpu(wqe_fragment_length[wqe_fragment_index]) != 0) {
1826 u64temp = (u64)le32_to_cpu(
1827 nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX+
1828 wqe_fragment_index*2]);
1829 u64temp += ((u64)le32_to_cpu(
1830 nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX
1831 + wqe_fragment_index*2]))<<32;
1832 bus_address = (dma_addr_t)u64temp;
1833 if (test_and_clear_bit(nesvnic->nic.sq_tail,
1834 nesvnic->nic.first_frag_overflow)) {
1835 pci_unmap_single(nesdev->pcidev,
1836 bus_address,
1837 le16_to_cpu(wqe_fragment_length[
1838 wqe_fragment_index++]),
1839 PCI_DMA_TODEVICE);
1840 }
1841 for (; wqe_fragment_index < 5; wqe_fragment_index++) {
1842 if (wqe_fragment_length[wqe_fragment_index]) {
1843 u64temp = le32_to_cpu(
1844 nic_sqe->wqe_words[
1845 NES_NIC_SQ_WQE_FRAG0_LOW_IDX+
1846 wqe_fragment_index*2]);
1847 u64temp += ((u64)le32_to_cpu(
1848 nic_sqe->wqe_words[
1849 NES_NIC_SQ_WQE_FRAG0_HIGH_IDX+
1850 wqe_fragment_index*2]))<<32;
1851 bus_address = (dma_addr_t)u64temp;
1852 pci_unmap_page(nesdev->pcidev,
1853 bus_address,
1854 le16_to_cpu(
1855 wqe_fragment_length[
1856 wqe_fragment_index]),
1857 PCI_DMA_TODEVICE);
1858 } else
1859 break;
1860 }
1861 }
1862 if (nesvnic->nic.tx_skb[nesvnic->nic.sq_tail])
1863 dev_kfree_skb(
1864 nesvnic->nic.tx_skb[nesvnic->nic.sq_tail]);
1865
1866 nesvnic->nic.sq_tail = (++nesvnic->nic.sq_tail)
1867 & (nesvnic->nic.sq_size - 1);
1868 }
1869
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001870 spin_lock_irqsave(&nesdev->cqp.lock, flags);
1871
1872 /* Destroy NIC QP */
1873 cqp_head = nesdev->cqp.sq_head;
1874 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1875 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
1876
1877 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
1878 (NES_CQP_DESTROY_QP | NES_CQP_QP_TYPE_NIC));
1879 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,
1880 nesvnic->nic.qp_id);
1881
1882 if (++cqp_head >= nesdev->cqp.sq_size)
1883 cqp_head = 0;
1884
1885 cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
1886
1887 /* Destroy NIC CQ */
1888 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
1889 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
1890 (NES_CQP_DESTROY_CQ | ((u32)nesvnic->nic_cq.cq_size << 16)));
1891 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,
1892 (nesvnic->nic_cq.cq_number | ((u32)nesdev->nic_ceq_index << 16)));
1893
1894 if (++cqp_head >= nesdev->cqp.sq_size)
1895 cqp_head = 0;
1896
1897 nesdev->cqp.sq_head = cqp_head;
1898 barrier();
1899
1900 /* Ring doorbell (2 WQEs) */
1901 nes_write32(nesdev->regs+NES_WQE_ALLOC, 0x02800000 | nesdev->cqp.qp_id);
1902
1903 spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
1904 nes_debug(NES_DBG_SHUTDOWN, "Waiting for CQP, cqp_head=%u, cqp.sq_head=%u,"
1905 " cqp.sq_tail=%u, cqp.sq_size=%u\n",
1906 cqp_head, nesdev->cqp.sq_head,
1907 nesdev->cqp.sq_tail, nesdev->cqp.sq_size);
1908
1909 ret = wait_event_timeout(nesdev->cqp.waitq, (nesdev->cqp.sq_tail == cqp_head),
1910 NES_EVENT_TIMEOUT);
1911
1912 nes_debug(NES_DBG_SHUTDOWN, "Destroy NIC QP returned, wait_event_timeout ret = %u, cqp_head=%u,"
1913 " cqp.sq_head=%u, cqp.sq_tail=%u\n",
1914 ret, cqp_head, nesdev->cqp.sq_head, nesdev->cqp.sq_tail);
1915 if (!ret) {
1916 nes_debug(NES_DBG_SHUTDOWN, "NIC QP%u destroy timeout expired\n",
1917 nesvnic->nic.qp_id);
1918 }
1919
1920 pci_free_consistent(nesdev->pcidev, nesvnic->nic_mem_size, nesvnic->nic_vbase,
1921 nesvnic->nic_pbase);
1922}
1923
1924/**
1925 * nes_napi_isr
1926 */
1927int nes_napi_isr(struct nes_device *nesdev)
1928{
1929 struct nes_adapter *nesadapter = nesdev->nesadapter;
1930 u32 int_stat;
1931
1932 if (nesdev->napi_isr_ran) {
1933 /* interrupt status has already been read in ISR */
1934 int_stat = nesdev->int_stat;
1935 } else {
1936 int_stat = nes_read32(nesdev->regs + NES_INT_STAT);
1937 nesdev->int_stat = int_stat;
1938 nesdev->napi_isr_ran = 1;
1939 }
1940
1941 int_stat &= nesdev->int_req;
1942 /* iff NIC, process here, else wait for DPC */
1943 if ((int_stat) && ((int_stat & 0x0000ff00) == int_stat)) {
1944 nesdev->napi_isr_ran = 0;
Glenn Streiff7495ab62008-04-29 13:46:54 -07001945 nes_write32(nesdev->regs + NES_INT_STAT,
1946 (int_stat &
1947 ~(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 -08001948
1949 /* Process the CEQs */
1950 nes_process_ceq(nesdev, &nesdev->nesadapter->ceq[nesdev->nic_ceq_index]);
1951
1952 if (unlikely((((nesadapter->et_rx_coalesce_usecs_irq) &&
Glenn Streiff7495ab62008-04-29 13:46:54 -07001953 (!nesadapter->et_use_adaptive_rx_coalesce)) ||
1954 ((nesadapter->et_use_adaptive_rx_coalesce) &&
1955 (nesdev->deepcq_count > nesadapter->et_pkt_rate_low))))) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001956 if ((nesdev->int_req & NES_INT_TIMER) == 0) {
1957 /* Enable Periodic timer interrupts */
1958 nesdev->int_req |= NES_INT_TIMER;
1959 /* ack any pending periodic timer interrupts so we don't get an immediate interrupt */
1960 /* TODO: need to also ack other unused periodic timer values, get from nesadapter */
1961 nes_write32(nesdev->regs+NES_TIMER_STAT,
1962 nesdev->timer_int_req | ~(nesdev->nesadapter->timer_int_req));
1963 nes_write32(nesdev->regs+NES_INTF_INT_MASK,
1964 ~(nesdev->intf_int_req | NES_INTF_PERIODIC_TIMER));
1965 }
1966
1967 if (unlikely(nesadapter->et_use_adaptive_rx_coalesce))
1968 {
1969 nes_nic_init_timer(nesdev);
1970 }
1971 /* Enable interrupts, except CEQs */
1972 nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff | (~nesdev->int_req));
1973 } else {
1974 /* Enable interrupts, make sure timer is off */
1975 nesdev->int_req &= ~NES_INT_TIMER;
1976 nes_write32(nesdev->regs+NES_INTF_INT_MASK, ~(nesdev->intf_int_req));
1977 nes_write32(nesdev->regs+NES_INT_MASK, ~nesdev->int_req);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001978 }
1979 nesdev->deepcq_count = 0;
1980 return 1;
1981 } else {
1982 return 0;
1983 }
1984}
1985
Chien Tung9d156942008-09-26 15:08:10 -05001986static void process_critical_error(struct nes_device *nesdev)
1987{
1988 u32 debug_error;
1989 u32 nes_idx_debug_error_masks0 = 0;
1990 u16 error_module = 0;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001991
Chien Tung9d156942008-09-26 15:08:10 -05001992 debug_error = nes_read_indexed(nesdev, NES_IDX_DEBUG_ERROR_CONTROL_STATUS);
1993 printk(KERN_ERR PFX "Critical Error reported by device!!! 0x%02X\n",
1994 (u16)debug_error);
1995 nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_CONTROL_STATUS,
1996 0x01010000 | (debug_error & 0x0000ffff));
1997 if (crit_err_count++ > 10)
1998 nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS1, 1 << 0x17);
Chien Tunge2f5e732008-10-08 14:43:29 -07001999 error_module = (u16) (debug_error & 0x1F00) >> 8;
Chien Tung9d156942008-09-26 15:08:10 -05002000 if (++nesdev->nesadapter->crit_error_count[error_module-1] >=
2001 nes_max_critical_error_count) {
2002 printk(KERN_ERR PFX "Masking off critical error for module "
2003 "0x%02X\n", (u16)error_module);
2004 nes_idx_debug_error_masks0 = nes_read_indexed(nesdev,
2005 NES_IDX_DEBUG_ERROR_MASKS0);
2006 nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS0,
2007 nes_idx_debug_error_masks0 | (1 << error_module));
2008 }
2009}
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002010/**
2011 * nes_dpc
2012 */
2013void nes_dpc(unsigned long param)
2014{
2015 struct nes_device *nesdev = (struct nes_device *)param;
2016 struct nes_adapter *nesadapter = nesdev->nesadapter;
2017 u32 counter;
2018 u32 loop_counter = 0;
2019 u32 int_status_bit;
2020 u32 int_stat;
2021 u32 timer_stat;
2022 u32 temp_int_stat;
2023 u32 intf_int_stat;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002024 u32 processed_intf_int = 0;
2025 u16 processed_timer_int = 0;
2026 u16 completion_ints = 0;
2027 u16 timer_ints = 0;
2028
2029 /* nes_debug(NES_DBG_ISR, "\n"); */
2030
2031 do {
2032 timer_stat = 0;
2033 if (nesdev->napi_isr_ran) {
2034 nesdev->napi_isr_ran = 0;
2035 int_stat = nesdev->int_stat;
2036 } else
2037 int_stat = nes_read32(nesdev->regs+NES_INT_STAT);
2038 if (processed_intf_int != 0)
2039 int_stat &= nesdev->int_req & ~NES_INT_INTF;
2040 else
2041 int_stat &= nesdev->int_req;
2042 if (processed_timer_int == 0) {
2043 processed_timer_int = 1;
2044 if (int_stat & NES_INT_TIMER) {
2045 timer_stat = nes_read32(nesdev->regs + NES_TIMER_STAT);
2046 if ((timer_stat & nesdev->timer_int_req) == 0) {
2047 int_stat &= ~NES_INT_TIMER;
2048 }
2049 }
2050 } else {
2051 int_stat &= ~NES_INT_TIMER;
2052 }
2053
2054 if (int_stat) {
Glenn Streiff7495ab62008-04-29 13:46:54 -07002055 if (int_stat & ~(NES_INT_INTF | NES_INT_TIMER | NES_INT_MAC0|
2056 NES_INT_MAC1|NES_INT_MAC2 | NES_INT_MAC3)) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002057 /* Ack the interrupts */
2058 nes_write32(nesdev->regs+NES_INT_STAT,
Glenn Streiff7495ab62008-04-29 13:46:54 -07002059 (int_stat & ~(NES_INT_INTF | NES_INT_TIMER | NES_INT_MAC0|
2060 NES_INT_MAC1 | NES_INT_MAC2 | NES_INT_MAC3)));
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002061 }
2062
2063 temp_int_stat = int_stat;
2064 for (counter = 0, int_status_bit = 1; counter < 16; counter++) {
2065 if (int_stat & int_status_bit) {
2066 nes_process_ceq(nesdev, &nesadapter->ceq[counter]);
2067 temp_int_stat &= ~int_status_bit;
2068 completion_ints = 1;
2069 }
2070 if (!(temp_int_stat & 0x0000ffff))
2071 break;
2072 int_status_bit <<= 1;
2073 }
2074
2075 /* Process the AEQ for this pci function */
2076 int_status_bit = 1 << (16 + PCI_FUNC(nesdev->pcidev->devfn));
2077 if (int_stat & int_status_bit) {
2078 nes_process_aeq(nesdev, &nesadapter->aeq[PCI_FUNC(nesdev->pcidev->devfn)]);
2079 }
2080
2081 /* Process the MAC interrupt for this pci function */
2082 int_status_bit = 1 << (24 + nesdev->mac_index);
2083 if (int_stat & int_status_bit) {
2084 nes_process_mac_intr(nesdev, nesdev->mac_index);
2085 }
2086
2087 if (int_stat & NES_INT_TIMER) {
2088 if (timer_stat & nesdev->timer_int_req) {
2089 nes_write32(nesdev->regs + NES_TIMER_STAT,
2090 (timer_stat & nesdev->timer_int_req) |
2091 ~(nesdev->nesadapter->timer_int_req));
2092 timer_ints = 1;
2093 }
2094 }
2095
2096 if (int_stat & NES_INT_INTF) {
2097 processed_intf_int = 1;
2098 intf_int_stat = nes_read32(nesdev->regs+NES_INTF_INT_STAT);
2099 intf_int_stat &= nesdev->intf_int_req;
2100 if (NES_INTF_INT_CRITERR & intf_int_stat) {
Chien Tung9d156942008-09-26 15:08:10 -05002101 process_critical_error(nesdev);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002102 }
2103 if (NES_INTF_INT_PCIERR & intf_int_stat) {
2104 printk(KERN_ERR PFX "PCI Error reported by device!!!\n");
2105 BUG();
2106 }
2107 if (NES_INTF_INT_AEQ_OFLOW & intf_int_stat) {
2108 printk(KERN_ERR PFX "AEQ Overflow reported by device!!!\n");
2109 BUG();
2110 }
2111 nes_write32(nesdev->regs+NES_INTF_INT_STAT, intf_int_stat);
2112 }
2113
2114 if (int_stat & NES_INT_TSW) {
2115 }
2116 }
2117 /* Don't use the interface interrupt bit stay in loop */
Glenn Streiff7495ab62008-04-29 13:46:54 -07002118 int_stat &= ~NES_INT_INTF | NES_INT_TIMER | NES_INT_MAC0 |
2119 NES_INT_MAC1 | NES_INT_MAC2 | NES_INT_MAC3;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002120 } while ((int_stat != 0) && (loop_counter++ < MAX_DPC_ITERATIONS));
2121
2122 if (timer_ints == 1) {
2123 if ((nesadapter->et_rx_coalesce_usecs_irq) || (nesadapter->et_use_adaptive_rx_coalesce)) {
2124 if (completion_ints == 0) {
2125 nesdev->timer_only_int_count++;
2126 if (nesdev->timer_only_int_count>=nesadapter->timer_int_limit) {
2127 nesdev->timer_only_int_count = 0;
2128 nesdev->int_req &= ~NES_INT_TIMER;
2129 nes_write32(nesdev->regs + NES_INTF_INT_MASK, ~(nesdev->intf_int_req));
Glenn Streiff7495ab62008-04-29 13:46:54 -07002130 nes_write32(nesdev->regs + NES_INT_MASK, ~nesdev->int_req);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002131 } else {
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 if (unlikely(nesadapter->et_use_adaptive_rx_coalesce))
2136 {
2137 nes_nic_init_timer(nesdev);
2138 }
2139 nesdev->timer_only_int_count = 0;
Glenn Streiff7495ab62008-04-29 13:46:54 -07002140 nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff | (~nesdev->int_req));
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002141 }
2142 } else {
2143 nesdev->timer_only_int_count = 0;
2144 nesdev->int_req &= ~NES_INT_TIMER;
2145 nes_write32(nesdev->regs+NES_INTF_INT_MASK, ~(nesdev->intf_int_req));
2146 nes_write32(nesdev->regs+NES_TIMER_STAT,
2147 nesdev->timer_int_req | ~(nesdev->nesadapter->timer_int_req));
2148 nes_write32(nesdev->regs+NES_INT_MASK, ~nesdev->int_req);
2149 }
2150 } else {
2151 if ( (completion_ints == 1) &&
2152 (((nesadapter->et_rx_coalesce_usecs_irq) &&
2153 (!nesadapter->et_use_adaptive_rx_coalesce)) ||
2154 ((nesdev->deepcq_count > nesadapter->et_pkt_rate_low) &&
2155 (nesadapter->et_use_adaptive_rx_coalesce) )) ) {
2156 /* nes_debug(NES_DBG_ISR, "Enabling periodic timer interrupt.\n" ); */
2157 nesdev->timer_only_int_count = 0;
2158 nesdev->int_req |= NES_INT_TIMER;
2159 nes_write32(nesdev->regs+NES_TIMER_STAT,
2160 nesdev->timer_int_req | ~(nesdev->nesadapter->timer_int_req));
2161 nes_write32(nesdev->regs+NES_INTF_INT_MASK,
2162 ~(nesdev->intf_int_req | NES_INTF_PERIODIC_TIMER));
2163 nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff | (~nesdev->int_req));
2164 } else {
2165 nes_write32(nesdev->regs+NES_INT_MASK, ~nesdev->int_req);
2166 }
2167 }
2168 nesdev->deepcq_count = 0;
2169}
2170
2171
2172/**
2173 * nes_process_ceq
2174 */
Roland Dreier1a855fbf2008-04-16 21:01:09 -07002175static void nes_process_ceq(struct nes_device *nesdev, struct nes_hw_ceq *ceq)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002176{
2177 u64 u64temp;
2178 struct nes_hw_cq *cq;
2179 u32 head;
2180 u32 ceq_size;
2181
2182 /* nes_debug(NES_DBG_CQ, "\n"); */
2183 head = ceq->ceq_head;
2184 ceq_size = ceq->ceq_size;
2185
2186 do {
2187 if (le32_to_cpu(ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_HIGH_IDX]) &
2188 NES_CEQE_VALID) {
Glenn Streiff7495ab62008-04-29 13:46:54 -07002189 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 -08002190 ((u64)(le32_to_cpu(ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_LOW_IDX])));
2191 u64temp <<= 1;
2192 cq = *((struct nes_hw_cq **)&u64temp);
2193 /* nes_debug(NES_DBG_CQ, "pCQ = %p\n", cq); */
2194 barrier();
2195 ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_HIGH_IDX] = 0;
2196
2197 /* call the event handler */
2198 cq->ce_handler(nesdev, cq);
2199
2200 if (++head >= ceq_size)
2201 head = 0;
2202 } else {
2203 break;
2204 }
2205
2206 } while (1);
2207
2208 ceq->ceq_head = head;
2209}
2210
2211
2212/**
2213 * nes_process_aeq
2214 */
Roland Dreier1a855fbf2008-04-16 21:01:09 -07002215static void nes_process_aeq(struct nes_device *nesdev, struct nes_hw_aeq *aeq)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002216{
Glenn Streiff7495ab62008-04-29 13:46:54 -07002217 /* u64 u64temp; */
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002218 u32 head;
2219 u32 aeq_size;
2220 u32 aeqe_misc;
2221 u32 aeqe_cq_id;
2222 struct nes_hw_aeqe volatile *aeqe;
2223
2224 head = aeq->aeq_head;
2225 aeq_size = aeq->aeq_size;
2226
2227 do {
2228 aeqe = &aeq->aeq_vbase[head];
2229 if ((le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]) & NES_AEQE_VALID) == 0)
2230 break;
2231 aeqe_misc = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]);
2232 aeqe_cq_id = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]);
2233 if (aeqe_misc & (NES_AEQE_QP|NES_AEQE_CQ)) {
2234 if (aeqe_cq_id >= NES_FIRST_QPN) {
2235 /* dealing with an accelerated QP related AE */
Glenn Streiff7495ab62008-04-29 13:46:54 -07002236 /*
2237 * u64temp = (((u64)(le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX]))) << 32) |
2238 * ((u64)(le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX])));
2239 */
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002240 nes_process_iwarp_aeqe(nesdev, (struct nes_hw_aeqe *)aeqe);
2241 } else {
2242 /* TODO: dealing with a CQP related AE */
2243 nes_debug(NES_DBG_AEQ, "Processing CQP related AE, misc = 0x%04X\n",
2244 (u16)(aeqe_misc >> 16));
2245 }
2246 }
2247
2248 aeqe->aeqe_words[NES_AEQE_MISC_IDX] = 0;
2249
2250 if (++head >= aeq_size)
2251 head = 0;
Don Woodfd877782009-03-06 15:12:11 -08002252
2253 nes_write32(nesdev->regs + NES_AEQ_ALLOC, 1 << 16);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002254 }
2255 while (1);
2256 aeq->aeq_head = head;
2257}
2258
2259static void nes_reset_link(struct nes_device *nesdev, u32 mac_index)
2260{
2261 struct nes_adapter *nesadapter = nesdev->nesadapter;
2262 u32 reset_value;
2263 u32 i=0;
2264 u32 u32temp;
2265
2266 if (nesadapter->hw_rev == NE020_REV) {
2267 return;
2268 }
2269 mh_detected++;
2270
2271 reset_value = nes_read32(nesdev->regs+NES_SOFTWARE_RESET);
2272
2273 if ((mac_index == 0) || ((mac_index == 1) && (nesadapter->OneG_Mode)))
2274 reset_value |= 0x0000001d;
2275 else
2276 reset_value |= 0x0000002d;
2277
2278 if (4 <= (nesadapter->link_interrupt_count[mac_index] / ((u16)NES_MAX_LINK_INTERRUPTS))) {
2279 if ((!nesadapter->OneG_Mode) && (nesadapter->port_count == 2)) {
2280 nesadapter->link_interrupt_count[0] = 0;
2281 nesadapter->link_interrupt_count[1] = 0;
2282 u32temp = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1);
2283 if (0x00000040 & u32temp)
2284 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F088);
2285 else
2286 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F0C8);
2287
2288 reset_value |= 0x0000003d;
2289 }
2290 nesadapter->link_interrupt_count[mac_index] = 0;
2291 }
2292
2293 nes_write32(nesdev->regs+NES_SOFTWARE_RESET, reset_value);
2294
2295 while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET)
2296 & 0x00000040) != 0x00000040) && (i++ < 5000));
2297
2298 if (0x0000003d == (reset_value & 0x0000003d)) {
2299 u32 pcs_control_status0, pcs_control_status1;
2300
2301 for (i = 0; i < 10; i++) {
2302 pcs_control_status0 = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0);
2303 pcs_control_status1 = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200);
2304 if (((0x0F000000 == (pcs_control_status0 & 0x0F000000))
2305 && (pcs_control_status0 & 0x00100000))
2306 || ((0x0F000000 == (pcs_control_status1 & 0x0F000000))
2307 && (pcs_control_status1 & 0x00100000)))
2308 continue;
2309 else
2310 break;
2311 }
2312 if (10 == i) {
2313 u32temp = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1);
2314 if (0x00000040 & u32temp)
2315 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F088);
2316 else
2317 nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F0C8);
2318
2319 nes_write32(nesdev->regs+NES_SOFTWARE_RESET, reset_value);
2320
2321 while (((nes_read32(nesdev->regs + NES_SOFTWARE_RESET)
2322 & 0x00000040) != 0x00000040) && (i++ < 5000));
2323 }
2324 }
2325}
2326
2327/**
2328 * nes_process_mac_intr
2329 */
Roland Dreier1a855fbf2008-04-16 21:01:09 -07002330static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002331{
2332 unsigned long flags;
2333 u32 pcs_control_status;
2334 struct nes_adapter *nesadapter = nesdev->nesadapter;
2335 struct nes_vnic *nesvnic;
2336 u32 mac_status;
2337 u32 mac_index = nesdev->mac_index;
2338 u32 u32temp;
2339 u16 phy_data;
2340 u16 temp_phy_data;
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002341 u32 pcs_val = 0x0f0f0000;
2342 u32 pcs_mask = 0x0f1f0000;
Chien Tunga4849fc2009-04-08 14:27:18 -07002343 u32 cdr_ctrl;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002344
2345 spin_lock_irqsave(&nesadapter->phy_lock, flags);
2346 if (nesadapter->mac_sw_state[mac_number] != NES_MAC_SW_IDLE) {
2347 spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
2348 return;
2349 }
2350 nesadapter->mac_sw_state[mac_number] = NES_MAC_SW_INTERRUPT;
2351 spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
2352
2353 /* ack the MAC interrupt */
2354 mac_status = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (mac_index * 0x200));
2355 /* Clear the interrupt */
2356 nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (mac_index * 0x200), mac_status);
2357
2358 nes_debug(NES_DBG_PHY, "MAC%u interrupt status = 0x%X.\n", mac_number, mac_status);
2359
2360 if (mac_status & (NES_MAC_INT_LINK_STAT_CHG | NES_MAC_INT_XGMII_EXT)) {
2361 nesdev->link_status_interrupts++;
2362 if (0 == (++nesadapter->link_interrupt_count[mac_index] % ((u16)NES_MAX_LINK_INTERRUPTS))) {
2363 spin_lock_irqsave(&nesadapter->phy_lock, flags);
2364 nes_reset_link(nesdev, mac_index);
2365 spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
2366 }
2367 /* read the PHY interrupt status register */
Chien Tungfcb7ad32008-09-30 14:49:44 -07002368 if ((nesadapter->OneG_Mode) &&
2369 (nesadapter->phy_type[mac_index] != NES_PHY_TYPE_PUMA_1G)) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002370 do {
2371 nes_read_1G_phy_reg(nesdev, 0x1a,
2372 nesadapter->phy_index[mac_index], &phy_data);
2373 nes_debug(NES_DBG_PHY, "Phy%d data from register 0x1a = 0x%X.\n",
2374 nesadapter->phy_index[mac_index], phy_data);
2375 } while (phy_data&0x8000);
2376
2377 temp_phy_data = 0;
2378 do {
2379 nes_read_1G_phy_reg(nesdev, 0x11,
2380 nesadapter->phy_index[mac_index], &phy_data);
2381 nes_debug(NES_DBG_PHY, "Phy%d data from register 0x11 = 0x%X.\n",
2382 nesadapter->phy_index[mac_index], phy_data);
2383 if (temp_phy_data == phy_data)
2384 break;
2385 temp_phy_data = phy_data;
2386 } while (1);
2387
2388 nes_read_1G_phy_reg(nesdev, 0x1e,
2389 nesadapter->phy_index[mac_index], &phy_data);
2390 nes_debug(NES_DBG_PHY, "Phy%d data from register 0x1e = 0x%X.\n",
2391 nesadapter->phy_index[mac_index], phy_data);
2392
2393 nes_read_1G_phy_reg(nesdev, 1,
2394 nesadapter->phy_index[mac_index], &phy_data);
2395 nes_debug(NES_DBG_PHY, "1G phy%u data from register 1 = 0x%X\n",
2396 nesadapter->phy_index[mac_index], phy_data);
2397
2398 if (temp_phy_data & 0x1000) {
2399 nes_debug(NES_DBG_PHY, "The Link is up according to the PHY\n");
2400 phy_data = 4;
2401 } else {
2402 nes_debug(NES_DBG_PHY, "The Link is down according to the PHY\n");
2403 }
2404 }
2405 nes_debug(NES_DBG_PHY, "Eth SERDES Common Status: 0=0x%08X, 1=0x%08X\n",
2406 nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0),
2407 nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0+0x200));
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002408
2409 if (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_PUMA_1G) {
2410 switch (mac_index) {
2411 case 1:
2412 case 3:
2413 pcs_control_status = nes_read_indexed(nesdev,
2414 NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200);
2415 break;
2416 default:
2417 pcs_control_status = nes_read_indexed(nesdev,
2418 NES_IDX_PHY_PCS_CONTROL_STATUS0);
2419 break;
2420 }
2421 } else {
2422 pcs_control_status = nes_read_indexed(nesdev,
2423 NES_IDX_PHY_PCS_CONTROL_STATUS0 + ((mac_index & 1) * 0x200));
2424 pcs_control_status = nes_read_indexed(nesdev,
2425 NES_IDX_PHY_PCS_CONTROL_STATUS0 + ((mac_index & 1) * 0x200));
2426 }
2427
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002428 nes_debug(NES_DBG_PHY, "PCS PHY Control/Status%u: 0x%08X\n",
2429 mac_index, pcs_control_status);
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002430 if ((nesadapter->OneG_Mode) &&
2431 (nesadapter->phy_type[mac_index] != NES_PHY_TYPE_PUMA_1G)) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002432 u32temp = 0x01010000;
2433 if (nesadapter->port_count > 2) {
2434 u32temp |= 0x02020000;
2435 }
2436 if ((pcs_control_status & u32temp)!= u32temp) {
2437 phy_data = 0;
2438 nes_debug(NES_DBG_PHY, "PCS says the link is down\n");
2439 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002440 } else {
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002441 switch (nesadapter->phy_type[mac_index]) {
2442 case NES_PHY_TYPE_IRIS:
2443 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 1);
2444 temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
2445 u32temp = 20;
2446 do {
2447 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 1);
2448 phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
2449 if ((phy_data == temp_phy_data) || (!(--u32temp)))
2450 break;
2451 temp_phy_data = phy_data;
2452 } while (1);
2453 nes_debug(NES_DBG_PHY, "%s: Phy data = 0x%04X, link was %s.\n",
2454 __func__, phy_data, nesadapter->mac_link_down[mac_index] ? "DOWN" : "UP");
2455 break;
2456
2457 case NES_PHY_TYPE_ARGUS:
Chien Tung43035652009-04-08 14:27:56 -07002458 case NES_PHY_TYPE_SFP_D:
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002459 /* clear the alarms */
2460 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0x0008);
2461 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0xc001);
2462 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0xc002);
2463 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0xc005);
2464 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0xc006);
2465 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9003);
2466 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9004);
2467 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9005);
2468 /* check link status */
Chien Tung1b949322009-04-08 14:27:09 -07002469 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9003);
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002470 temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002471
Chien Tung1b949322009-04-08 14:27:09 -07002472 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 3, 0x0021);
2473 nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
2474 nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 3, 0x0021);
2475 phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
2476
2477 phy_data = (!temp_phy_data && (phy_data == 0x8000)) ? 0x4 : 0x0;
2478
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002479 nes_debug(NES_DBG_PHY, "%s: Phy data = 0x%04X, link was %s.\n",
Chien Tung1b949322009-04-08 14:27:09 -07002480 __func__, phy_data, nesadapter->mac_link_down[mac_index] ? "DOWN" : "UP");
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002481 break;
2482
2483 case NES_PHY_TYPE_PUMA_1G:
2484 if (mac_index < 2)
2485 pcs_val = pcs_mask = 0x01010000;
2486 else
2487 pcs_val = pcs_mask = 0x02020000;
2488 /* fall through */
2489 default:
2490 phy_data = (pcs_val == (pcs_control_status & pcs_mask)) ? 0x4 : 0x0;
2491 break;
2492 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002493 }
2494
2495 if (phy_data & 0x0004) {
Chien Tunga4849fc2009-04-08 14:27:18 -07002496 if (wide_ppm_offset &&
2497 (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_CX4) &&
2498 (nesadapter->hw_rev != NE020_REV)) {
2499 cdr_ctrl = nes_read_indexed(nesdev,
2500 NES_IDX_ETH_SERDES_CDR_CONTROL0 +
2501 mac_index * 0x200);
2502 nes_write_indexed(nesdev,
2503 NES_IDX_ETH_SERDES_CDR_CONTROL0 +
2504 mac_index * 0x200,
2505 cdr_ctrl | 0x000F0000);
2506 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002507 nesadapter->mac_link_down[mac_index] = 0;
2508 list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) {
2509 nes_debug(NES_DBG_PHY, "The Link is UP!!. linkup was %d\n",
2510 nesvnic->linkup);
2511 if (nesvnic->linkup == 0) {
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002512 printk(PFX "The Link is now up for port %s, netdev %p.\n",
2513 nesvnic->netdev->name, nesvnic->netdev);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002514 if (netif_queue_stopped(nesvnic->netdev))
2515 netif_start_queue(nesvnic->netdev);
2516 nesvnic->linkup = 1;
2517 netif_carrier_on(nesvnic->netdev);
2518 }
2519 }
2520 } else {
Chien Tunga4849fc2009-04-08 14:27:18 -07002521 if (wide_ppm_offset &&
2522 (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_CX4) &&
2523 (nesadapter->hw_rev != NE020_REV)) {
2524 cdr_ctrl = nes_read_indexed(nesdev,
2525 NES_IDX_ETH_SERDES_CDR_CONTROL0 +
2526 mac_index * 0x200);
2527 nes_write_indexed(nesdev,
2528 NES_IDX_ETH_SERDES_CDR_CONTROL0 +
2529 mac_index * 0x200,
2530 cdr_ctrl & 0xFFF0FFFF);
2531 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002532 nesadapter->mac_link_down[mac_index] = 1;
2533 list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) {
2534 nes_debug(NES_DBG_PHY, "The Link is Down!!. linkup was %d\n",
2535 nesvnic->linkup);
2536 if (nesvnic->linkup == 1) {
Eric Schneider0e1de5d2008-04-29 13:46:54 -07002537 printk(PFX "The Link is now down for port %s, netdev %p.\n",
2538 nesvnic->netdev->name, nesvnic->netdev);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002539 if (!(netif_queue_stopped(nesvnic->netdev)))
2540 netif_stop_queue(nesvnic->netdev);
2541 nesvnic->linkup = 0;
2542 netif_carrier_off(nesvnic->netdev);
2543 }
2544 }
2545 }
2546 }
2547
2548 nesadapter->mac_sw_state[mac_number] = NES_MAC_SW_IDLE;
2549}
2550
2551
2552
Roland Dreier1a855fbf2008-04-16 21:01:09 -07002553static void nes_nic_napi_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002554{
2555 struct nes_vnic *nesvnic = container_of(cq, struct nes_vnic, nic_cq);
2556
Ben Hutchings288379f2009-01-19 16:43:59 -08002557 napi_schedule(&nesvnic->napi);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002558}
2559
2560
2561/* The MAX_RQES_TO_PROCESS defines how many max read requests to complete before
2562* getting out of nic_ce_handler
2563*/
2564#define MAX_RQES_TO_PROCESS 384
2565
2566/**
2567 * nes_nic_ce_handler
2568 */
2569void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
2570{
2571 u64 u64temp;
2572 dma_addr_t bus_address;
2573 struct nes_hw_nic *nesnic;
2574 struct nes_vnic *nesvnic = container_of(cq, struct nes_vnic, nic_cq);
2575 struct nes_adapter *nesadapter = nesdev->nesadapter;
2576 struct nes_hw_nic_rq_wqe *nic_rqe;
2577 struct nes_hw_nic_sq_wqe *nic_sqe;
2578 struct sk_buff *skb;
2579 struct sk_buff *rx_skb;
2580 __le16 *wqe_fragment_length;
2581 u32 head;
2582 u32 cq_size;
2583 u32 rx_pkt_size;
2584 u32 cqe_count=0;
2585 u32 cqe_errv;
2586 u32 cqe_misc;
2587 u16 wqe_fragment_index = 1; /* first fragment (0) is used by copy buffer */
2588 u16 vlan_tag;
2589 u16 pkt_type;
2590 u16 rqes_processed = 0;
2591 u8 sq_cqes = 0;
Faisal Latif37dab412008-04-29 13:46:54 -07002592 u8 nes_use_lro = 0;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002593
2594 head = cq->cq_head;
2595 cq_size = cq->cq_size;
2596 cq->cqes_pending = 1;
Faisal Latif37dab412008-04-29 13:46:54 -07002597 if (nesvnic->netdev->features & NETIF_F_LRO)
2598 nes_use_lro = 1;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002599 do {
2600 if (le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX]) &
2601 NES_NIC_CQE_VALID) {
2602 nesnic = &nesvnic->nic;
2603 cqe_misc = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX]);
2604 if (cqe_misc & NES_NIC_CQE_SQ) {
2605 sq_cqes++;
2606 wqe_fragment_index = 1;
2607 nic_sqe = &nesnic->sq_vbase[nesnic->sq_tail];
2608 skb = nesnic->tx_skb[nesnic->sq_tail];
2609 wqe_fragment_length = (__le16 *)&nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX];
2610 /* bump past the vlan tag */
2611 wqe_fragment_length++;
2612 if (le16_to_cpu(wqe_fragment_length[wqe_fragment_index]) != 0) {
Glenn Streiff7495ab62008-04-29 13:46:54 -07002613 u64temp = (u64) le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX +
2614 wqe_fragment_index * 2]);
2615 u64temp += ((u64)le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX +
2616 wqe_fragment_index * 2])) << 32;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002617 bus_address = (dma_addr_t)u64temp;
2618 if (test_and_clear_bit(nesnic->sq_tail, nesnic->first_frag_overflow)) {
2619 pci_unmap_single(nesdev->pcidev,
2620 bus_address,
2621 le16_to_cpu(wqe_fragment_length[wqe_fragment_index++]),
2622 PCI_DMA_TODEVICE);
2623 }
2624 for (; wqe_fragment_index < 5; wqe_fragment_index++) {
2625 if (wqe_fragment_length[wqe_fragment_index]) {
Glenn Streiff7495ab62008-04-29 13:46:54 -07002626 u64temp = le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX +
2627 wqe_fragment_index * 2]);
2628 u64temp += ((u64)le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX
2629 + wqe_fragment_index * 2])) <<32;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002630 bus_address = (dma_addr_t)u64temp;
2631 pci_unmap_page(nesdev->pcidev,
2632 bus_address,
2633 le16_to_cpu(wqe_fragment_length[wqe_fragment_index]),
2634 PCI_DMA_TODEVICE);
2635 } else
2636 break;
2637 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002638 }
Faisal Latif28699752009-03-06 15:12:11 -08002639 if (skb)
2640 dev_kfree_skb_any(skb);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002641 nesnic->sq_tail++;
2642 nesnic->sq_tail &= nesnic->sq_size-1;
2643 if (sq_cqes > 128) {
2644 barrier();
2645 /* restart the queue if it had been stopped */
2646 if (netif_queue_stopped(nesvnic->netdev))
2647 netif_wake_queue(nesvnic->netdev);
2648 sq_cqes = 0;
2649 }
2650 } else {
2651 rqes_processed ++;
2652
2653 cq->rx_cqes_completed++;
2654 cq->rx_pkts_indicated++;
2655 rx_pkt_size = cqe_misc & 0x0000ffff;
2656 nic_rqe = &nesnic->rq_vbase[nesnic->rq_tail];
2657 /* Get the skb */
2658 rx_skb = nesnic->rx_skb[nesnic->rq_tail];
2659 nic_rqe = &nesnic->rq_vbase[nesvnic->nic.rq_tail];
2660 bus_address = (dma_addr_t)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]);
2661 bus_address += ((u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX])) << 32;
2662 pci_unmap_single(nesdev->pcidev, bus_address,
2663 nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
2664 /* rx_skb->tail = rx_skb->data + rx_pkt_size; */
2665 /* rx_skb->len = rx_pkt_size; */
2666 rx_skb->len = 0; /* TODO: see if this is necessary */
2667 skb_put(rx_skb, rx_pkt_size);
2668 rx_skb->protocol = eth_type_trans(rx_skb, nesvnic->netdev);
2669 nesnic->rq_tail++;
2670 nesnic->rq_tail &= nesnic->rq_size - 1;
2671
2672 atomic_inc(&nesvnic->rx_skbs_needed);
2673 if (atomic_read(&nesvnic->rx_skbs_needed) > (nesvnic->nic.rq_size>>1)) {
2674 nes_write32(nesdev->regs+NES_CQE_ALLOC,
2675 cq->cq_number | (cqe_count << 16));
Glenn Streiff7495ab62008-04-29 13:46:54 -07002676 /* nesadapter->tune_timer.cq_count += cqe_count; */
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002677 nesdev->currcq_count += cqe_count;
2678 cqe_count = 0;
2679 nes_replenish_nic_rq(nesvnic);
2680 }
2681 pkt_type = (u16)(le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_TAG_PKT_TYPE_IDX]));
2682 cqe_errv = (cqe_misc & NES_NIC_CQE_ERRV_MASK) >> NES_NIC_CQE_ERRV_SHIFT;
2683 rx_skb->ip_summed = CHECKSUM_NONE;
2684
2685 if ((NES_PKT_TYPE_TCPV4_BITS == (pkt_type & NES_PKT_TYPE_TCPV4_MASK)) ||
2686 (NES_PKT_TYPE_UDPV4_BITS == (pkt_type & NES_PKT_TYPE_UDPV4_MASK))) {
2687 if ((cqe_errv &
2688 (NES_NIC_ERRV_BITS_IPV4_CSUM_ERR | NES_NIC_ERRV_BITS_TCPUDP_CSUM_ERR |
2689 NES_NIC_ERRV_BITS_IPH_ERR | NES_NIC_ERRV_BITS_WQE_OVERRUN)) == 0) {
2690 if (nesvnic->rx_checksum_disabled == 0) {
2691 rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
2692 }
2693 } else
2694 nes_debug(NES_DBG_CQ, "%s: unsuccessfully checksummed TCP or UDP packet."
2695 " errv = 0x%X, pkt_type = 0x%X.\n",
2696 nesvnic->netdev->name, cqe_errv, pkt_type);
2697
2698 } else if ((pkt_type & NES_PKT_TYPE_IPV4_MASK) == NES_PKT_TYPE_IPV4_BITS) {
2699 if ((cqe_errv &
2700 (NES_NIC_ERRV_BITS_IPV4_CSUM_ERR | NES_NIC_ERRV_BITS_IPH_ERR |
2701 NES_NIC_ERRV_BITS_WQE_OVERRUN)) == 0) {
2702 if (nesvnic->rx_checksum_disabled == 0) {
2703 rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
2704 /* nes_debug(NES_DBG_CQ, "%s: Reporting successfully checksummed IPv4 packet.\n",
2705 nesvnic->netdev->name); */
2706 }
2707 } else
2708 nes_debug(NES_DBG_CQ, "%s: unsuccessfully checksummed TCP or UDP packet."
2709 " errv = 0x%X, pkt_type = 0x%X.\n",
2710 nesvnic->netdev->name, cqe_errv, pkt_type);
2711 }
2712 /* nes_debug(NES_DBG_CQ, "pkt_type=%x, APBVT_MASK=%x\n",
2713 pkt_type, (pkt_type & NES_PKT_TYPE_APBVT_MASK)); */
2714
2715 if ((pkt_type & NES_PKT_TYPE_APBVT_MASK) == NES_PKT_TYPE_APBVT_BITS) {
Faisal Latif4a14f6a2008-11-21 20:50:49 -06002716 if (nes_cm_recv(rx_skb, nesvnic->netdev))
2717 rx_skb = NULL;
2718 }
2719 if (rx_skb == NULL)
2720 goto skip_rx_indicate0;
2721
2722
2723 if ((cqe_misc & NES_NIC_CQE_TAG_VALID) &&
2724 (nesvnic->vlan_grp != NULL)) {
2725 vlan_tag = (u16)(le32_to_cpu(
2726 cq->cq_vbase[head].cqe_words[NES_NIC_CQE_TAG_PKT_TYPE_IDX])
2727 >> 16);
2728 nes_debug(NES_DBG_CQ, "%s: Reporting stripped VLAN packet. Tag = 0x%04X\n",
2729 nesvnic->netdev->name, vlan_tag);
2730 if (nes_use_lro)
2731 lro_vlan_hwaccel_receive_skb(&nesvnic->lro_mgr, rx_skb,
2732 nesvnic->vlan_grp, vlan_tag, NULL);
2733 else
2734 nes_vlan_rx(rx_skb, nesvnic->vlan_grp, vlan_tag);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002735 } else {
Faisal Latif4a14f6a2008-11-21 20:50:49 -06002736 if (nes_use_lro)
2737 lro_receive_skb(&nesvnic->lro_mgr, rx_skb, NULL);
2738 else
2739 nes_netif_rx(rx_skb);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002740 }
2741
Faisal Latif4a14f6a2008-11-21 20:50:49 -06002742skip_rx_indicate0:
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002743 nesvnic->netdev->last_rx = jiffies;
2744 /* nesvnic->netstats.rx_packets++; */
2745 /* nesvnic->netstats.rx_bytes += rx_pkt_size; */
2746 }
2747
2748 cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX] = 0;
2749 /* Accounting... */
2750 cqe_count++;
2751 if (++head >= cq_size)
2752 head = 0;
2753 if (cqe_count == 255) {
2754 /* Replenish Nic CQ */
2755 nes_write32(nesdev->regs+NES_CQE_ALLOC,
2756 cq->cq_number | (cqe_count << 16));
Glenn Streiff7495ab62008-04-29 13:46:54 -07002757 /* nesdev->nesadapter->tune_timer.cq_count += cqe_count; */
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002758 nesdev->currcq_count += cqe_count;
2759 cqe_count = 0;
2760 }
2761
2762 if (cq->rx_cqes_completed >= nesvnic->budget)
2763 break;
2764 } else {
2765 cq->cqes_pending = 0;
2766 break;
2767 }
2768
2769 } while (1);
2770
Faisal Latif37dab412008-04-29 13:46:54 -07002771 if (nes_use_lro)
2772 lro_flush_all(&nesvnic->lro_mgr);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002773 if (sq_cqes) {
2774 barrier();
2775 /* restart the queue if it had been stopped */
2776 if (netif_queue_stopped(nesvnic->netdev))
2777 netif_wake_queue(nesvnic->netdev);
2778 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002779 cq->cq_head = head;
2780 /* nes_debug(NES_DBG_CQ, "CQ%u Processed = %u cqes, new head = %u.\n",
2781 cq->cq_number, cqe_count, cq->cq_head); */
2782 cq->cqe_allocs_pending = cqe_count;
2783 if (unlikely(nesadapter->et_use_adaptive_rx_coalesce))
2784 {
Glenn Streiff7495ab62008-04-29 13:46:54 -07002785 /* nesdev->nesadapter->tune_timer.cq_count += cqe_count; */
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002786 nesdev->currcq_count += cqe_count;
2787 nes_nic_tune_timer(nesdev);
2788 }
2789 if (atomic_read(&nesvnic->rx_skbs_needed))
2790 nes_replenish_nic_rq(nesvnic);
Faisal Latif37dab412008-04-29 13:46:54 -07002791}
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002792
2793
2794/**
2795 * nes_cqp_ce_handler
2796 */
Roland Dreier1a855fbf2008-04-16 21:01:09 -07002797static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002798{
2799 u64 u64temp;
2800 unsigned long flags;
2801 struct nes_hw_cqp *cqp = NULL;
2802 struct nes_cqp_request *cqp_request;
2803 struct nes_hw_cqp_wqe *cqp_wqe;
2804 u32 head;
2805 u32 cq_size;
2806 u32 cqe_count=0;
2807 u32 error_code;
2808 /* u32 counter; */
2809
2810 head = cq->cq_head;
2811 cq_size = cq->cq_size;
2812
2813 do {
2814 /* process the CQE */
2815 /* nes_debug(NES_DBG_CQP, "head=%u cqe_words=%08X\n", head,
2816 le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX])); */
2817
2818 if (le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_VALID) {
2819 u64temp = (((u64)(le32_to_cpu(cq->cq_vbase[head].
Glenn Streiff7495ab62008-04-29 13:46:54 -07002820 cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX]))) << 32) |
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002821 ((u64)(le32_to_cpu(cq->cq_vbase[head].
2822 cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX])));
2823 cqp = *((struct nes_hw_cqp **)&u64temp);
2824
2825 error_code = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_ERROR_CODE_IDX]);
2826 if (error_code) {
2827 nes_debug(NES_DBG_CQP, "Bad Completion code for opcode 0x%02X from CQP,"
2828 " Major/Minor codes = 0x%04X:%04X.\n",
2829 le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX])&0x3f,
2830 (u16)(error_code >> 16),
2831 (u16)error_code);
2832 nes_debug(NES_DBG_CQP, "cqp: qp_id=%u, sq_head=%u, sq_tail=%u\n",
2833 cqp->qp_id, cqp->sq_head, cqp->sq_tail);
2834 }
2835
2836 u64temp = (((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail].
Glenn Streiff7495ab62008-04-29 13:46:54 -07002837 wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX]))) << 32) |
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002838 ((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail].
2839 wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX])));
2840 cqp_request = *((struct nes_cqp_request **)&u64temp);
2841 if (cqp_request) {
2842 if (cqp_request->waiting) {
2843 /* nes_debug(NES_DBG_CQP, "%s: Waking up requestor\n"); */
2844 cqp_request->major_code = (u16)(error_code >> 16);
2845 cqp_request->minor_code = (u16)error_code;
2846 barrier();
2847 cqp_request->request_done = 1;
2848 wake_up(&cqp_request->waitq);
Roland Dreier1ff66e82008-07-14 23:48:49 -07002849 nes_put_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002850 } else {
Roland Dreier1ff66e82008-07-14 23:48:49 -07002851 if (cqp_request->callback)
2852 cqp_request->cqp_callback(nesdev, cqp_request);
2853 nes_free_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002854 }
2855 } else {
2856 wake_up(&nesdev->cqp.waitq);
2857 }
2858
2859 cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX] = 0;
Glenn Streiff7495ab62008-04-29 13:46:54 -07002860 nes_write32(nesdev->regs + NES_CQE_ALLOC, cq->cq_number | (1 << 16));
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002861 if (++cqp->sq_tail >= cqp->sq_size)
2862 cqp->sq_tail = 0;
2863
2864 /* Accounting... */
2865 cqe_count++;
2866 if (++head >= cq_size)
2867 head = 0;
2868 } else {
2869 break;
2870 }
2871 } while (1);
2872 cq->cq_head = head;
2873
2874 spin_lock_irqsave(&nesdev->cqp.lock, flags);
2875 while ((!list_empty(&nesdev->cqp_pending_reqs)) &&
2876 ((((nesdev->cqp.sq_tail+nesdev->cqp.sq_size)-nesdev->cqp.sq_head) &
2877 (nesdev->cqp.sq_size - 1)) != 1)) {
2878 cqp_request = list_entry(nesdev->cqp_pending_reqs.next,
2879 struct nes_cqp_request, list);
2880 list_del_init(&cqp_request->list);
2881 head = nesdev->cqp.sq_head++;
2882 nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
2883 cqp_wqe = &nesdev->cqp.sq_vbase[head];
2884 memcpy(cqp_wqe, &cqp_request->cqp_wqe, sizeof(*cqp_wqe));
2885 barrier();
2886 cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] =
2887 cpu_to_le32((u32)((unsigned long)cqp_request));
2888 cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] =
2889 cpu_to_le32((u32)(upper_32_bits((unsigned long)cqp_request)));
2890 nes_debug(NES_DBG_CQP, "CQP request %p (opcode 0x%02X) put on CQPs SQ wqe%u.\n",
2891 cqp_request, le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f, head);
2892 /* Ring doorbell (1 WQEs) */
2893 barrier();
2894 nes_write32(nesdev->regs+NES_WQE_ALLOC, 0x01800000 | nesdev->cqp.qp_id);
2895 }
2896 spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
2897
2898 /* Arm the CCQ */
2899 nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT |
2900 cq->cq_number);
2901 nes_read32(nesdev->regs+NES_CQE_ALLOC);
2902}
2903
2904
2905/**
2906 * nes_process_iwarp_aeqe
2907 */
Roland Dreier1a855fbf2008-04-16 21:01:09 -07002908static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
2909 struct nes_hw_aeqe *aeqe)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002910{
2911 u64 context;
2912 u64 aeqe_context = 0;
2913 unsigned long flags;
2914 struct nes_qp *nesqp;
2915 int resource_allocated;
2916 /* struct iw_cm_id *cm_id; */
2917 struct nes_adapter *nesadapter = nesdev->nesadapter;
2918 struct ib_event ibevent;
2919 /* struct iw_cm_event cm_event; */
2920 u32 aeq_info;
2921 u32 next_iwarp_state = 0;
2922 u16 async_event_id;
2923 u8 tcp_state;
2924 u8 iwarp_state;
2925
2926 nes_debug(NES_DBG_AEQ, "\n");
2927 aeq_info = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]);
2928 if ((NES_AEQE_INBOUND_RDMA&aeq_info) || (!(NES_AEQE_QP&aeq_info))) {
Glenn Streiff7495ab62008-04-29 13:46:54 -07002929 context = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX]);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002930 context += ((u64)le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX])) << 32;
2931 } else {
2932 aeqe_context = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX]);
2933 aeqe_context += ((u64)le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX])) << 32;
2934 context = (unsigned long)nesadapter->qp_table[le32_to_cpu(
Glenn Streiff7495ab62008-04-29 13:46:54 -07002935 aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]) - NES_FIRST_QPN];
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002936 BUG_ON(!context);
2937 }
2938
2939 async_event_id = (u16)aeq_info;
2940 tcp_state = (aeq_info & NES_AEQE_TCP_STATE_MASK) >> NES_AEQE_TCP_STATE_SHIFT;
2941 iwarp_state = (aeq_info & NES_AEQE_IWARP_STATE_MASK) >> NES_AEQE_IWARP_STATE_SHIFT;
2942 nes_debug(NES_DBG_AEQ, "aeid = 0x%04X, qp-cq id = %d, aeqe = %p,"
2943 " Tcp state = %s, iWARP state = %s\n",
2944 async_event_id,
2945 le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]), aeqe,
2946 nes_tcp_state_str[tcp_state], nes_iwarp_state_str[iwarp_state]);
2947
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002948 switch (async_event_id) {
2949 case NES_AEQE_AEID_LLP_FIN_RECEIVED:
2950 nesqp = *((struct nes_qp **)&context);
2951 if (atomic_inc_return(&nesqp->close_timer_started) == 1) {
2952 nesqp->cm_id->add_ref(nesqp->cm_id);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002953 schedule_nes_timer(nesqp->cm_node, (struct sk_buff *)nesqp,
2954 NES_TIMER_TYPE_CLOSE, 1, 0);
2955 nes_debug(NES_DBG_AEQ, "QP%u Not decrementing QP refcount (%d),"
2956 " need ae to finish up, original_last_aeq = 0x%04X."
2957 " last_aeq = 0x%04X, scheduling timer. TCP state = %d\n",
2958 nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),
2959 async_event_id, nesqp->last_aeq, tcp_state);
2960 }
2961 if ((tcp_state != NES_AEQE_TCP_STATE_CLOSE_WAIT) ||
2962 (nesqp->ibqp_state != IB_QPS_RTS)) {
2963 /* FIN Received but tcp state or IB state moved on,
2964 should expect a close complete */
2965 return;
2966 }
2967 case NES_AEQE_AEID_LLP_CLOSE_COMPLETE:
2968 case NES_AEQE_AEID_LLP_CONNECTION_RESET:
2969 case NES_AEQE_AEID_TERMINATE_SENT:
2970 case NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE:
2971 case NES_AEQE_AEID_RESET_SENT:
2972 nesqp = *((struct nes_qp **)&context);
2973 if (async_event_id == NES_AEQE_AEID_RESET_SENT) {
2974 tcp_state = NES_AEQE_TCP_STATE_CLOSED;
2975 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002976 spin_lock_irqsave(&nesqp->lock, flags);
2977 nesqp->hw_iwarp_state = iwarp_state;
2978 nesqp->hw_tcp_state = tcp_state;
2979 nesqp->last_aeq = async_event_id;
2980
2981 if ((tcp_state == NES_AEQE_TCP_STATE_CLOSED) ||
2982 (tcp_state == NES_AEQE_TCP_STATE_TIME_WAIT)) {
2983 nesqp->hte_added = 0;
2984 spin_unlock_irqrestore(&nesqp->lock, flags);
2985 nes_debug(NES_DBG_AEQ, "issuing hw modifyqp for QP%u to remove hte\n",
2986 nesqp->hwqp.qp_id);
2987 nes_hw_modify_qp(nesdev, nesqp,
2988 NES_CQP_QP_IWARP_STATE_ERROR | NES_CQP_QP_DEL_HTE, 0);
2989 spin_lock_irqsave(&nesqp->lock, flags);
2990 }
2991
2992 if ((nesqp->ibqp_state == IB_QPS_RTS) &&
2993 ((tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) ||
2994 (async_event_id == NES_AEQE_AEID_LLP_CONNECTION_RESET))) {
2995 switch (nesqp->hw_iwarp_state) {
2996 case NES_AEQE_IWARP_STATE_RTS:
2997 next_iwarp_state = NES_CQP_QP_IWARP_STATE_CLOSING;
2998 nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_CLOSING;
2999 break;
3000 case NES_AEQE_IWARP_STATE_TERMINATE:
3001 next_iwarp_state = NES_CQP_QP_IWARP_STATE_TERMINATE;
3002 nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_TERMINATE;
3003 if (async_event_id == NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE) {
3004 next_iwarp_state |= 0x02000000;
3005 nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
3006 }
3007 break;
3008 default:
3009 next_iwarp_state = 0;
3010 }
3011 spin_unlock_irqrestore(&nesqp->lock, flags);
3012 if (next_iwarp_state) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003013 nes_debug(NES_DBG_AEQ, "issuing hw modifyqp for QP%u. next state = 0x%08X,"
3014 " also added another reference\n",
3015 nesqp->hwqp.qp_id, next_iwarp_state);
3016 nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0);
3017 }
3018 nes_cm_disconn(nesqp);
3019 } else {
3020 if (async_event_id == NES_AEQE_AEID_LLP_FIN_RECEIVED) {
3021 /* FIN Received but ib state not RTS,
3022 close complete will be on its way */
3023 spin_unlock_irqrestore(&nesqp->lock, flags);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003024 return;
3025 }
3026 spin_unlock_irqrestore(&nesqp->lock, flags);
3027 if (async_event_id == NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE) {
3028 next_iwarp_state = NES_CQP_QP_IWARP_STATE_TERMINATE | 0x02000000;
3029 nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
3030 nes_debug(NES_DBG_AEQ, "issuing hw modifyqp for QP%u. next state = 0x%08X,"
3031 " also added another reference\n",
3032 nesqp->hwqp.qp_id, next_iwarp_state);
3033 nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0);
3034 }
3035 nes_cm_disconn(nesqp);
3036 }
3037 break;
3038 case NES_AEQE_AEID_LLP_TERMINATE_RECEIVED:
3039 nesqp = *((struct nes_qp **)&context);
3040 spin_lock_irqsave(&nesqp->lock, flags);
3041 nesqp->hw_iwarp_state = iwarp_state;
3042 nesqp->hw_tcp_state = tcp_state;
3043 nesqp->last_aeq = async_event_id;
3044 spin_unlock_irqrestore(&nesqp->lock, flags);
3045 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_LLP_TERMINATE_RECEIVED"
3046 " event on QP%u \n Q2 Data:\n",
3047 nesqp->hwqp.qp_id);
3048 if (nesqp->ibqp.event_handler) {
3049 ibevent.device = nesqp->ibqp.device;
3050 ibevent.element.qp = &nesqp->ibqp;
3051 ibevent.event = IB_EVENT_QP_FATAL;
3052 nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
3053 }
3054 if ((tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) ||
3055 ((nesqp->ibqp_state == IB_QPS_RTS)&&
3056 (async_event_id == NES_AEQE_AEID_LLP_CONNECTION_RESET))) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003057 nes_cm_disconn(nesqp);
3058 } else {
3059 nesqp->in_disconnect = 0;
3060 wake_up(&nesqp->kick_waitq);
3061 }
3062 break;
3063 case NES_AEQE_AEID_LLP_TOO_MANY_RETRIES:
3064 nesqp = *((struct nes_qp **)&context);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003065 spin_lock_irqsave(&nesqp->lock, flags);
3066 nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_ERROR;
3067 nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
3068 nesqp->last_aeq = async_event_id;
3069 if (nesqp->cm_id) {
3070 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_LLP_TOO_MANY_RETRIES"
3071 " event on QP%u, remote IP = 0x%08X \n",
3072 nesqp->hwqp.qp_id,
3073 ntohl(nesqp->cm_id->remote_addr.sin_addr.s_addr));
3074 } else {
3075 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_LLP_TOO_MANY_RETRIES"
3076 " event on QP%u \n",
3077 nesqp->hwqp.qp_id);
3078 }
3079 spin_unlock_irqrestore(&nesqp->lock, flags);
3080 next_iwarp_state = NES_CQP_QP_IWARP_STATE_ERROR | NES_CQP_QP_RESET;
3081 nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0);
3082 if (nesqp->ibqp.event_handler) {
3083 ibevent.device = nesqp->ibqp.device;
3084 ibevent.element.qp = &nesqp->ibqp;
3085 ibevent.event = IB_EVENT_QP_FATAL;
3086 nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
3087 }
3088 break;
3089 case NES_AEQE_AEID_AMP_BAD_STAG_INDEX:
3090 if (NES_AEQE_INBOUND_RDMA&aeq_info) {
3091 nesqp = nesadapter->qp_table[le32_to_cpu(
3092 aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX])-NES_FIRST_QPN];
3093 } else {
3094 /* TODO: get the actual WQE and mask off wqe index */
3095 context &= ~((u64)511);
3096 nesqp = *((struct nes_qp **)&context);
3097 }
3098 spin_lock_irqsave(&nesqp->lock, flags);
3099 nesqp->hw_iwarp_state = iwarp_state;
3100 nesqp->hw_tcp_state = tcp_state;
3101 nesqp->last_aeq = async_event_id;
3102 spin_unlock_irqrestore(&nesqp->lock, flags);
3103 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_AMP_BAD_STAG_INDEX event on QP%u\n",
3104 nesqp->hwqp.qp_id);
3105 if (nesqp->ibqp.event_handler) {
3106 ibevent.device = nesqp->ibqp.device;
3107 ibevent.element.qp = &nesqp->ibqp;
3108 ibevent.event = IB_EVENT_QP_ACCESS_ERR;
3109 nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
3110 }
3111 break;
3112 case NES_AEQE_AEID_AMP_UNALLOCATED_STAG:
3113 nesqp = *((struct nes_qp **)&context);
3114 spin_lock_irqsave(&nesqp->lock, flags);
3115 nesqp->hw_iwarp_state = iwarp_state;
3116 nesqp->hw_tcp_state = tcp_state;
3117 nesqp->last_aeq = async_event_id;
3118 spin_unlock_irqrestore(&nesqp->lock, flags);
3119 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_AMP_UNALLOCATED_STAG event on QP%u\n",
3120 nesqp->hwqp.qp_id);
3121 if (nesqp->ibqp.event_handler) {
3122 ibevent.device = nesqp->ibqp.device;
3123 ibevent.element.qp = &nesqp->ibqp;
3124 ibevent.event = IB_EVENT_QP_ACCESS_ERR;
3125 nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
3126 }
3127 break;
3128 case NES_AEQE_AEID_PRIV_OPERATION_DENIED:
3129 nesqp = nesadapter->qp_table[le32_to_cpu(aeqe->aeqe_words
3130 [NES_AEQE_COMP_QP_CQ_ID_IDX])-NES_FIRST_QPN];
3131 spin_lock_irqsave(&nesqp->lock, flags);
3132 nesqp->hw_iwarp_state = iwarp_state;
3133 nesqp->hw_tcp_state = tcp_state;
3134 nesqp->last_aeq = async_event_id;
3135 spin_unlock_irqrestore(&nesqp->lock, flags);
3136 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_PRIV_OPERATION_DENIED event on QP%u,"
3137 " nesqp = %p, AE reported %p\n",
3138 nesqp->hwqp.qp_id, nesqp, *((struct nes_qp **)&context));
3139 if (nesqp->ibqp.event_handler) {
3140 ibevent.device = nesqp->ibqp.device;
3141 ibevent.element.qp = &nesqp->ibqp;
3142 ibevent.event = IB_EVENT_QP_ACCESS_ERR;
3143 nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
3144 }
3145 break;
3146 case NES_AEQE_AEID_CQ_OPERATION_ERROR:
3147 context <<= 1;
3148 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_CQ_OPERATION_ERROR event on CQ%u, %p\n",
3149 le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]), (void *)(unsigned long)context);
3150 resource_allocated = nes_is_resource_allocated(nesadapter, nesadapter->allocated_cqs,
3151 le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]));
3152 if (resource_allocated) {
3153 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 -07003154 __func__, le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]));
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003155 }
3156 break;
3157 case NES_AEQE_AEID_DDP_UBE_DDP_MESSAGE_TOO_LONG_FOR_AVAILABLE_BUFFER:
3158 nesqp = nesadapter->qp_table[le32_to_cpu(
3159 aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX])-NES_FIRST_QPN];
3160 spin_lock_irqsave(&nesqp->lock, flags);
3161 nesqp->hw_iwarp_state = iwarp_state;
3162 nesqp->hw_tcp_state = tcp_state;
3163 nesqp->last_aeq = async_event_id;
3164 spin_unlock_irqrestore(&nesqp->lock, flags);
3165 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_DDP_UBE_DDP_MESSAGE_TOO_LONG"
3166 "_FOR_AVAILABLE_BUFFER event on QP%u\n",
3167 nesqp->hwqp.qp_id);
3168 if (nesqp->ibqp.event_handler) {
3169 ibevent.device = nesqp->ibqp.device;
3170 ibevent.element.qp = &nesqp->ibqp;
3171 ibevent.event = IB_EVENT_QP_ACCESS_ERR;
3172 nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
3173 }
3174 /* tell cm to disconnect, cm will queue work to thread */
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003175 nes_cm_disconn(nesqp);
3176 break;
3177 case NES_AEQE_AEID_DDP_UBE_INVALID_MSN_NO_BUFFER_AVAILABLE:
3178 nesqp = *((struct nes_qp **)&context);
3179 spin_lock_irqsave(&nesqp->lock, flags);
3180 nesqp->hw_iwarp_state = iwarp_state;
3181 nesqp->hw_tcp_state = tcp_state;
3182 nesqp->last_aeq = async_event_id;
3183 spin_unlock_irqrestore(&nesqp->lock, flags);
3184 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_DDP_UBE_INVALID_MSN"
3185 "_NO_BUFFER_AVAILABLE event on QP%u\n",
3186 nesqp->hwqp.qp_id);
3187 if (nesqp->ibqp.event_handler) {
3188 ibevent.device = nesqp->ibqp.device;
3189 ibevent.element.qp = &nesqp->ibqp;
3190 ibevent.event = IB_EVENT_QP_FATAL;
3191 nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
3192 }
3193 /* tell cm to disconnect, cm will queue work to thread */
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003194 nes_cm_disconn(nesqp);
3195 break;
3196 case NES_AEQE_AEID_LLP_RECEIVED_MPA_CRC_ERROR:
3197 nesqp = *((struct nes_qp **)&context);
3198 spin_lock_irqsave(&nesqp->lock, flags);
3199 nesqp->hw_iwarp_state = iwarp_state;
3200 nesqp->hw_tcp_state = tcp_state;
3201 nesqp->last_aeq = async_event_id;
3202 spin_unlock_irqrestore(&nesqp->lock, flags);
3203 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_LLP_RECEIVED_MPA_CRC_ERROR"
3204 " event on QP%u \n Q2 Data:\n",
3205 nesqp->hwqp.qp_id);
3206 if (nesqp->ibqp.event_handler) {
3207 ibevent.device = nesqp->ibqp.device;
3208 ibevent.element.qp = &nesqp->ibqp;
3209 ibevent.event = IB_EVENT_QP_FATAL;
3210 nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
3211 }
3212 /* tell cm to disconnect, cm will queue work to thread */
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003213 nes_cm_disconn(nesqp);
3214 break;
3215 /* TODO: additional AEs need to be here */
Faisal Latif1bb28492008-09-26 15:08:10 -05003216 case NES_AEQE_AEID_AMP_BOUNDS_VIOLATION:
3217 nesqp = *((struct nes_qp **)&context);
3218 spin_lock_irqsave(&nesqp->lock, flags);
3219 nesqp->hw_iwarp_state = iwarp_state;
3220 nesqp->hw_tcp_state = tcp_state;
3221 nesqp->last_aeq = async_event_id;
3222 spin_unlock_irqrestore(&nesqp->lock, flags);
3223 if (nesqp->ibqp.event_handler) {
3224 ibevent.device = nesqp->ibqp.device;
3225 ibevent.element.qp = &nesqp->ibqp;
3226 ibevent.event = IB_EVENT_QP_ACCESS_ERR;
3227 nesqp->ibqp.event_handler(&ibevent,
3228 nesqp->ibqp.qp_context);
3229 }
3230 nes_cm_disconn(nesqp);
3231 break;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003232 default:
3233 nes_debug(NES_DBG_AEQ, "Processing an iWARP related AE for QP, misc = 0x%04X\n",
3234 async_event_id);
3235 break;
3236 }
3237
3238}
3239
3240
3241/**
3242 * nes_iwarp_ce_handler
3243 */
3244void nes_iwarp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *hw_cq)
3245{
3246 struct nes_cq *nescq = container_of(hw_cq, struct nes_cq, hw_cq);
3247
3248 /* nes_debug(NES_DBG_CQ, "Processing completion event for iWARP CQ%u.\n",
3249 nescq->hw_cq.cq_number); */
3250 nes_write32(nesdev->regs+NES_CQ_ACK, nescq->hw_cq.cq_number);
3251
3252 if (nescq->ibcq.comp_handler)
3253 nescq->ibcq.comp_handler(&nescq->ibcq, nescq->ibcq.cq_context);
3254
3255 return;
3256}
3257
3258
3259/**
3260 * nes_manage_apbvt()
3261 */
3262int nes_manage_apbvt(struct nes_vnic *nesvnic, u32 accel_local_port,
3263 u32 nic_index, u32 add_port)
3264{
3265 struct nes_device *nesdev = nesvnic->nesdev;
3266 struct nes_hw_cqp_wqe *cqp_wqe;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003267 struct nes_cqp_request *cqp_request;
3268 int ret = 0;
3269 u16 major_code;
3270
3271 /* Send manage APBVT request to CQP */
3272 cqp_request = nes_get_cqp_request(nesdev);
3273 if (cqp_request == NULL) {
3274 nes_debug(NES_DBG_QP, "Failed to get a cqp_request.\n");
3275 return -ENOMEM;
3276 }
3277 cqp_request->waiting = 1;
3278 cqp_wqe = &cqp_request->cqp_wqe;
3279
3280 nes_debug(NES_DBG_QP, "%s APBV for local port=%u(0x%04x), nic_index=%u\n",
3281 (add_port == NES_MANAGE_APBVT_ADD) ? "ADD" : "DEL",
3282 accel_local_port, accel_local_port, nic_index);
3283
3284 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
3285 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, (NES_CQP_MANAGE_APBVT |
3286 ((add_port == NES_MANAGE_APBVT_ADD) ? NES_CQP_APBVT_ADD : 0)));
3287 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,
3288 ((nic_index << NES_CQP_APBVT_NIC_SHIFT) | accel_local_port));
3289
3290 nes_debug(NES_DBG_QP, "Waiting for CQP completion for APBVT.\n");
3291
3292 atomic_set(&cqp_request->refcount, 2);
Roland Dreier8294f292008-07-14 23:48:49 -07003293 nes_post_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003294
3295 if (add_port == NES_MANAGE_APBVT_ADD)
3296 ret = wait_event_timeout(cqp_request->waitq, (cqp_request->request_done != 0),
3297 NES_EVENT_TIMEOUT);
3298 nes_debug(NES_DBG_QP, "Completed, ret=%u, CQP Major:Minor codes = 0x%04X:0x%04X\n",
3299 ret, cqp_request->major_code, cqp_request->minor_code);
3300 major_code = cqp_request->major_code;
Roland Dreier1ff66e82008-07-14 23:48:49 -07003301
3302 nes_put_cqp_request(nesdev, cqp_request);
3303
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003304 if (!ret)
3305 return -ETIME;
3306 else if (major_code)
3307 return -EIO;
3308 else
3309 return 0;
3310}
3311
3312
3313/**
3314 * nes_manage_arp_cache
3315 */
3316void nes_manage_arp_cache(struct net_device *netdev, unsigned char *mac_addr,
3317 u32 ip_addr, u32 action)
3318{
3319 struct nes_hw_cqp_wqe *cqp_wqe;
3320 struct nes_vnic *nesvnic = netdev_priv(netdev);
3321 struct nes_device *nesdev;
3322 struct nes_cqp_request *cqp_request;
3323 int arp_index;
3324
3325 nesdev = nesvnic->nesdev;
3326 arp_index = nes_arp_table(nesdev, ip_addr, mac_addr, action);
3327 if (arp_index == -1) {
3328 return;
3329 }
3330
3331 /* update the ARP entry */
3332 cqp_request = nes_get_cqp_request(nesdev);
3333 if (cqp_request == NULL) {
3334 nes_debug(NES_DBG_NETDEV, "Failed to get a cqp_request.\n");
3335 return;
3336 }
3337 cqp_request->waiting = 0;
3338 cqp_wqe = &cqp_request->cqp_wqe;
3339 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
3340
3341 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(
3342 NES_CQP_MANAGE_ARP_CACHE | NES_CQP_ARP_PERM);
3343 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= cpu_to_le32(
3344 (u32)PCI_FUNC(nesdev->pcidev->devfn) << NES_CQP_ARP_AEQ_INDEX_SHIFT);
3345 cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(arp_index);
3346
3347 if (action == NES_ARP_ADD) {
3348 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= cpu_to_le32(NES_CQP_ARP_VALID);
3349 cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_ADDR_LOW_IDX] = cpu_to_le32(
3350 (((u32)mac_addr[2]) << 24) | (((u32)mac_addr[3]) << 16) |
Glenn Streiff7495ab62008-04-29 13:46:54 -07003351 (((u32)mac_addr[4]) << 8) | (u32)mac_addr[5]);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003352 cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_HIGH_IDX] = cpu_to_le32(
3353 (((u32)mac_addr[0]) << 16) | (u32)mac_addr[1]);
3354 } else {
3355 cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_ADDR_LOW_IDX] = 0;
3356 cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_HIGH_IDX] = 0;
3357 }
3358
3359 nes_debug(NES_DBG_NETDEV, "Not waiting for CQP, cqp.sq_head=%u, cqp.sq_tail=%u\n",
3360 nesdev->cqp.sq_head, nesdev->cqp.sq_tail);
3361
3362 atomic_set(&cqp_request->refcount, 1);
Roland Dreier8294f292008-07-14 23:48:49 -07003363 nes_post_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003364}
3365
3366
3367/**
3368 * flush_wqes
3369 */
3370void flush_wqes(struct nes_device *nesdev, struct nes_qp *nesqp,
3371 u32 which_wq, u32 wait_completion)
3372{
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003373 struct nes_cqp_request *cqp_request;
3374 struct nes_hw_cqp_wqe *cqp_wqe;
3375 int ret;
3376
3377 cqp_request = nes_get_cqp_request(nesdev);
3378 if (cqp_request == NULL) {
3379 nes_debug(NES_DBG_QP, "Failed to get a cqp_request.\n");
3380 return;
3381 }
3382 if (wait_completion) {
3383 cqp_request->waiting = 1;
3384 atomic_set(&cqp_request->refcount, 2);
3385 } else {
3386 cqp_request->waiting = 0;
3387 }
3388 cqp_wqe = &cqp_request->cqp_wqe;
3389 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
3390
3391 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] =
3392 cpu_to_le32(NES_CQP_FLUSH_WQES | which_wq);
3393 cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesqp->hwqp.qp_id);
3394
Roland Dreier8294f292008-07-14 23:48:49 -07003395 nes_post_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003396
3397 if (wait_completion) {
3398 /* Wait for CQP */
3399 ret = wait_event_timeout(cqp_request->waitq, (cqp_request->request_done != 0),
3400 NES_EVENT_TIMEOUT);
3401 nes_debug(NES_DBG_QP, "Flush SQ QP WQEs completed, ret=%u,"
3402 " CQP Major:Minor codes = 0x%04X:0x%04X\n",
3403 ret, cqp_request->major_code, cqp_request->minor_code);
Roland Dreier1ff66e82008-07-14 23:48:49 -07003404 nes_put_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003405 }
3406}