xref: /illumos-gate/usr/src/uts/common/io/bnxe/bnxe_hw.c (revision 20a7641f9918de8574b8b3b47dbe35c4bfc78df1)
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 
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 
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 
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 
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 
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 
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  */
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 
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 
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  */
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 
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 
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 
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! */
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 
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 
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! */
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 
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 
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  */
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