1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2014 QLogic Corporation
24 * The contents of this file are subject to the terms of the
25 * QLogic End User License (the "License").
26 * You may not use this file except in compliance with the License.
27 *
28 * You can obtain a copy of the License at
29 * http://www.qlogic.com/Resources/Documents/DriverDownloadHelp/
30 * QLogic_End_User_Software_License.txt
31 * See the License for the specific language governing permissions
32 * and limitations under the License.
33 */
34
35 /*
36 * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
37 */
38
39 #include "bnxe.h"
40
41
42 #ifdef BNXE_DEBUG_DMA_LIST
43
BnxeVerifySavedDmaList(um_device_t * pUM)44 static void BnxeVerifySavedDmaList(um_device_t * pUM)
45 {
46 BnxeMemDma * pTmp;
47 int i;
48
49 BNXE_LOCK_ENTER_MEM(pUM);
50
51 pTmp = (BnxeMemDma *)d_list_peek_head(&pUM->memDmaListSaved);
52 while (pTmp)
53 {
54 BnxeLogWarn(pUM, "testing dma block %p / %p %d",
55 pTmp, pTmp->pDmaVirt, pTmp->size);
56 for (i = 0; i < pTmp->size; i++)
57 {
58 if (((u8_t *)pTmp->pDmaVirt)[i] != 0x0)
59 {
60 BnxeDbgBreakMsg(pUM, "old dma block wacked %p (byte %i)",
61 pTmp, i);
62 }
63 }
64
65 pTmp = (BnxeMemDma *)d_list_next_entry(&pTmp->link);
66 }
67
68 BNXE_LOCK_EXIT_MEM(pUM);
69 }
70
71 #endif /* BNXE_DEBUG_DMA_LIST */
72
73
BnxeRssEnable(um_device_t * pUM)74 static boolean_t BnxeRssEnable(um_device_t * pUM)
75 {
76 #define BNXE_RSS_HASH_KEY_SIZE 40
77 u8_t hashKey[BNXE_RSS_HASH_KEY_SIZE];
78 #define BNXE_RSS_INDIRECTION_TABLE_SIZE 128 /* must be a power of 2 */
79 u8_t indirectionTable[BNXE_RSS_INDIRECTION_TABLE_SIZE];
80 lm_rss_hash_t hashType;
81 int i, rc;
82
83 if (!pUM->devParams.numRings)
84 {
85 return B_TRUE;
86 }
87
88 /* fill out the indirection table */
89 for (i = 0; i < BNXE_RSS_INDIRECTION_TABLE_SIZE; i++)
90 {
91 indirectionTable[i] = (i % pUM->devParams.numRings);
92 }
93
94 /* seed the hash function with random data */
95 random_get_pseudo_bytes(hashKey, BNXE_RSS_HASH_KEY_SIZE);
96
97 hashType = (LM_RSS_HASH_IPV4 |
98 LM_RSS_HASH_TCP_IPV4 |
99 LM_RSS_HASH_IPV6 |
100 LM_RSS_HASH_TCP_IPV6);
101
102 rc = lm_enable_rss((lm_device_t *)pUM,
103 indirectionTable,
104 BNXE_RSS_INDIRECTION_TABLE_SIZE,
105 hashKey,
106 BNXE_RSS_HASH_KEY_SIZE,
107 hashType,
108 FALSE,
109 NULL);
110
111 if (rc == LM_STATUS_PENDING)
112 {
113 if ((rc = lm_wait_config_rss_done(&pUM->lm_dev)) != LM_STATUS_SUCCESS)
114 {
115 BnxeLogWarn(pUM, "Failed to enable RSS from pending operation (%d)", rc);
116 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_NO_RESPONSE);
117 }
118 }
119 else if (rc != LM_STATUS_SUCCESS)
120 {
121 BnxeLogWarn(pUM, "Failed to enable RSS (%d)", rc);
122 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE);
123 }
124
125 return (rc == LM_STATUS_SUCCESS) ? B_TRUE : B_FALSE;
126 }
127
128
BnxeRssDisable(um_device_t * pUM)129 static lm_status_t BnxeRssDisable(um_device_t * pUM)
130 {
131 lm_status_t rc;
132
133 rc = lm_disable_rss((lm_device_t *)pUM, FALSE, NULL);
134
135 if (rc == LM_STATUS_PENDING)
136 {
137 if ((rc = lm_wait_config_rss_done(&pUM->lm_dev)) != LM_STATUS_SUCCESS)
138 {
139 BnxeLogWarn(pUM, "Failed to disable RSS from pending operation (%d)", rc);
140 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_NO_RESPONSE);
141 }
142 }
143 else if (rc != LM_STATUS_SUCCESS)
144 {
145 BnxeLogWarn(pUM, "Failed to disable RSS (%d)", rc);
146 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE);
147 }
148
149 return (rc);
150 }
151
152
BnxeHwReqPhyMediumSettings(um_device_t * pUM)153 lm_medium_t BnxeHwReqPhyMediumSettings(um_device_t * pUM)
154 {
155 lm_device_t * pLM = &pUM->lm_dev;
156 lm_medium_t medium = 0;
157 char buf[128];
158 int i;
159
160 memset(pUM->hwinit.supported, 0, sizeof(pUM->hwinit.supported));
161
162 switch (pLM->params.link.num_phys)
163 {
164 case 1:
165
166 pUM->hwinit.supported[0] =
167 pLM->params.link.phy[ELINK_INT_PHY].supported;
168 pUM->hwinit.phy_cfg_size = 1;
169 break;
170
171 case 2:
172
173 pUM->hwinit.supported[0] =
174 pLM->params.link.phy[ELINK_EXT_PHY1].supported;
175 pUM->hwinit.phy_cfg_size = 1;
176 break;
177
178 case 3:
179
180 if (pLM->params.link.multi_phy_config &
181 PORT_HW_CFG_PHY_SWAPPED_ENABLED)
182 {
183 pUM->hwinit.supported[1] =
184 pLM->params.link.phy[ELINK_EXT_PHY1].supported;
185 pUM->hwinit.supported[0] =
186 pLM->params.link.phy[ELINK_EXT_PHY2].supported;
187 }
188 else
189 {
190 pUM->hwinit.supported[0] =
191 pLM->params.link.phy[ELINK_EXT_PHY1].supported;
192 pUM->hwinit.supported[1] =
193 pLM->params.link.phy[ELINK_EXT_PHY2].supported;
194 }
195
196 pUM->hwinit.phy_cfg_size = 2;
197 break;
198
199 default:
200
201 BnxeLogWarn(pUM, "Unexpected number of phys, check nvram config! (%d)",
202 pLM->params.link.num_phys);
203 return 0;
204 }
205
206 for (i = 0; i < pUM->hwinit.phy_cfg_size; i++)
207 {
208 *buf = 0;
209 snprintf(buf, sizeof(buf), "Phy %d supported:", i);
210
211 if (!(pLM->params.link.speed_cap_mask[i] &
212 PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF))
213 {
214 pUM->hwinit.supported[i] &= ~ELINK_SUPPORTED_10baseT_Half;
215 }
216 else
217 {
218 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
219 " 10M/half");
220 }
221
222 if (!(pLM->params.link.speed_cap_mask[i] &
223 PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL))
224 {
225 pUM->hwinit.supported[i] &= ~ELINK_SUPPORTED_10baseT_Full;
226 }
227 else
228 {
229 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
230 " 10M/full");
231 }
232
233 if (!(pLM->params.link.speed_cap_mask[i] &
234 PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF))
235 {
236 pUM->hwinit.supported[i] &= ~ELINK_SUPPORTED_100baseT_Half;
237 }
238 else
239 {
240 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
241 " 100M/half");
242 }
243
244 if (!(pLM->params.link.speed_cap_mask[i] &
245 PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL))
246 {
247 pUM->hwinit.supported[i] &= ~ELINK_SUPPORTED_100baseT_Full;
248 }
249 else
250 {
251 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
252 " 100M/full");
253 }
254
255 if (!(pLM->params.link.speed_cap_mask[i] &
256 PORT_HW_CFG_SPEED_CAPABILITY_D0_1G))
257 {
258 pUM->hwinit.supported[i] &= ~ELINK_SUPPORTED_1000baseT_Full;
259 }
260 else
261 {
262 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
263 " 1G");
264 }
265
266 if (!(pLM->params.link.speed_cap_mask[i] &
267 PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))
268 {
269 pUM->hwinit.supported[i] &= ~ELINK_SUPPORTED_2500baseX_Full;
270 }
271 else
272 {
273 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
274 " 2.5G");
275 }
276
277 if (!(pLM->params.link.speed_cap_mask[i] &
278 PORT_HW_CFG_SPEED_CAPABILITY_D0_10G))
279 {
280 pUM->hwinit.supported[i] &= ~ELINK_SUPPORTED_10000baseT_Full;
281 }
282 else
283 {
284 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
285 " 10G");
286 }
287
288 if (!(pLM->params.link.speed_cap_mask[i] &
289 PORT_HW_CFG_SPEED_CAPABILITY_D0_20G))
290 {
291 pUM->hwinit.supported[i] &= ~(ELINK_SUPPORTED_20000baseMLD2_Full |
292 ELINK_SUPPORTED_20000baseKR2_Full);
293 }
294 else
295 {
296 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
297 " 20G");
298 }
299
300 BnxeLogInfo(pUM, buf);
301
302 *buf = 0;
303 snprintf(buf, sizeof(buf), "Phy %d link config:", i);
304
305 switch ((uint32_t)pLM->hw_info.link_config[i] &
306 PORT_FEATURE_CONNECTED_SWITCH_MASK)
307 {
308 case PORT_FEATURE_CON_SWITCH_1G_SWITCH:
309 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
310 " switch/1G");
311 break;
312 case PORT_FEATURE_CON_SWITCH_10G_SWITCH:
313 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
314 " switch/10G");
315 break;
316 case PORT_FEATURE_CON_SWITCH_AUTO_DETECT:
317 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
318 " switch/auto");
319 break;
320 case PORT_FEATURE_CON_SWITCH_ONE_TIME_DETECT:
321 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
322 " switch/once");
323 break;
324 default:
325 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
326 " switch/unknown");
327 break;
328 }
329
330 switch ((uint32_t)pLM->hw_info.link_config[i] &
331 PORT_FEATURE_LINK_SPEED_MASK)
332 {
333 case PORT_FEATURE_LINK_SPEED_AUTO:
334 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
335 " speed/auto");
336 break;
337 case PORT_FEATURE_LINK_SPEED_10M_FULL:
338 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
339 " speed/10M/full");
340 break;
341 case PORT_FEATURE_LINK_SPEED_10M_HALF:
342 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
343 " speed/10M/half");
344 break;
345 case PORT_FEATURE_LINK_SPEED_100M_HALF:
346 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
347 " speed/100M/half");
348 break;
349 case PORT_FEATURE_LINK_SPEED_100M_FULL:
350 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
351 " speed/100M/full");
352 break;
353 case PORT_FEATURE_LINK_SPEED_1G:
354 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
355 " speed/1G");
356 break;
357 case PORT_FEATURE_LINK_SPEED_2_5G:
358 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
359 " speed/2.5G");
360 break;
361 case PORT_FEATURE_LINK_SPEED_10G_CX4:
362 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
363 " speed/10G");
364 break;
365 case PORT_FEATURE_LINK_SPEED_20G:
366 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
367 " speed/20G");
368 break;
369 default:
370 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
371 " speed/unknown");
372 break;
373 }
374
375 switch ((uint32_t)pLM->hw_info.link_config[i] &
376 PORT_FEATURE_FLOW_CONTROL_MASK)
377 {
378 case PORT_FEATURE_FLOW_CONTROL_AUTO:
379 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
380 " flow/auto");
381 break;
382 case PORT_FEATURE_FLOW_CONTROL_TX:
383 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
384 " flow/tx");
385 break;
386 case PORT_FEATURE_FLOW_CONTROL_RX:
387 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
388 " flow/rx");
389 break;
390 case PORT_FEATURE_FLOW_CONTROL_BOTH:
391 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
392 " flow/both");
393 break;
394 case PORT_FEATURE_FLOW_CONTROL_NONE:
395 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
396 " flow/none");
397 break;
398 default:
399 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
400 " flow/unknown");
401 break;
402 }
403
404 BnxeLogInfo(pUM, buf);
405 }
406
407 for (i = 0; i < pUM->hwinit.phy_cfg_size; i++)
408 {
409 *buf = 0;
410 snprintf(buf, sizeof(buf), "Requesting Phy %d speed:", i);
411
412 if (pUM->curcfg.lnkcfg.param_10hdx)
413 {
414 if (((pLM->hw_info.link_config[i] &
415 PORT_FEATURE_LINK_SPEED_MASK) ==
416 PORT_FEATURE_LINK_SPEED_AUTO) ||
417 ((pLM->hw_info.link_config[i] &
418 PORT_FEATURE_LINK_SPEED_MASK) ==
419 PORT_FEATURE_LINK_SPEED_10M_HALF))
420 {
421 medium |= (LM_MEDIUM_SPEED_10MBPS | LM_MEDIUM_HALF_DUPLEX);
422 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
423 " 10M/half");
424 }
425 else
426 {
427 BnxeLogWarn(pUM, "Phy 10hdx requested but not supported");
428 }
429 }
430
431 if (pUM->curcfg.lnkcfg.param_10fdx)
432 {
433 if (((pLM->hw_info.link_config[i] &
434 PORT_FEATURE_LINK_SPEED_MASK) ==
435 PORT_FEATURE_LINK_SPEED_AUTO) ||
436 ((pLM->hw_info.link_config[i] &
437 PORT_FEATURE_LINK_SPEED_MASK) ==
438 PORT_FEATURE_LINK_SPEED_10M_FULL))
439 {
440 medium |= (LM_MEDIUM_SPEED_10MBPS | LM_MEDIUM_FULL_DUPLEX);
441 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
442 " 10M/full");
443 }
444 else
445 {
446 BnxeLogWarn(pUM, "Phy 10fdx requested but not supported");
447 }
448 }
449
450 if (pUM->curcfg.lnkcfg.param_100hdx)
451 {
452 if (((pLM->hw_info.link_config[i] &
453 PORT_FEATURE_LINK_SPEED_MASK) ==
454 PORT_FEATURE_LINK_SPEED_AUTO) ||
455 ((pLM->hw_info.link_config[i] &
456 PORT_FEATURE_LINK_SPEED_MASK) ==
457 PORT_FEATURE_LINK_SPEED_100M_HALF))
458 {
459 medium |= (LM_MEDIUM_SPEED_100MBPS | LM_MEDIUM_HALF_DUPLEX);
460 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
461 " 100M/half");
462 }
463 else
464 {
465 BnxeLogWarn(pUM, "Phy 100hdx requested but not supported");
466 }
467 }
468
469 if (pUM->curcfg.lnkcfg.param_100fdx)
470 {
471 if (((pLM->hw_info.link_config[i] &
472 PORT_FEATURE_LINK_SPEED_MASK) ==
473 PORT_FEATURE_LINK_SPEED_AUTO) ||
474 ((pLM->hw_info.link_config[i] &
475 PORT_FEATURE_LINK_SPEED_MASK) ==
476 PORT_FEATURE_LINK_SPEED_100M_FULL))
477 {
478 medium |= (LM_MEDIUM_SPEED_100MBPS | LM_MEDIUM_FULL_DUPLEX);
479 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
480 " 100M/full");
481 }
482 else
483 {
484 BnxeLogWarn(pUM, "Phy 100fdx requested but not supported");
485 }
486 }
487
488 if (pUM->curcfg.lnkcfg.param_1000fdx)
489 {
490 if (((pLM->hw_info.link_config[i] &
491 PORT_FEATURE_LINK_SPEED_MASK) ==
492 PORT_FEATURE_LINK_SPEED_AUTO) ||
493 ((pLM->hw_info.link_config[i] &
494 PORT_FEATURE_LINK_SPEED_MASK) ==
495 PORT_FEATURE_LINK_SPEED_1G))
496 {
497 medium |= (LM_MEDIUM_SPEED_1000MBPS | LM_MEDIUM_FULL_DUPLEX);
498 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
499 " 1G");
500 }
501 else
502 {
503 BnxeLogWarn(pUM, "Phy 1000fdx requested but not supported");
504 }
505 }
506
507 if (pUM->curcfg.lnkcfg.param_10000fdx)
508 {
509 if (((pLM->hw_info.link_config[i] &
510 PORT_FEATURE_LINK_SPEED_MASK) ==
511 PORT_FEATURE_LINK_SPEED_AUTO) ||
512 ((pLM->hw_info.link_config[i] &
513 PORT_FEATURE_LINK_SPEED_MASK) ==
514 PORT_FEATURE_LINK_SPEED_10G_CX4))
515 {
516 medium |= (LM_MEDIUM_SPEED_10GBPS | LM_MEDIUM_FULL_DUPLEX);
517 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
518 " 10G");
519 }
520 else
521 {
522 BnxeLogWarn(pUM, "Phy 10000fdx requested but not supported");
523 }
524 }
525
526 if (pUM->curcfg.lnkcfg.param_20000fdx)
527 {
528 if (((pLM->hw_info.link_config[i] &
529 PORT_FEATURE_LINK_SPEED_MASK) ==
530 PORT_FEATURE_LINK_SPEED_AUTO) ||
531 ((pLM->hw_info.link_config[i] &
532 PORT_FEATURE_LINK_SPEED_MASK) ==
533 PORT_FEATURE_LINK_SPEED_20G))
534 {
535 medium |= (LM_MEDIUM_SPEED_20GBPS | LM_MEDIUM_FULL_DUPLEX);
536 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
537 " 20G");
538 }
539 else
540 {
541 BnxeLogWarn(pUM, "Phy 20000fdx requested but not supported");
542 }
543 }
544
545 if (pUM->curcfg.lnkcfg.link_autoneg)
546 {
547 if ((pLM->hw_info.link_config[i] &
548 PORT_FEATURE_LINK_SPEED_MASK) ==
549 PORT_FEATURE_LINK_SPEED_AUTO)
550 {
551 if (medium)
552 {
553 BnxeLogWarn(pUM, "Phy autoneg requested along with other speeds, ignoring others and forcing autoneg");
554 }
555
556 medium = LM_MEDIUM_SPEED_AUTONEG; /* 0x0000 */
557 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
558 " auto");
559 }
560 else
561 {
562 BnxeLogWarn(pUM, "Phy autoneg requested but not supported");
563 }
564 }
565
566 BnxeLogInfo(pUM, buf);
567 }
568
569 medium |= LM_MEDIUM_TYPE_XGXS;
570
571 return medium;
572 }
573
574
BnxeHwReqPhyFlowSettings(um_device_t * pUM)575 lm_flow_control_t BnxeHwReqPhyFlowSettings(um_device_t * pUM)
576 {
577 lm_device_t * pLM = &pUM->lm_dev;
578 lm_flow_control_t flowctrl;
579 char buf[128];
580 int i;
581
582 flowctrl = LM_FLOW_CONTROL_NONE;
583
584 for (i = 0; i < pUM->hwinit.phy_cfg_size; i++)
585 {
586 *buf = 0;
587 snprintf(buf, sizeof(buf), "Requesting Phy %d flow:", i);
588
589 if (pUM->curcfg.lnkcfg.param_txpause)
590 {
591 if ((pLM->hw_info.link_config[i] &
592 PORT_FEATURE_FLOW_CONTROL_MASK) &
593 PORT_FEATURE_FLOW_CONTROL_TX)
594 {
595 flowctrl |= LM_FLOW_CONTROL_TRANSMIT_PAUSE;
596 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
597 " tx");
598 }
599 else
600 {
601 BnxeLogWarn(pUM, "Phy TX flow requested but not supported");
602 }
603 }
604
605 if (pUM->curcfg.lnkcfg.param_rxpause)
606 {
607 if ((pLM->hw_info.link_config[i] &
608 PORT_FEATURE_FLOW_CONTROL_MASK) &
609 PORT_FEATURE_FLOW_CONTROL_RX)
610 {
611 flowctrl |= LM_FLOW_CONTROL_RECEIVE_PAUSE;
612 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
613 " rx");
614 }
615 else
616 {
617 BnxeLogWarn(pUM, "Phy RX flow requested but not supported");
618 }
619 }
620
621 if (pUM->curcfg.flow_autoneg)
622 {
623 /*
624 * This value can be or'ed with receive pause and transmit
625 * pause. If the auto-negotiation is disabled and the receive
626 * pause and transmit pause bits are set, then flow control is
627 * enabled regardless of link partner's flow control capability.
628 * Otherwise, if this bit is set, then flow is negotiated with
629 * the link partner. Values 0x80000000 and 0x80000003 are
630 * equivalent.
631 */
632 if ((pLM->hw_info.link_config[i] &
633 PORT_FEATURE_FLOW_CONTROL_MASK) ==
634 PORT_FEATURE_FLOW_CONTROL_AUTO)
635 {
636 flowctrl |= LM_FLOW_CONTROL_AUTO_PAUSE;
637 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)),
638 " auto");
639 }
640 else
641 {
642 BnxeLogWarn(pUM, "Phy Auto flow requested but not supported");
643 }
644 }
645
646 BnxeLogInfo(pUM, buf);
647 }
648
649 return flowctrl;
650 }
651
652
BnxeUpdatePhy(um_device_t * pUM)653 void BnxeUpdatePhy(um_device_t * pUM)
654 {
655 lm_device_t * pLM = &pUM->lm_dev;
656 int rc;
657
658 BNXE_LOCK_ENTER_PHY(pUM);
659
660 pLM->params.req_medium = BnxeHwReqPhyMediumSettings(pUM);
661 pLM->params.flow_ctrl_cap = BnxeHwReqPhyFlowSettings(pUM);
662
663 if (IS_PMF(&pUM->lm_dev))
664 {
665 lm_reset_link(pLM);
666 }
667
668 rc = lm_init_phy(pLM,
669 pLM->params.req_medium,
670 pLM->params.flow_ctrl_cap,
671 0 /* pLM->params.selective_autoneg */,
672 0 /* pLM->params.wire_speed */,
673 0);
674
675 if (pUM->fmCapabilities &&
676 BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK)
677 {
678 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED);
679 }
680
681 if (rc == LM_STATUS_SUCCESS)
682 {
683 pUM->phyInitialized = B_TRUE;
684 }
685 else
686 {
687 BnxeLogWarn(pUM, "Failed to initialize the phy (%d)", rc);
688 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE);
689 }
690
691 #if 0
692 /*
693 * This is problematic. For non-PMF functions the lm_niv_vif_set for
694 * a link up will come very early and is queued for processing right
695 * after lm_chip_start. Thereafter setting the loopback mode brings
696 * the interface back down. Don't know if setting the loopback mode
697 * is even required when forcing it off. XXX
698 */
699 if (IS_MF_AFEX_MODE(&pUM->lm_dev))
700 {
701 lm_niv_set_loopback_mode(&pUM->lm_dev, FALSE);
702 }
703 #endif
704
705 BNXE_LOCK_EXIT_PHY(pUM);
706 }
707
708
709 /*
710 * (flag) TRUE = add, FALSE = remove
711 *
712 * This function must be called with BNXE_LOCK_ENTER_HWINIT held because this
713 * is shared between GLDv3 and FCoE entry points.
714 */
BnxeMacAddress(um_device_t * pUM,int cliIdx,boolean_t flag,const uint8_t * pMacAddr)715 int BnxeMacAddress(um_device_t * pUM,
716 int cliIdx,
717 boolean_t flag,
718 const uint8_t * pMacAddr)
719 {
720 int i, rc;
721
722 if ((cliIdx != LM_CLI_IDX_NDIS) && (cliIdx != LM_CLI_IDX_FCOE))
723 {
724 return EINVAL;
725 }
726
727 BnxeLogDbg(pUM, "%s MAC address: %02x:%02x:%02x:%02x:%02x:%02x",
728 (flag) ? "Adding" : "Removing",
729 pMacAddr[0], pMacAddr[1], pMacAddr[2],
730 pMacAddr[3], pMacAddr[4], pMacAddr[5]);
731
732 rc = lm_set_mac_addr(&pUM->lm_dev,
733 (u8_t *)pMacAddr,
734 /* XXX */ LM_SET_CAM_NO_VLAN_FILTER,
735 LM_CLI_CID(&pUM->lm_dev, cliIdx),
736 NULL, flag, 0);
737
738 if (rc == LM_STATUS_PENDING)
739 {
740 if ((rc = lm_wait_set_mac_done(&pUM->lm_dev,
741 LM_CLI_CID(&pUM->lm_dev, cliIdx))) !=
742 LM_STATUS_SUCCESS)
743 {
744 BnxeLogWarn(pUM, "Failed to %s MAC Address from pending operation (%d)",
745 (flag) ? "set" : "remove", rc);
746 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_NO_RESPONSE);
747 return ENOMEM;
748 }
749 }
750 else if ((rc != LM_STATUS_PENDING) && (rc != LM_STATUS_EXISTING_OBJECT))
751 {
752 BnxeLogWarn(pUM, "Failed to %s MAC Address (%d)",
753 (flag) ? "set" : "remove", rc);
754 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE);
755 return ENOMEM;
756 }
757
758 return 0;
759 }
760
761
762 /*
763 * This function is used to enable or disable multicast packet reception for
764 * particular multicast addresses. (flag) TRUE = add, FALSE = remove.
765 *
766 * This function must be called with BNXE_LOCK_ENTER_HWINIT held because this
767 * is shared between GLDv3 and FCoE entry points.
768 */
769
BnxeMulticastE1(um_device_t * pUM,int cliIdx)770 void BnxeMulticastE1(um_device_t * pUM,
771 int cliIdx)
772 {
773 if ((cliIdx != LM_CLI_IDX_NDIS) || !CHIP_IS_E1(&pUM->lm_dev))
774 {
775 return;
776 }
777
778 /* already holding BNXE_LOCK_ENTER_HWINIT */
779
780 if (d_list_entry_cnt(&pUM->mcast_l2) > 64)
781 {
782 if (!(pUM->devParams.rx_filter_mask[LM_CLI_IDX_NDIS] &
783 LM_RX_MASK_ACCEPT_ALL_MULTICAST))
784 {
785 BnxeLogInfo(pUM, "Turning ON the ALL_MCAST rx mask, number of multicast addressess is >64");
786
787 pUM->devParams.rx_filter_mask[LM_CLI_IDX_NDIS] |=
788 LM_RX_MASK_ACCEPT_ALL_MULTICAST;
789
790 BnxeRxMask(pUM, LM_CLI_IDX_NDIS,
791 pUM->devParams.rx_filter_mask[LM_CLI_IDX_NDIS]);
792 }
793 }
794 else
795 {
796 if (pUM->devParams.rx_filter_mask[LM_CLI_IDX_NDIS] &
797 LM_RX_MASK_ACCEPT_ALL_MULTICAST)
798 {
799 BnxeLogInfo(pUM, "Turning OFF the ALL_MCAST rx mask, number of multicast addressess is <=64");
800
801 pUM->devParams.rx_filter_mask[LM_CLI_IDX_NDIS] &=
802 ~LM_RX_MASK_ACCEPT_ALL_MULTICAST;
803
804 BnxeRxMask(pUM, LM_CLI_IDX_NDIS,
805 pUM->devParams.rx_filter_mask[LM_CLI_IDX_NDIS]);
806 }
807 }
808 }
809
BnxeMulticast(um_device_t * pUM,int cliIdx,boolean_t flag,const uint8_t * pMcastAddr,boolean_t hwSet)810 int BnxeMulticast(um_device_t * pUM,
811 int cliIdx,
812 boolean_t flag,
813 const uint8_t * pMcastAddr,
814 boolean_t hwSet)
815 {
816 struct ecore_mcast_list_elem * pTmp;
817 d_list_t * mcastList;
818 int i, rc;
819
820 if ((cliIdx != LM_CLI_IDX_NDIS) && (cliIdx != LM_CLI_IDX_FCOE))
821 {
822 return EINVAL;
823 }
824
825 if (!pMcastAddr)
826 {
827 BnxeLogInfo(pUM, "Removing all multicast");
828 }
829 else
830 {
831 BnxeLogInfo(pUM, "%s multicast: %02x:%02x:%02x:%02x:%02x:%02x",
832 (flag) ? "Adding" : "Removing",
833 pMcastAddr[0], pMcastAddr[1], pMcastAddr[2],
834 pMcastAddr[3], pMcastAddr[4], pMcastAddr[5]);
835 }
836
837 mcastList = (cliIdx == LM_CLI_IDX_NDIS) ? &pUM->mcast_l2 :
838 &pUM->mcast_fcoe;
839
840 if (flag && (pMcastAddr == NULL))
841 {
842 /* adding a new address that isn't specified...? */
843 BnxeLogWarn(pUM, "ERROR: Multicast address not specified");
844 return EINVAL;
845 }
846 else if (!flag && (pMcastAddr == NULL))
847 {
848 /* clear all multicast addresses */
849
850 while (d_list_entry_cnt(mcastList))
851 {
852 pTmp = (struct ecore_mcast_list_elem *)d_list_pop_head(mcastList);
853 kmem_free(pTmp, (sizeof(struct ecore_mcast_list_elem) +
854 ETHERNET_ADDRESS_SIZE));
855 }
856
857 if (!hwSet)
858 {
859 return 0;
860 }
861
862 rc = lm_set_mc_list(&pUM->lm_dev, mcastList, NULL, cliIdx);
863
864 if (rc == LM_STATUS_PENDING)
865 {
866 if ((rc = lm_wait_set_mc_done(&pUM->lm_dev, cliIdx)) !=
867 LM_STATUS_SUCCESS)
868 {
869 BnxeLogWarn(pUM, "Failed to clear Multicast Address table from pending operation (%d)", rc);
870 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_NO_RESPONSE);
871 return ENOMEM;
872 }
873 }
874 else if (rc != LM_STATUS_SUCCESS)
875 {
876 BnxeLogWarn(pUM, "Failed to clear Multicast Address table (%d)", rc);
877 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE);
878 return ENOMEM;
879 }
880
881 BnxeMulticastE1(pUM, cliIdx);
882
883 return 0;
884 }
885
886 /* check if this address already exists in the table */
887 pTmp = (struct ecore_mcast_list_elem *)d_list_peek_head(mcastList);
888 while (pTmp)
889 {
890 if (IS_ETH_ADDRESS_EQUAL(pMcastAddr, pTmp->mac))
891 {
892 break;
893 }
894
895 pTmp = (struct ecore_mcast_list_elem *)d_list_next_entry(D_LINK_CAST(pTmp));
896 }
897
898 if (flag)
899 {
900 /* only add the address if the table is empty or address not found */
901 if (pTmp == NULL)
902 {
903 if ((pTmp = kmem_zalloc((sizeof(struct ecore_mcast_list_elem) +
904 ETHERNET_ADDRESS_SIZE),
905 KM_NOSLEEP)) == NULL)
906 {
907 BnxeLogWarn(pUM, "Failed to alloc Multicast Address node");
908 return ENOMEM;
909 }
910
911 pTmp->mac = (u8_t *)pTmp + sizeof(struct ecore_mcast_list_elem);
912
913 COPY_ETH_ADDRESS(pMcastAddr, pTmp->mac);
914
915 d_list_push_head(mcastList, D_LINK_CAST(pTmp));
916 }
917 }
918 else /* (!flag) */
919 {
920 if (pTmp == NULL)
921 {
922 /* the address isn't in the table */
923 return ENXIO;
924 }
925
926 d_list_remove_entry(mcastList, D_LINK_CAST(pTmp));
927
928 kmem_free(pTmp, (sizeof(struct ecore_mcast_list_elem) +
929 ETHERNET_ADDRESS_SIZE));
930 }
931
932 if (!hwSet)
933 {
934 return 0;
935 }
936
937 rc = lm_set_mc_list(&pUM->lm_dev, mcastList, NULL, cliIdx);
938
939 if (rc == LM_STATUS_PENDING)
940 {
941 if ((rc = lm_wait_set_mc_done(&pUM->lm_dev, cliIdx)) !=
942 LM_STATUS_SUCCESS)
943 {
944 BnxeLogWarn(pUM, "Failed to set Multicast Address table from pending operation (%d)", rc);
945 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_NO_RESPONSE);
946 return ENOMEM;
947 }
948 }
949 else if (rc != LM_STATUS_SUCCESS)
950 {
951 BnxeLogWarn(pUM, "Failed to set Multicast Address table (%d)", rc);
952 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE);
953 return ENOMEM;
954 }
955
956 BnxeMulticastE1(pUM, cliIdx);
957
958 return 0;
959 }
960
961
962 /*
963 * This function must be called with BNXE_LOCK_ENTER_HWINIT held because this
964 * is shared between GLDv3 and FCoE entry points.
965 */
BnxeRxMask(um_device_t * pUM,int cliIdx,lm_rx_mask_t mask)966 int BnxeRxMask(um_device_t * pUM,
967 int cliIdx,
968 lm_rx_mask_t mask)
969 {
970 int rc;
971
972 if ((cliIdx != LM_CLI_IDX_NDIS) && (cliIdx != LM_CLI_IDX_FCOE))
973 {
974 return EINVAL;
975 }
976
977 pUM->devParams.rx_filter_mask[cliIdx] = mask;
978
979 rc = lm_set_rx_mask(&pUM->lm_dev,
980 LM_CLI_CID(&pUM->lm_dev, cliIdx), mask, NULL);
981
982 if (rc == LM_STATUS_PENDING)
983 {
984 if ((rc =
985 lm_wait_set_rx_mask_done(&pUM->lm_dev,
986 LM_CLI_CID(&pUM->lm_dev, cliIdx))) !=
987 LM_STATUS_SUCCESS)
988 {
989 BnxeLogWarn(pUM, "Failed to set Rx mask from pending operation (%d)", rc);
990 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_NO_RESPONSE);
991 return ENOMEM;
992 }
993 }
994
995 if (pUM->fmCapabilities &&
996 BnxeCheckAccHandle(pUM->lm_dev.vars.reg_handle[BAR_0]) != DDI_FM_OK)
997 {
998 BnxeLogWarn(pUM, "DMA fault when setting Rx mask");
999 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_LOST);
1000 return ENOMEM;
1001 }
1002
1003 if (rc != LM_STATUS_SUCCESS)
1004 {
1005 BnxeLogWarn(pUM, "Failed to set Rx mask (%d)", rc);
1006 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE);
1007 return ENOMEM;
1008 }
1009
1010 return 0;
1011 }
1012
1013
BnxeEstablishHwConn(um_device_t * pUM,int cid)1014 boolean_t BnxeEstablishHwConn(um_device_t * pUM,
1015 int cid)
1016 {
1017 lm_device_t * pLM = &pUM->lm_dev;
1018 lm_client_con_params_t cliParams;
1019 int sb_id;
1020 int rc;
1021
1022 sb_id = lm_sb_id_from_chain(&pUM->lm_dev, cid);
1023
1024 memset(&cliParams, 0, sizeof(cliParams));
1025 cliParams.mtu = pUM->devParams.mtu[LM_CHAIN_IDX_CLI(pLM, cid)];
1026 //cliParams.lah_size = pUM->devParams.mtu[LM_CHAIN_IDX_CLI(pLM, cid)];
1027 cliParams.lah_size = 0;
1028 cliParams.num_rx_desc = pUM->devParams.numRxDesc[LM_CHAIN_IDX_CLI(pLM, cid)];
1029 cliParams.num_tx_desc = pUM->devParams.numTxDesc[LM_CHAIN_IDX_CLI(pLM, cid)];
1030 cliParams.attributes = (LM_CLIENT_ATTRIBUTES_RX |
1031 LM_CLIENT_ATTRIBUTES_TX |
1032 LM_CLIENT_ATTRIBUTES_REG_CLI);
1033
1034 BnxeLogDbg(pUM, "Setting up client for cid %d", cid);
1035 if (lm_setup_client_con_params(pLM, cid, &cliParams) != LM_STATUS_SUCCESS)
1036 {
1037 BnxeLogWarn(pUM, "Failed to setup client for cid %d", cid);
1038 return B_FALSE;
1039 }
1040
1041 /*********************************************************/
1042
1043 BnxeLogDbg(pUM, "Initializing client for cid %d", cid);
1044 rc = lm_init_chain_con(pLM, cid, TRUE);
1045
1046 if (pUM->fmCapabilities &&
1047 BnxeCheckAccHandle(pUM->pPciCfg) != DDI_FM_OK)
1048 {
1049 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_LOST);
1050 return B_FALSE;
1051 }
1052
1053 if (pUM->fmCapabilities &&
1054 BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK)
1055 {
1056 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_LOST);
1057 return B_FALSE;
1058 }
1059
1060 if (rc != LM_STATUS_SUCCESS)
1061 {
1062 BnxeLogWarn(pUM, "Failed to initialize client for cid %d", cid);
1063 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE);
1064 return B_FALSE;
1065 }
1066
1067 /*********************************************************/
1068
1069 BnxeLogDbg(pUM, "Establishing client for cid %d", cid);
1070 rc = lm_establish_eth_con(pLM, cid, sb_id,
1071 pLM->params.l2_cli_con_params[cid].attributes);
1072
1073 if (pUM->fmCapabilities &&
1074 BnxeCheckAccHandle(pUM->pPciCfg) != DDI_FM_OK)
1075 {
1076 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_LOST);
1077 return B_FALSE;
1078 }
1079
1080 if (pUM->fmCapabilities &&
1081 BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK)
1082 {
1083 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_LOST);
1084 return B_FALSE;
1085 }
1086
1087 if (rc != LM_STATUS_SUCCESS)
1088 {
1089 BnxeLogWarn(pUM, "Failed to establish client connection");
1090 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE);
1091 return B_FALSE;
1092 }
1093
1094 return B_TRUE;
1095 }
1096
1097
BnxeHwStartFCOE(um_device_t * pUM)1098 int BnxeHwStartFCOE(um_device_t * pUM)
1099 {
1100 lm_device_t * pLM = &pUM->lm_dev;
1101 int rc;
1102
1103 if (!BNXE_FCOE(pUM))
1104 {
1105 BnxeDbgBreakMsg(pUM, "Inside BnxeHwStartFCOE and FCoE not supported!");
1106 return -1;
1107 }
1108
1109 BNXE_LOCK_ENTER_HWINIT(pUM);
1110
1111 BnxeLogInfo(pUM, "BnxeHwStartFCOE: Starting FCoE (clients %s)",
1112 BnxeClientsHw(pUM));
1113
1114 if (BnxeHwStartCore(pUM))
1115 {
1116 goto BnxeHwStartFCOE_error;
1117 }
1118
1119 if (!pUM->hwInitDone)
1120 {
1121 BnxeLogWarn(pUM, "BnxeHwStartFCOE: Failed, hardware not initialized (clients %s)",
1122 BnxeClientsHw(pUM));
1123 goto BnxeHwStartFCOE_error;
1124 }
1125
1126 /*********************************************************/
1127
1128 BnxeLogDbg(pUM, "Allocating FCoE Resources");
1129
1130 if (lm_fc_alloc_resc(&pUM->lm_dev) != LM_STATUS_SUCCESS)
1131 {
1132 BnxeLogWarn(pUM, "Failed to allocate FCoE resources");
1133 goto BnxeHwStartFCOE_error;
1134 }
1135
1136 /*********************************************************/
1137
1138 BnxeLogDbg(pUM, "Opening FCoE Ethernet Connection");
1139
1140 pUM->lm_dev.ofld_info.state_blks[STATE_BLOCK_FCOE] =
1141 &pUM->lm_dev.fcoe_info.run_time.state_blk;
1142
1143 if (!BnxeEstablishHwConn(pUM, FCOE_CID(pLM)))
1144 {
1145 goto BnxeHwStartFCOE_error;
1146 }
1147
1148 /*********************************************************/
1149
1150 BnxeLogDbg(pUM, "Initializing FCoE Tx Pkts");
1151
1152 if (BnxeTxPktsInit(pUM, LM_CLI_IDX_FCOE))
1153 {
1154 BnxeLogWarn(pUM, "Failed to allocate FCoE Tx resources");
1155 goto BnxeHwStartFCOE_error;
1156 }
1157
1158 /*********************************************************/
1159
1160 BnxeLogDbg(pUM, "Initializing FCoE Rx Pkts");
1161
1162 if (BnxeRxPktsInit(pUM, LM_CLI_IDX_FCOE))
1163 {
1164 BnxeLogWarn(pUM, "Failed to allocate FCoE Rx resources");
1165 goto BnxeHwStartFCOE_error;
1166 }
1167
1168 if (BnxeRxPktsInitPostBuffers(pUM, LM_CLI_IDX_FCOE))
1169 {
1170 BnxeLogWarn(pUM, "Failed to post FCoE Rx buffers");
1171 goto BnxeHwStartFCOE_error;
1172 }
1173
1174 /*********************************************************/
1175
1176 BnxeLogDbg(pUM, "Setting FCoE MAC Address");
1177
1178 if (BnxeMacAddress(pUM, LM_CLI_IDX_FCOE, B_TRUE,
1179 pLM->hw_info.fcoe_mac_addr) < 0)
1180 {
1181 goto BnxeHwStartFCOE_error;
1182 }
1183
1184 /*********************************************************/
1185
1186 BnxeLogDbg(pUM, "Setting FCoE Multicast Addresses");
1187
1188 #define ALL_FCOE_MACS (const uint8_t *)"\x01\x10\x18\x01\x00\x00"
1189 #define ALL_ENODE_MACS (const uint8_t *)"\x01\x10\x18\x01\x00\x01"
1190
1191 if ((BnxeMulticast(pUM, LM_CLI_IDX_FCOE, B_TRUE, ALL_FCOE_MACS, B_FALSE) < 0) ||
1192 (BnxeMulticast(pUM, LM_CLI_IDX_FCOE, B_TRUE, ALL_ENODE_MACS, B_TRUE) < 0))
1193 {
1194 goto BnxeHwStartFCOE_error;
1195 }
1196
1197 /*********************************************************/
1198
1199 BnxeLogDbg(pUM, "Turning on FCoE Rx Mask");
1200
1201 if (BnxeRxMask(pUM, LM_CLI_IDX_FCOE, (
1202 LM_RX_MASK_ACCEPT_UNICAST
1203 //| LM_RX_MASK_ACCEPT_ALL_MULTICAST
1204 | LM_RX_MASK_ACCEPT_MULTICAST
1205 //| LM_RX_MASK_ACCEPT_BROADCAST
1206 //| LM_RX_MASK_PROMISCUOUS_MODE
1207 )) < 0)
1208 {
1209 goto BnxeHwStartFCOE_error;
1210 }
1211
1212 /*********************************************************/
1213
1214 CLIENT_HW_SET(pUM, LM_CLI_IDX_FCOE);
1215
1216 BnxeLogInfo(pUM, "BnxeHwStartFCOE: FCoE started (clients %s)",
1217 BnxeClientsHw(pUM));
1218
1219 BNXE_LOCK_EXIT_HWINIT(pUM);
1220 return 0;
1221
1222 BnxeHwStartFCOE_error:
1223
1224 BNXE_LOCK_EXIT_HWINIT(pUM);
1225 return -1;
1226 }
1227
1228
BnxeHwStartL2(um_device_t * pUM)1229 int BnxeHwStartL2(um_device_t * pUM)
1230 {
1231 lm_device_t * pLM = &pUM->lm_dev;
1232 int idx, rc;
1233
1234 BNXE_LOCK_ENTER_HWINIT(pUM);
1235
1236 BnxeLogInfo(pUM, "BnxeHwStartL2: Starting L2 (clients %s)",
1237 BnxeClientsHw(pUM));
1238
1239 if (BnxeHwStartCore(pUM))
1240 {
1241 goto BnxeHwStartL2_error;
1242 }
1243
1244 if (!pUM->hwInitDone)
1245 {
1246 BnxeLogWarn(pUM, "BnxeHwStartL2: Failed, hardware not initialized (clients %s)",
1247 BnxeClientsHw(pUM));
1248 goto BnxeHwStartL2_error;
1249 }
1250
1251 /*********************************************************/
1252
1253 BnxeLogDbg(pUM, "Opening L2 Ethernet Connections (%d)",
1254 pLM->params.rss_chain_cnt);
1255
1256 LM_FOREACH_RSS_IDX(pLM, idx)
1257 {
1258 if (!BnxeEstablishHwConn(pUM, idx))
1259 {
1260 goto BnxeHwStartL2_error;
1261 }
1262 }
1263
1264 /*********************************************************/
1265
1266 BnxeLogDbg(pUM, "Initializing Tx Pkts");
1267
1268 if (BnxeTxPktsInit(pUM, LM_CLI_IDX_NDIS))
1269 {
1270 BnxeLogWarn(pUM, "Failed to allocate tx resources");
1271 goto BnxeHwStartL2_error;
1272 }
1273
1274 /*********************************************************/
1275
1276 BnxeLogDbg(pUM, "Initializing Rx Pkts");
1277
1278 if (BnxeRxPktsInit(pUM, LM_CLI_IDX_NDIS))
1279 {
1280 BnxeLogWarn(pUM, "Failed to allocate L2 Rx resources");
1281 goto BnxeHwStartL2_error;
1282 }
1283
1284 if (BnxeRxPktsInitPostBuffers(pUM, LM_CLI_IDX_NDIS))
1285 {
1286 BnxeLogWarn(pUM, "Failed to post L2 Rx buffers");
1287 goto BnxeHwStartL2_error;
1288 }
1289
1290 /*********************************************************/
1291
1292 BnxeLogDbg(pUM, "Enabling RSS");
1293
1294 if (!BnxeRssEnable(pUM))
1295 {
1296 goto BnxeHwStartL2_error;
1297 }
1298
1299 /*********************************************************/
1300
1301 BnxeLogDbg(pUM, "Setting L2 MAC Address");
1302
1303 /* use the hw programmed address (GLDv3 will overwrite if needed) */
1304
1305 {
1306 u8_t zero_mac_addr[ETHERNET_ADDRESS_SIZE];
1307 memset(zero_mac_addr, 0, ETHERNET_ADDRESS_SIZE);
1308
1309 if (IS_ETH_ADDRESS_EQUAL(pUM->gldMac, zero_mac_addr))
1310 {
1311 COPY_ETH_ADDRESS(pUM->lm_dev.hw_info.mac_addr,
1312 pUM->lm_dev.params.mac_addr);
1313 }
1314 else
1315 {
1316 COPY_ETH_ADDRESS(pUM->gldMac,
1317 pUM->lm_dev.params.mac_addr);
1318 }
1319 }
1320
1321 if (BnxeMacAddress(pUM, LM_CLI_IDX_NDIS, B_TRUE,
1322 pUM->lm_dev.params.mac_addr) < 0)
1323 {
1324 goto BnxeHwStartL2_error;
1325 }
1326
1327 /*********************************************************/
1328
1329 BnxeLogDbg(pUM, "Turning on L2 Rx Mask");
1330
1331 if (BnxeRxMask(pUM, LM_CLI_IDX_NDIS, (
1332 LM_RX_MASK_ACCEPT_UNICAST
1333 //| LM_RX_MASK_ACCEPT_ALL_MULTICAST
1334 | LM_RX_MASK_ACCEPT_MULTICAST
1335 | LM_RX_MASK_ACCEPT_BROADCAST
1336 //| LM_RX_MASK_PROMISCUOUS_MODE
1337 )) < 0)
1338 {
1339 goto BnxeHwStartL2_error;
1340 }
1341
1342 /*********************************************************/
1343
1344 CLIENT_HW_SET(pUM, LM_CLI_IDX_NDIS);
1345 lm_mcp_indicate_client_bind(&pUM->lm_dev, LM_CLI_IDX_NDIS);
1346
1347 BNXE_LOCK_EXIT_HWINIT(pUM);
1348
1349 /*********************************************************/
1350
1351 /*
1352 * Force a link update. Another client might already be up in which case
1353 * the link status won't change during this plumb of the L2 client.
1354 */
1355 BnxeGldLink(pUM, (pUM->devParams.lastIndLink == LM_STATUS_LINK_ACTIVE) ?
1356 LINK_STATE_UP : LINK_STATE_DOWN);
1357
1358 BnxeLogInfo(pUM, "BnxeHwStartL2: L2 started (clients %s)",
1359 BnxeClientsHw(pUM));
1360
1361 return 0;
1362
1363 BnxeHwStartL2_error:
1364
1365 /* XXX Need cleanup! */
1366
1367 BNXE_LOCK_EXIT_HWINIT(pUM);
1368 return -1;
1369 }
1370
1371
1372 /* Must be called with BNXE_LOCK_ENTER_HWINIT taken! */
BnxeHwStartCore(um_device_t * pUM)1373 int BnxeHwStartCore(um_device_t * pUM)
1374 {
1375 lm_device_t * pLM = &pUM->lm_dev;
1376 int rc;
1377
1378 if (pUM->hwInitDone)
1379 {
1380 /* already initialized */
1381 BnxeLogInfo(pUM, "BnxeHwStartCore: Hardware already initialized (clients %s)",
1382 BnxeClientsHw(pUM));
1383 return 0;
1384 }
1385
1386 BnxeLogInfo(pUM, "BnxeHwStartCore: Starting hardware (clients %s)",
1387 BnxeClientsHw(pUM));
1388
1389 memset(&pLM->debug_info, 0, sizeof(pLM->debug_info));
1390
1391 /*********************************************************/
1392
1393 /* reset the configuration to the hardware default */
1394 BnxeCfgReset(pUM);
1395
1396 pUM->phyInitialized = B_FALSE;
1397
1398 /*********************************************************/
1399
1400 BnxeLogDbg(pUM, "Allocating LM Resources");
1401
1402 if (lm_alloc_resc(pLM) != LM_STATUS_SUCCESS)
1403 {
1404 BnxeLogWarn(pUM, "Failed to allocate resources");
1405 goto BnxeHwStartCore_error;
1406 }
1407
1408 /*********************************************************/
1409
1410 BnxeLogDbg(pUM, "Initializing BRCM Chip");
1411
1412 rc = lm_chip_init(pLM);
1413
1414 if (pUM->fmCapabilities &&
1415 BnxeCheckAccHandle(pUM->pPciCfg) != DDI_FM_OK)
1416 {
1417 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_LOST);
1418 goto BnxeHwStartCore_error;
1419 }
1420
1421 if (pUM->fmCapabilities &&
1422 BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK)
1423 {
1424 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_LOST);
1425 goto BnxeHwStartCore_error;
1426 }
1427
1428 if (rc != LM_STATUS_SUCCESS)
1429 {
1430 BnxeLogWarn(pUM, "Failed to initialize chip");
1431 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE);
1432 goto BnxeHwStartCore_error;
1433 }
1434
1435 /*********************************************************/
1436
1437 BnxeLogDbg(pUM, "Enabling Interrupts");
1438
1439 if (BnxeIntrEnable(pUM))
1440 {
1441 BnxeLogWarn(pUM, "Failed to enable interrupts");
1442 goto BnxeHwStartCore_error;
1443 }
1444
1445 /*********************************************************/
1446
1447 BnxeLogDbg(pUM, "Starting BRCM Chip");
1448
1449 rc = lm_chip_start(pLM);
1450
1451 if (pUM->fmCapabilities &&
1452 BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK)
1453 {
1454 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_LOST);
1455 goto BnxeHwStartCore_error;
1456 }
1457
1458 if (rc != LM_STATUS_SUCCESS)
1459 {
1460 BnxeLogWarn(pUM, "Failed to start chip");
1461 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE);
1462 goto BnxeHwStartCore_error;
1463 }
1464
1465 atomic_swap_32(&pUM->chipStarted, B_TRUE);
1466
1467 /*********************************************************/
1468
1469 BnxeLogDbg(pUM, "Activating pending WorkQ items");
1470
1471 BnxeWorkQueueStartPending(pUM);
1472
1473 /*********************************************************/
1474
1475 BnxeLogDbg(pUM, "Initializing DCBX");
1476
1477 lm_dcbx_init(pLM, B_FALSE); /* B_TRUE for hibernate */
1478
1479 /*********************************************************/
1480
1481 BnxeLogDbg(pUM, "Initializing Phy");
1482
1483 BnxeUpdatePhy(pUM);
1484
1485 /*********************************************************/
1486
1487 BnxeLogDbg(pUM, "Starting Timer");
1488
1489 BnxeTimerStart(pUM);
1490
1491 /*********************************************************/
1492
1493 atomic_swap_32(&pUM->hwInitDone, B_TRUE);
1494
1495 BnxeLogInfo(pUM, "BnxeHwStartCore: Hardware started (clients %s)",
1496 BnxeClientsHw(pUM));
1497
1498 return 0;
1499
1500 BnxeHwStartCore_error:
1501
1502 return -1;
1503 }
1504
1505
BnxeHwStopFCOE(um_device_t * pUM)1506 void BnxeHwStopFCOE(um_device_t * pUM)
1507 {
1508 lm_device_t * pLM = &pUM->lm_dev;
1509 int rc;
1510
1511 if (!BNXE_FCOE(pUM))
1512 {
1513 BnxeDbgBreakMsg(pUM, "Inside BnxeHwStopFCOE and FCoE not supported!");
1514 return;
1515 }
1516
1517 BNXE_LOCK_ENTER_HWINIT(pUM);
1518
1519 BnxeLogInfo(pUM, "BnxeHwStopFCOE: Stopping FCoE (clients %s)",
1520 BnxeClientsHw(pUM));
1521
1522 CLIENT_HW_RESET(pUM, LM_CLI_IDX_FCOE);
1523
1524 /*********************************************************/
1525
1526 BnxeLogDbg(pUM, "Turning off FCoE RX Mask");
1527
1528 BnxeRxMask(pUM, LM_CLI_IDX_FCOE, LM_RX_MASK_ACCEPT_NONE);
1529
1530 /*********************************************************/
1531
1532 BnxeLogDbg(pUM, "Clearing the FCoE Multicast Table");
1533
1534 BnxeMulticast(pUM, LM_CLI_IDX_FCOE, B_FALSE, NULL, B_TRUE);
1535
1536 /*********************************************************/
1537
1538 BnxeLogDbg(pUM, "Closing FCoE Connection");
1539
1540 if ((rc = lm_close_eth_con(pLM, FCOE_CID(pLM), B_TRUE)) !=
1541 LM_STATUS_SUCCESS)
1542 {
1543 BnxeLogWarn(pUM, "Failed to close FCoE conn %d (%d)",
1544 FCOE_CID(pLM), rc);
1545 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE);
1546 }
1547
1548 /*********************************************************/
1549
1550 BnxeLogDbg(pUM, "Aborting FCoE TX Chains");
1551
1552 BnxeTxPktsAbort(pUM, LM_CLI_IDX_FCOE);
1553
1554 /*********************************************************/
1555
1556 BnxeLogDbg(pUM, "Aborting FCoE RX Chains");
1557
1558 BnxeRxPktsAbort(pUM, LM_CLI_IDX_FCOE);
1559
1560 /*********************************************************/
1561
1562 BnxeLogDbg(pUM, "Cleaning up FCoE Tx Pkts");
1563
1564 BnxeTxPktsFini(pUM, LM_CLI_IDX_FCOE);
1565
1566 /*********************************************************/
1567
1568 BnxeLogDbg(pUM, "Cleaning up FCoE Rx Pkts");
1569
1570 BnxeRxPktsFini(pUM, LM_CLI_IDX_FCOE);
1571
1572 /*********************************************************/
1573
1574 BnxeLogDbg(pUM, "Clearing FCoE Resources");
1575
1576 if ((rc = lm_fc_clear_resc(pLM)) != LM_STATUS_SUCCESS)
1577 {
1578 BnxeLogWarn(pUM, "Failed to clear FCoE resources (%d)\n", rc);
1579 }
1580
1581 lm_cid_recycled_cb_deregister(pLM, FCOE_CONNECTION_TYPE);
1582
1583 /*********************************************************/
1584
1585 BnxeHwStopCore(pUM);
1586
1587 /*********************************************************/
1588
1589 BnxeLogInfo(pUM, "BnxeHwStopFCOE: FCoE stopped (clients %s)",
1590 BnxeClientsHw(pUM));
1591
1592 BNXE_LOCK_EXIT_HWINIT(pUM);
1593 }
1594
1595
BnxeHwStopL2(um_device_t * pUM)1596 void BnxeHwStopL2(um_device_t * pUM)
1597 {
1598 lm_device_t * pLM = &pUM->lm_dev;
1599 int idx, rc;
1600
1601 BNXE_LOCK_ENTER_HWINIT(pUM);
1602
1603 BnxeLogInfo(pUM, "BnxeHwStopL2: Stopping L2 (clients %s)",
1604 BnxeClientsHw(pUM));
1605
1606 lm_mcp_indicate_client_unbind(&pUM->lm_dev, LM_CLI_IDX_NDIS);
1607 CLIENT_HW_RESET(pUM, LM_CLI_IDX_NDIS);
1608
1609 /*********************************************************/
1610
1611 BnxeLogDbg(pUM, "Turning off L2 RX Mask");
1612
1613 BnxeRxMask(pUM, LM_CLI_IDX_NDIS, LM_RX_MASK_ACCEPT_NONE);
1614
1615 /*********************************************************/
1616
1617 BnxeLogDbg(pUM, "Clearing the L2 MAC Address");
1618
1619 /*
1620 * Reset the mac_addr to hw programmed default and then clear
1621 * it in the firmware.
1622 */
1623 {
1624 u8_t mac_to_delete[ETHERNET_ADDRESS_SIZE];
1625 COPY_ETH_ADDRESS(pUM->lm_dev.params.mac_addr,
1626 mac_to_delete);
1627
1628 COPY_ETH_ADDRESS(pUM->lm_dev.hw_info.mac_addr,
1629 pUM->lm_dev.params.mac_addr);
1630 memset(pUM->gldMac, 0, ETHERNET_ADDRESS_SIZE);
1631
1632 #if 0
1633 BnxeMacAddress(pUM, LM_CLI_IDX_NDIS, B_FALSE, mac_to_delete);
1634 #else
1635 BnxeLogInfo(pUM, "Removing all MAC addresses");
1636
1637 if ((rc = lm_clear_all_mac_addr(pLM,
1638 LM_CLI_CID(&pUM->lm_dev,
1639 LM_CLI_IDX_NDIS))) !=
1640 LM_STATUS_SUCCESS)
1641 {
1642 BnxeLogWarn(pUM, "Failed to delete all MAC addresses (%d)", rc);
1643 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE);
1644 }
1645 #endif
1646 }
1647
1648 /*********************************************************/
1649
1650 BnxeLogDbg(pUM, "Clearing the L2 Multicast Table");
1651
1652 BnxeMulticast(pUM, LM_CLI_IDX_NDIS, B_FALSE, NULL, B_TRUE);
1653
1654 /*********************************************************/
1655
1656 BnxeLogDbg(pUM, "Disabling RSS");
1657
1658 BnxeRssDisable(pUM);
1659
1660 /*********************************************************/
1661
1662 /*
1663 * In Solaris when RX traffic is accepted, the system might generate and
1664 * attempt to send some TX packets (from within gld_recv()!). Claiming any
1665 * TX locks before this point would create a deadlock. The ISR would be
1666 * waiting for a lock acquired here that would never be freed, since we
1667 * in-turn would be waiting for the ISR to finish here. Consequently, we
1668 * acquire the TX lock as soon as we know that no TX traffic is a result of
1669 * RX traffic.
1670 */
1671 BNXE_LOCK_ENTER_GLDTX(pUM, RW_WRITER);
1672
1673 /*********************************************************/
1674
1675 BnxeLogDbg(pUM, "Closing L2 Ethernet Connections (%d)",
1676 pLM->params.rss_chain_cnt);
1677
1678 LM_FOREACH_RSS_IDX(pLM, idx)
1679 {
1680 if ((rc = lm_close_eth_con(pLM, idx, B_TRUE)) !=
1681 LM_STATUS_SUCCESS)
1682 {
1683 BnxeLogWarn(pUM, "Failed to close Ethernet conn on RSS %d (%d)",
1684 idx, rc);
1685 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE);
1686 }
1687 }
1688
1689 /*********************************************************/
1690
1691 BnxeLogDbg(pUM, "Aborting L2 Tx Chains");
1692
1693 BnxeTxPktsAbort(pUM, LM_CLI_IDX_NDIS);
1694
1695 /*********************************************************/
1696
1697 BnxeLogDbg(pUM, "Aborting L2 Rx Chains");
1698
1699 BnxeRxPktsAbort(pUM, LM_CLI_IDX_NDIS);
1700
1701 /*********************************************************/
1702
1703 BNXE_LOCK_EXIT_GLDTX(pUM);
1704
1705 /*********************************************************/
1706
1707 BnxeLogDbg(pUM, "Cleaning up L2 Tx Pkts");
1708
1709 BnxeTxPktsFini(pUM, LM_CLI_IDX_NDIS);
1710
1711 /*********************************************************/
1712
1713 BnxeLogDbg(pUM, "Cleaning up L2 Rx Pkts");
1714
1715 BnxeRxPktsFini(pUM, LM_CLI_IDX_NDIS);
1716
1717 /*********************************************************/
1718
1719 BnxeHwStopCore(pUM);
1720
1721 /*********************************************************/
1722
1723 BnxeLogInfo(pUM, "BnxeHwStopL2: L2 stopped (clients %s)",
1724 BnxeClientsHw(pUM));
1725
1726 BNXE_LOCK_EXIT_HWINIT(pUM);
1727 }
1728
1729
1730 /* Must be called with BNXE_LOCK_ENTER_HWINIT taken! */
BnxeHwStopCore(um_device_t * pUM)1731 void BnxeHwStopCore(um_device_t * pUM)
1732 {
1733 lm_device_t * pLM = &pUM->lm_dev;
1734 BnxeMemBlock * pMemBlock;
1735 BnxeMemDma * pMemDma;
1736 lm_address_t physAddr;
1737 int rc;
1738
1739 physAddr.as_ptr = NULL;
1740
1741 if (!pUM->hwInitDone)
1742 {
1743 /* already finished? (should never get here) */
1744 BnxeLogWarn(pUM, "BnxeHwStopCore: Hardware already stopped (clients %s)",
1745 BnxeClientsHw(pUM));
1746 return;
1747 }
1748
1749 if (BnxeIsClientBound(pUM))
1750 {
1751 BnxeLogInfo(pUM, "BnxeHwStopCore: Hardware cannot be stopped (clients %s)",
1752 BnxeClientsHw(pUM));
1753 return;
1754 }
1755
1756 BnxeLogInfo(pUM, "BnxeHwStopCore: Stopping hardware (clients %s)",
1757 BnxeClientsHw(pUM));
1758
1759 mm_indicate_link(pLM, LM_STATUS_LINK_DOWN, pUM->devParams.lastIndMedium);
1760
1761 /*********************************************************/
1762
1763 BnxeLogDbg(pUM, "Stopping Timer");
1764
1765 BnxeTimerStop(pUM);
1766
1767 /*********************************************************/
1768
1769 BnxeLogDbg(pUM, "Stopping DCBX");
1770
1771 lm_dcbx_free_resc(pLM);
1772
1773 /*********************************************************/
1774
1775 BnxeLogDbg(pUM, "Stopping BRCM Chip");
1776
1777 rc = lm_chip_stop(pLM);
1778
1779 if (pUM->fmCapabilities &&
1780 BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK)
1781 {
1782 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED);
1783 }
1784
1785 if (rc != LM_STATUS_SUCCESS)
1786 {
1787 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE);
1788 }
1789
1790 atomic_swap_32(&pUM->chipStarted, B_FALSE);
1791
1792 /*********************************************************/
1793
1794 BnxeLogDbg(pUM, "Disabling Interrupts");
1795
1796 BnxeIntrDisable(pUM);
1797
1798 /*********************************************************/
1799
1800 BnxeLogDbg(pUM, "Resetting BRCM Chip");
1801
1802 lm_chip_reset(pLM, LM_REASON_DRIVER_SHUTDOWN);
1803
1804 pUM->phyInitialized = B_FALSE;
1805
1806 if (pUM->fmCapabilities &&
1807 BnxeCheckAccHandle(pUM->pPciCfg) != DDI_FM_OK)
1808 {
1809 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED);
1810 }
1811
1812 if (pUM->fmCapabilities &&
1813 BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK)
1814 {
1815 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED);
1816 }
1817
1818 /*********************************************************/
1819
1820 while (!d_list_is_empty(&pUM->memBlockList))
1821 {
1822 pMemBlock = (BnxeMemBlock *)d_list_peek_head(&pUM->memBlockList);
1823 mm_rt_free_mem(pLM,
1824 ((char *)pMemBlock->pBuf + BNXE_MEM_CHECK_LEN),
1825 (pMemBlock->size - (BNXE_MEM_CHECK_LEN * 2)),
1826 LM_CLI_IDX_NDIS);
1827 }
1828
1829 #ifndef BNXE_DEBUG_DMA_LIST
1830 while (!d_list_is_empty(&pUM->memDmaList))
1831 {
1832 pMemDma = (BnxeMemDma *)d_list_peek_head(&pUM->memDmaList);
1833 mm_rt_free_phys_mem(pLM,
1834 pMemDma->size,
1835 pMemDma->pDmaVirt,
1836 physAddr,
1837 LM_CLI_IDX_NDIS);
1838 }
1839 #else
1840 {
1841 BnxeMemDma * pTmp;
1842 int i;
1843
1844 BNXE_LOCK_ENTER_MEM(pUM);
1845
1846 pTmp = (BnxeMemDma *)d_list_peek_head(&pUM->memDmaList);
1847 while (pTmp)
1848 {
1849 for (i = 0; i < pTmp->size; i++)
1850 {
1851 ((u8_t *)pTmp->pDmaVirt)[i] = 0x0;
1852 }
1853
1854 pTmp = (BnxeMemDma *)d_list_next_entry(&pTmp->link);
1855 }
1856
1857 d_list_add_head(&pUM->memDmaListSaved, &pUM->memDmaList);
1858 d_list_clear(&pUM->memDmaList);
1859
1860 BNXE_LOCK_EXIT_MEM(pUM);
1861
1862 BnxeVerifySavedDmaList(pUM);
1863 }
1864 #endif /* BNXE_DEBUG_DMA_LIST */
1865
1866 atomic_swap_32(&pUM->hwInitDone, B_FALSE);
1867
1868 BnxeLogInfo(pUM, "BnxeHwStopCore: Hardware stopped (clients %s)",
1869 BnxeClientsHw(pUM));
1870 }
1871
1872
BnxeHwResume(um_device_t * pUM)1873 int BnxeHwResume(um_device_t * pUM)
1874 {
1875 lm_device_t * pLM = &pUM->lm_dev;
1876 int rc;
1877
1878 BnxeLogDbg(pUM, "Setting Power State");
1879 lm_set_power_state(pLM, LM_POWER_STATE_D0, LM_WAKE_UP_MODE_NONE, FALSE);
1880
1881 /* XXX Do we need it? */
1882 BnxeLogDbg(pUM, "Enabling PCI DMA");
1883 lm_enable_pci_dma(pLM);
1884
1885 if (pUM->fmCapabilities &&
1886 BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK)
1887 {
1888 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_LOST);
1889 return -1;
1890 }
1891
1892 if (!pUM->plumbed)
1893 {
1894 /* XXX
1895 * Won't work under new model with multiple clients. Need an
1896 * extra pause mechanism/layer for suspend and resume.
1897 */
1898 if (BnxeHwStartCore(pUM))
1899 {
1900 return -1;
1901 }
1902
1903 atomic_swap_32(&pUM->plumbed, B_TRUE);
1904 }
1905
1906 return 0;
1907 }
1908
1909
BnxeHwSuspend(um_device_t * pUM)1910 int BnxeHwSuspend(um_device_t * pUM)
1911 {
1912 lm_device_t * pLM = &pUM->lm_dev;
1913
1914 lm_reset_set_inprogress(pLM);
1915 lm_reset_mask_attn(pLM);
1916
1917 disable_blocks_attention(pLM);
1918
1919 if (pUM->plumbed)
1920 {
1921 /* XXX
1922 * Won't work under new model with multiple clients. Need an
1923 * extra pause mechanism/layer for suspend and resume.
1924 */
1925 BnxeHwStopCore(pUM);
1926 atomic_swap_32(&pUM->plumbed, B_FALSE);
1927 }
1928
1929 /* XXX proper lm_wake_up_mode_t when WOL supported */
1930 lm_set_d3_nwuf(pLM, LM_WAKE_UP_MODE_NONE);
1931
1932 if (pUM->fmCapabilities &&
1933 BnxeCheckAccHandle(pUM->pPciCfg) != DDI_FM_OK)
1934 {
1935 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED);
1936 return LM_STATUS_FAILURE;
1937 }
1938
1939 if (pUM->fmCapabilities &&
1940 BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK)
1941 {
1942 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED);
1943 return -1;
1944 }
1945
1946 /* XXX proper lm_wake_up_mode_t when WOL supported */
1947 lm_set_d3_mpkt(pLM, LM_WAKE_UP_MODE_NONE);
1948
1949 if (pUM->fmCapabilities &&
1950 BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK)
1951 {
1952 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED);
1953 return -1;
1954 }
1955
1956 /* XXX Do we need it? */
1957 BnxeLogDbg(pUM, "Disabling PCI DMA");
1958 lm_disable_pci_dma(pLM, TRUE);
1959
1960 if (pUM->fmCapabilities &&
1961 BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK)
1962 {
1963 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED);
1964 return -1;
1965 }
1966
1967 return 0;
1968 }
1969
1970
1971 #if (DEVO_REV > 3)
1972
1973 /*
1974 * This is a non-blocking function to make sure no more interrupt and dma memory
1975 * access of this hardware. We don't have to free any resource here.
1976 */
BnxeHwQuiesce(um_device_t * pUM)1977 int BnxeHwQuiesce(um_device_t * pUM)
1978 {
1979 lm_device_t * pLM = &pUM->lm_dev;
1980
1981 /* XXX temporary block until bnxef supports fast reboot... */
1982 if (CLIENT_BOUND(pUM, LM_CLI_IDX_FCOE))
1983 {
1984 BnxeLogWarn(pUM, "Unable to quiesce, FCoE is bound!");
1985 return -1;
1986 }
1987
1988 #if 0
1989 lm_chip_stop(pLM);
1990 #endif
1991
1992 lm_disable_int(pLM);
1993
1994 lm_chip_reset(pLM, LM_REASON_DRIVER_SHUTDOWN);
1995
1996 BnxeRxPktsAbort(pUM, LM_CLI_IDX_NDIS);
1997 BnxeTxPktsAbort(pUM, LM_CLI_IDX_NDIS);
1998
1999 return 0;
2000 }
2001
2002 #endif
2003
2004