[SCSI] bfa: Brocade BFA FC SCSI driver
[safe/jmp/linux-2.6] / drivers / scsi / bfa / bfa_fcport.c
1 /*
2  * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
3  * All rights reserved
4  * www.brocade.com
5  *
6  * Linux driver for Brocade Fibre Channel Host Bus Adapter.
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License (GPL) Version 2 as
10  * published by the Free Software Foundation
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  */
17
18 #include <bfa.h>
19 #include <bfa_svc.h>
20 #include <bfi/bfi_pport.h>
21 #include <cs/bfa_debug.h>
22 #include <aen/bfa_aen.h>
23 #include <cs/bfa_plog.h>
24 #include <aen/bfa_aen_port.h>
25
26 BFA_TRC_FILE(HAL, PPORT);
27 BFA_MODULE(pport);
28
29 #define bfa_pport_callback(__pport, __event) do {                       \
30         if ((__pport)->bfa->fcs) {      \
31                 (__pport)->event_cbfn((__pport)->event_cbarg, (__event));      \
32         } else {                                                        \
33                 (__pport)->hcb_event = (__event);      \
34                 bfa_cb_queue((__pport)->bfa, &(__pport)->hcb_qe,        \
35                 __bfa_cb_port_event, (__pport));      \
36         }                                                               \
37 } while (0)
38
39 /*
40  * The port is considered disabled if corresponding physical port or IOC are
41  * disabled explicitly
42  */
43 #define BFA_PORT_IS_DISABLED(bfa) \
44         ((bfa_pport_is_disabled(bfa) == BFA_TRUE) || \
45         (bfa_ioc_is_disabled(&bfa->ioc) == BFA_TRUE))
46
47 /*
48  * forward declarations
49  */
50 static bfa_boolean_t bfa_pport_send_enable(struct bfa_pport_s *port);
51 static bfa_boolean_t bfa_pport_send_disable(struct bfa_pport_s *port);
52 static void     bfa_pport_update_linkinfo(struct bfa_pport_s *pport);
53 static void     bfa_pport_reset_linkinfo(struct bfa_pport_s *pport);
54 static void     bfa_pport_set_wwns(struct bfa_pport_s *port);
55 static void     __bfa_cb_port_event(void *cbarg, bfa_boolean_t complete);
56 static void     __bfa_cb_port_stats(void *cbarg, bfa_boolean_t complete);
57 static void     __bfa_cb_port_stats_clr(void *cbarg, bfa_boolean_t complete);
58 static void     bfa_port_stats_timeout(void *cbarg);
59 static void     bfa_port_stats_clr_timeout(void *cbarg);
60
61 /**
62  *  bfa_pport_private
63  */
64
65 /**
66  * BFA port state machine events
67  */
68 enum bfa_pport_sm_event {
69         BFA_PPORT_SM_START = 1, /*  start port state machine */
70         BFA_PPORT_SM_STOP = 2,  /*  stop port state machine */
71         BFA_PPORT_SM_ENABLE = 3,        /*  enable port */
72         BFA_PPORT_SM_DISABLE = 4,       /*  disable port state machine */
73         BFA_PPORT_SM_FWRSP = 5, /*  firmware enable/disable rsp */
74         BFA_PPORT_SM_LINKUP = 6,        /*  firmware linkup event */
75         BFA_PPORT_SM_LINKDOWN = 7,      /*  firmware linkup down */
76         BFA_PPORT_SM_QRESUME = 8,       /*  CQ space available */
77         BFA_PPORT_SM_HWFAIL = 9,        /*  IOC h/w failure */
78 };
79
80 static void     bfa_pport_sm_uninit(struct bfa_pport_s *pport,
81                                     enum bfa_pport_sm_event event);
82 static void     bfa_pport_sm_enabling_qwait(struct bfa_pport_s *pport,
83                                             enum bfa_pport_sm_event event);
84 static void     bfa_pport_sm_enabling(struct bfa_pport_s *pport,
85                                       enum bfa_pport_sm_event event);
86 static void     bfa_pport_sm_linkdown(struct bfa_pport_s *pport,
87                                       enum bfa_pport_sm_event event);
88 static void     bfa_pport_sm_linkup(struct bfa_pport_s *pport,
89                                     enum bfa_pport_sm_event event);
90 static void     bfa_pport_sm_disabling(struct bfa_pport_s *pport,
91                                        enum bfa_pport_sm_event event);
92 static void     bfa_pport_sm_disabling_qwait(struct bfa_pport_s *pport,
93                                              enum bfa_pport_sm_event event);
94 static void     bfa_pport_sm_disabled(struct bfa_pport_s *pport,
95                                       enum bfa_pport_sm_event event);
96 static void     bfa_pport_sm_stopped(struct bfa_pport_s *pport,
97                                      enum bfa_pport_sm_event event);
98 static void     bfa_pport_sm_iocdown(struct bfa_pport_s *pport,
99                                      enum bfa_pport_sm_event event);
100 static void     bfa_pport_sm_iocfail(struct bfa_pport_s *pport,
101                                      enum bfa_pport_sm_event event);
102
103 static struct bfa_sm_table_s hal_pport_sm_table[] = {
104         {BFA_SM(bfa_pport_sm_uninit), BFA_PPORT_ST_UNINIT},
105         {BFA_SM(bfa_pport_sm_enabling_qwait), BFA_PPORT_ST_ENABLING_QWAIT},
106         {BFA_SM(bfa_pport_sm_enabling), BFA_PPORT_ST_ENABLING},
107         {BFA_SM(bfa_pport_sm_linkdown), BFA_PPORT_ST_LINKDOWN},
108         {BFA_SM(bfa_pport_sm_linkup), BFA_PPORT_ST_LINKUP},
109         {BFA_SM(bfa_pport_sm_disabling_qwait),
110          BFA_PPORT_ST_DISABLING_QWAIT},
111         {BFA_SM(bfa_pport_sm_disabling), BFA_PPORT_ST_DISABLING},
112         {BFA_SM(bfa_pport_sm_disabled), BFA_PPORT_ST_DISABLED},
113         {BFA_SM(bfa_pport_sm_stopped), BFA_PPORT_ST_STOPPED},
114         {BFA_SM(bfa_pport_sm_iocdown), BFA_PPORT_ST_IOCDOWN},
115         {BFA_SM(bfa_pport_sm_iocfail), BFA_PPORT_ST_IOCDOWN},
116 };
117
118 static void
119 bfa_pport_aen_post(struct bfa_pport_s *pport, enum bfa_port_aen_event event)
120 {
121         union bfa_aen_data_u aen_data;
122         struct bfa_log_mod_s *logmod = pport->bfa->logm;
123         wwn_t           pwwn = pport->pwwn;
124         char            pwwn_ptr[BFA_STRING_32];
125         struct bfa_ioc_attr_s ioc_attr;
126
127         wwn2str(pwwn_ptr, pwwn);
128         switch (event) {
129         case BFA_PORT_AEN_ONLINE:
130                 bfa_log(logmod, BFA_AEN_PORT_ONLINE, pwwn_ptr);
131                 break;
132         case BFA_PORT_AEN_OFFLINE:
133                 bfa_log(logmod, BFA_AEN_PORT_OFFLINE, pwwn_ptr);
134                 break;
135         case BFA_PORT_AEN_ENABLE:
136                 bfa_log(logmod, BFA_AEN_PORT_ENABLE, pwwn_ptr);
137                 break;
138         case BFA_PORT_AEN_DISABLE:
139                 bfa_log(logmod, BFA_AEN_PORT_DISABLE, pwwn_ptr);
140                 break;
141         case BFA_PORT_AEN_DISCONNECT:
142                 bfa_log(logmod, BFA_AEN_PORT_DISCONNECT, pwwn_ptr);
143                 break;
144         case BFA_PORT_AEN_QOS_NEG:
145                 bfa_log(logmod, BFA_AEN_PORT_QOS_NEG, pwwn_ptr);
146                 break;
147         default:
148                 break;
149         }
150
151         bfa_ioc_get_attr(&pport->bfa->ioc, &ioc_attr);
152         aen_data.port.ioc_type = ioc_attr.ioc_type;
153         aen_data.port.pwwn = pwwn;
154 }
155
156 static void
157 bfa_pport_sm_uninit(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
158 {
159         bfa_trc(pport->bfa, event);
160
161         switch (event) {
162         case BFA_PPORT_SM_START:
163                 /**
164                  * Start event after IOC is configured and BFA is started.
165                  */
166                 if (bfa_pport_send_enable(pport))
167                         bfa_sm_set_state(pport, bfa_pport_sm_enabling);
168                 else
169                         bfa_sm_set_state(pport, bfa_pport_sm_enabling_qwait);
170                 break;
171
172         case BFA_PPORT_SM_ENABLE:
173                 /**
174                  * Port is persistently configured to be in enabled state. Do
175                  * not change state. Port enabling is done when START event is
176                  * received.
177                  */
178                 break;
179
180         case BFA_PPORT_SM_DISABLE:
181                 /**
182                  * If a port is persistently configured to be disabled, the
183                  * first event will a port disable request.
184                  */
185                 bfa_sm_set_state(pport, bfa_pport_sm_disabled);
186                 break;
187
188         case BFA_PPORT_SM_HWFAIL:
189                 bfa_sm_set_state(pport, bfa_pport_sm_iocdown);
190                 break;
191
192         default:
193                 bfa_sm_fault(pport->bfa, event);
194         }
195 }
196
197 static void
198 bfa_pport_sm_enabling_qwait(struct bfa_pport_s *pport,
199                             enum bfa_pport_sm_event event)
200 {
201         bfa_trc(pport->bfa, event);
202
203         switch (event) {
204         case BFA_PPORT_SM_QRESUME:
205                 bfa_sm_set_state(pport, bfa_pport_sm_enabling);
206                 bfa_pport_send_enable(pport);
207                 break;
208
209         case BFA_PPORT_SM_STOP:
210                 bfa_reqq_wcancel(&pport->reqq_wait);
211                 bfa_sm_set_state(pport, bfa_pport_sm_stopped);
212                 break;
213
214         case BFA_PPORT_SM_ENABLE:
215                 /**
216                  * Already enable is in progress.
217                  */
218                 break;
219
220         case BFA_PPORT_SM_DISABLE:
221                 /**
222                  * Just send disable request to firmware when room becomes
223                  * available in request queue.
224                  */
225                 bfa_sm_set_state(pport, bfa_pport_sm_disabled);
226                 bfa_reqq_wcancel(&pport->reqq_wait);
227                 bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL,
228                              BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
229                 bfa_pport_aen_post(pport, BFA_PORT_AEN_DISABLE);
230                 break;
231
232         case BFA_PPORT_SM_LINKUP:
233         case BFA_PPORT_SM_LINKDOWN:
234                 /**
235                  * Possible to get link events when doing back-to-back
236                  * enable/disables.
237                  */
238                 break;
239
240         case BFA_PPORT_SM_HWFAIL:
241                 bfa_reqq_wcancel(&pport->reqq_wait);
242                 bfa_sm_set_state(pport, bfa_pport_sm_iocdown);
243                 break;
244
245         default:
246                 bfa_sm_fault(pport->bfa, event);
247         }
248 }
249
250 static void
251 bfa_pport_sm_enabling(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
252 {
253         bfa_trc(pport->bfa, event);
254
255         switch (event) {
256         case BFA_PPORT_SM_FWRSP:
257         case BFA_PPORT_SM_LINKDOWN:
258                 bfa_sm_set_state(pport, bfa_pport_sm_linkdown);
259                 break;
260
261         case BFA_PPORT_SM_LINKUP:
262                 bfa_pport_update_linkinfo(pport);
263                 bfa_sm_set_state(pport, bfa_pport_sm_linkup);
264
265                 bfa_assert(pport->event_cbfn);
266                 bfa_pport_callback(pport, BFA_PPORT_LINKUP);
267                 break;
268
269         case BFA_PPORT_SM_ENABLE:
270                 /**
271                  * Already being enabled.
272                  */
273                 break;
274
275         case BFA_PPORT_SM_DISABLE:
276                 if (bfa_pport_send_disable(pport))
277                         bfa_sm_set_state(pport, bfa_pport_sm_disabling);
278                 else
279                         bfa_sm_set_state(pport, bfa_pport_sm_disabling_qwait);
280
281                 bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL,
282                              BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
283                 bfa_pport_aen_post(pport, BFA_PORT_AEN_DISABLE);
284                 break;
285
286         case BFA_PPORT_SM_STOP:
287                 bfa_sm_set_state(pport, bfa_pport_sm_stopped);
288                 break;
289
290         case BFA_PPORT_SM_HWFAIL:
291                 bfa_sm_set_state(pport, bfa_pport_sm_iocdown);
292                 break;
293
294         default:
295                 bfa_sm_fault(pport->bfa, event);
296         }
297 }
298
299 static void
300 bfa_pport_sm_linkdown(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
301 {
302         bfa_trc(pport->bfa, event);
303
304         switch (event) {
305         case BFA_PPORT_SM_LINKUP:
306                 bfa_pport_update_linkinfo(pport);
307                 bfa_sm_set_state(pport, bfa_pport_sm_linkup);
308                 bfa_assert(pport->event_cbfn);
309                 bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL,
310                              BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkup");
311                 bfa_pport_callback(pport, BFA_PPORT_LINKUP);
312                 bfa_pport_aen_post(pport, BFA_PORT_AEN_ONLINE);
313                 /**
314                  * If QoS is enabled and it is not online,
315                  * Send a separate event.
316                  */
317                 if ((pport->cfg.qos_enabled)
318                     && (bfa_os_ntohl(pport->qos_attr.state) != BFA_QOS_ONLINE))
319                         bfa_pport_aen_post(pport, BFA_PORT_AEN_QOS_NEG);
320
321                 break;
322
323         case BFA_PPORT_SM_LINKDOWN:
324                 /**
325                  * Possible to get link down event.
326                  */
327                 break;
328
329         case BFA_PPORT_SM_ENABLE:
330                 /**
331                  * Already enabled.
332                  */
333                 break;
334
335         case BFA_PPORT_SM_DISABLE:
336                 if (bfa_pport_send_disable(pport))
337                         bfa_sm_set_state(pport, bfa_pport_sm_disabling);
338                 else
339                         bfa_sm_set_state(pport, bfa_pport_sm_disabling_qwait);
340
341                 bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL,
342                              BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
343                 bfa_pport_aen_post(pport, BFA_PORT_AEN_DISABLE);
344                 break;
345
346         case BFA_PPORT_SM_STOP:
347                 bfa_sm_set_state(pport, bfa_pport_sm_stopped);
348                 break;
349
350         case BFA_PPORT_SM_HWFAIL:
351                 bfa_sm_set_state(pport, bfa_pport_sm_iocdown);
352                 break;
353
354         default:
355                 bfa_sm_fault(pport->bfa, event);
356         }
357 }
358
359 static void
360 bfa_pport_sm_linkup(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
361 {
362         bfa_trc(pport->bfa, event);
363
364         switch (event) {
365         case BFA_PPORT_SM_ENABLE:
366                 /**
367                  * Already enabled.
368                  */
369                 break;
370
371         case BFA_PPORT_SM_DISABLE:
372                 if (bfa_pport_send_disable(pport))
373                         bfa_sm_set_state(pport, bfa_pport_sm_disabling);
374                 else
375                         bfa_sm_set_state(pport, bfa_pport_sm_disabling_qwait);
376
377                 bfa_pport_reset_linkinfo(pport);
378                 bfa_pport_callback(pport, BFA_PPORT_LINKDOWN);
379                 bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL,
380                              BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
381                 bfa_pport_aen_post(pport, BFA_PORT_AEN_OFFLINE);
382                 bfa_pport_aen_post(pport, BFA_PORT_AEN_DISABLE);
383                 break;
384
385         case BFA_PPORT_SM_LINKDOWN:
386                 bfa_sm_set_state(pport, bfa_pport_sm_linkdown);
387                 bfa_pport_reset_linkinfo(pport);
388                 bfa_pport_callback(pport, BFA_PPORT_LINKDOWN);
389                 bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL,
390                              BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkdown");
391                 if (BFA_PORT_IS_DISABLED(pport->bfa)) {
392                         bfa_pport_aen_post(pport, BFA_PORT_AEN_OFFLINE);
393                 } else {
394                         bfa_pport_aen_post(pport, BFA_PORT_AEN_DISCONNECT);
395                 }
396                 break;
397
398         case BFA_PPORT_SM_STOP:
399                 bfa_sm_set_state(pport, bfa_pport_sm_stopped);
400                 bfa_pport_reset_linkinfo(pport);
401                 if (BFA_PORT_IS_DISABLED(pport->bfa)) {
402                         bfa_pport_aen_post(pport, BFA_PORT_AEN_OFFLINE);
403                 } else {
404                         bfa_pport_aen_post(pport, BFA_PORT_AEN_DISCONNECT);
405                 }
406                 break;
407
408         case BFA_PPORT_SM_HWFAIL:
409                 bfa_sm_set_state(pport, bfa_pport_sm_iocdown);
410                 bfa_pport_reset_linkinfo(pport);
411                 bfa_pport_callback(pport, BFA_PPORT_LINKDOWN);
412                 if (BFA_PORT_IS_DISABLED(pport->bfa)) {
413                         bfa_pport_aen_post(pport, BFA_PORT_AEN_OFFLINE);
414                 } else {
415                         bfa_pport_aen_post(pport, BFA_PORT_AEN_DISCONNECT);
416                 }
417                 break;
418
419         default:
420                 bfa_sm_fault(pport->bfa, event);
421         }
422 }
423
424 static void
425 bfa_pport_sm_disabling_qwait(struct bfa_pport_s *pport,
426                              enum bfa_pport_sm_event event)
427 {
428         bfa_trc(pport->bfa, event);
429
430         switch (event) {
431         case BFA_PPORT_SM_QRESUME:
432                 bfa_sm_set_state(pport, bfa_pport_sm_disabling);
433                 bfa_pport_send_disable(pport);
434                 break;
435
436         case BFA_PPORT_SM_STOP:
437                 bfa_sm_set_state(pport, bfa_pport_sm_stopped);
438                 bfa_reqq_wcancel(&pport->reqq_wait);
439                 break;
440
441         case BFA_PPORT_SM_DISABLE:
442                 /**
443                  * Already being disabled.
444                  */
445                 break;
446
447         case BFA_PPORT_SM_LINKUP:
448         case BFA_PPORT_SM_LINKDOWN:
449                 /**
450                  * Possible to get link events when doing back-to-back
451                  * enable/disables.
452                  */
453                 break;
454
455         case BFA_PPORT_SM_HWFAIL:
456                 bfa_sm_set_state(pport, bfa_pport_sm_iocfail);
457                 bfa_reqq_wcancel(&pport->reqq_wait);
458                 break;
459
460         default:
461                 bfa_sm_fault(pport->bfa, event);
462         }
463 }
464
465 static void
466 bfa_pport_sm_disabling(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
467 {
468         bfa_trc(pport->bfa, event);
469
470         switch (event) {
471         case BFA_PPORT_SM_FWRSP:
472                 bfa_sm_set_state(pport, bfa_pport_sm_disabled);
473                 break;
474
475         case BFA_PPORT_SM_DISABLE:
476                 /**
477                  * Already being disabled.
478                  */
479                 break;
480
481         case BFA_PPORT_SM_ENABLE:
482                 if (bfa_pport_send_enable(pport))
483                         bfa_sm_set_state(pport, bfa_pport_sm_enabling);
484                 else
485                         bfa_sm_set_state(pport, bfa_pport_sm_enabling_qwait);
486
487                 bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL,
488                              BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
489                 bfa_pport_aen_post(pport, BFA_PORT_AEN_ENABLE);
490                 break;
491
492         case BFA_PPORT_SM_STOP:
493                 bfa_sm_set_state(pport, bfa_pport_sm_stopped);
494                 break;
495
496         case BFA_PPORT_SM_LINKUP:
497         case BFA_PPORT_SM_LINKDOWN:
498                 /**
499                  * Possible to get link events when doing back-to-back
500                  * enable/disables.
501                  */
502                 break;
503
504         case BFA_PPORT_SM_HWFAIL:
505                 bfa_sm_set_state(pport, bfa_pport_sm_iocfail);
506                 break;
507
508         default:
509                 bfa_sm_fault(pport->bfa, event);
510         }
511 }
512
513 static void
514 bfa_pport_sm_disabled(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
515 {
516         bfa_trc(pport->bfa, event);
517
518         switch (event) {
519         case BFA_PPORT_SM_START:
520                 /**
521                  * Ignore start event for a port that is disabled.
522                  */
523                 break;
524
525         case BFA_PPORT_SM_STOP:
526                 bfa_sm_set_state(pport, bfa_pport_sm_stopped);
527                 break;
528
529         case BFA_PPORT_SM_ENABLE:
530                 if (bfa_pport_send_enable(pport))
531                         bfa_sm_set_state(pport, bfa_pport_sm_enabling);
532                 else
533                         bfa_sm_set_state(pport, bfa_pport_sm_enabling_qwait);
534
535                 bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL,
536                              BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
537                 bfa_pport_aen_post(pport, BFA_PORT_AEN_ENABLE);
538                 break;
539
540         case BFA_PPORT_SM_DISABLE:
541                 /**
542                  * Already disabled.
543                  */
544                 break;
545
546         case BFA_PPORT_SM_HWFAIL:
547                 bfa_sm_set_state(pport, bfa_pport_sm_iocfail);
548                 break;
549
550         default:
551                 bfa_sm_fault(pport->bfa, event);
552         }
553 }
554
555 static void
556 bfa_pport_sm_stopped(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
557 {
558         bfa_trc(pport->bfa, event);
559
560         switch (event) {
561         case BFA_PPORT_SM_START:
562                 if (bfa_pport_send_enable(pport))
563                         bfa_sm_set_state(pport, bfa_pport_sm_enabling);
564                 else
565                         bfa_sm_set_state(pport, bfa_pport_sm_enabling_qwait);
566                 break;
567
568         default:
569                 /**
570                  * Ignore all other events.
571                  */
572                 ;
573         }
574 }
575
576 /**
577  * Port is enabled. IOC is down/failed.
578  */
579 static void
580 bfa_pport_sm_iocdown(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
581 {
582         bfa_trc(pport->bfa, event);
583
584         switch (event) {
585         case BFA_PPORT_SM_START:
586                 if (bfa_pport_send_enable(pport))
587                         bfa_sm_set_state(pport, bfa_pport_sm_enabling);
588                 else
589                         bfa_sm_set_state(pport, bfa_pport_sm_enabling_qwait);
590                 break;
591
592         default:
593                 /**
594                  * Ignore all events.
595                  */
596                 ;
597         }
598 }
599
600 /**
601  * Port is disabled. IOC is down/failed.
602  */
603 static void
604 bfa_pport_sm_iocfail(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
605 {
606         bfa_trc(pport->bfa, event);
607
608         switch (event) {
609         case BFA_PPORT_SM_START:
610                 bfa_sm_set_state(pport, bfa_pport_sm_disabled);
611                 break;
612
613         case BFA_PPORT_SM_ENABLE:
614                 bfa_sm_set_state(pport, bfa_pport_sm_iocdown);
615                 break;
616
617         default:
618                 /**
619                  * Ignore all events.
620                  */
621                 ;
622         }
623 }
624
625
626
627 /**
628  *  bfa_pport_private
629  */
630
631 static void
632 __bfa_cb_port_event(void *cbarg, bfa_boolean_t complete)
633 {
634         struct bfa_pport_s *pport = cbarg;
635
636         if (complete)
637                 pport->event_cbfn(pport->event_cbarg, pport->hcb_event);
638 }
639
640 #define PPORT_STATS_DMA_SZ (BFA_ROUNDUP(sizeof(union bfa_pport_stats_u), \
641                                                         BFA_CACHELINE_SZ))
642
643 static void
644 bfa_pport_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
645                   u32 *dm_len)
646 {
647         *dm_len += PPORT_STATS_DMA_SZ;
648 }
649
650 static void
651 bfa_pport_qresume(void *cbarg)
652 {
653         struct bfa_pport_s *port = cbarg;
654
655         bfa_sm_send_event(port, BFA_PPORT_SM_QRESUME);
656 }
657
658 static void
659 bfa_pport_mem_claim(struct bfa_pport_s *pport, struct bfa_meminfo_s *meminfo)
660 {
661         u8        *dm_kva;
662         u64        dm_pa;
663
664         dm_kva = bfa_meminfo_dma_virt(meminfo);
665         dm_pa = bfa_meminfo_dma_phys(meminfo);
666
667         pport->stats_kva = dm_kva;
668         pport->stats_pa = dm_pa;
669         pport->stats = (union bfa_pport_stats_u *)dm_kva;
670
671         dm_kva += PPORT_STATS_DMA_SZ;
672         dm_pa += PPORT_STATS_DMA_SZ;
673
674         bfa_meminfo_dma_virt(meminfo) = dm_kva;
675         bfa_meminfo_dma_phys(meminfo) = dm_pa;
676 }
677
678 /**
679  * Memory initialization.
680  */
681 static void
682 bfa_pport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
683                  struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
684 {
685         struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
686         struct bfa_pport_cfg_s *port_cfg = &pport->cfg;
687
688         bfa_os_memset(pport, 0, sizeof(struct bfa_pport_s));
689         pport->bfa = bfa;
690
691         bfa_pport_mem_claim(pport, meminfo);
692
693         bfa_sm_set_state(pport, bfa_pport_sm_uninit);
694
695         /**
696          * initialize and set default configuration
697          */
698         port_cfg->topology = BFA_PPORT_TOPOLOGY_P2P;
699         port_cfg->speed = BFA_PPORT_SPEED_AUTO;
700         port_cfg->trunked = BFA_FALSE;
701         port_cfg->maxfrsize = 0;
702
703         port_cfg->trl_def_speed = BFA_PPORT_SPEED_1GBPS;
704
705         bfa_reqq_winit(&pport->reqq_wait, bfa_pport_qresume, pport);
706 }
707
708 static void
709 bfa_pport_initdone(struct bfa_s *bfa)
710 {
711         struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
712
713         /**
714          * Initialize port attributes from IOC hardware data.
715          */
716         bfa_pport_set_wwns(pport);
717         if (pport->cfg.maxfrsize == 0)
718                 pport->cfg.maxfrsize = bfa_ioc_maxfrsize(&bfa->ioc);
719         pport->cfg.rx_bbcredit = bfa_ioc_rx_bbcredit(&bfa->ioc);
720         pport->speed_sup = bfa_ioc_speed_sup(&bfa->ioc);
721
722         bfa_assert(pport->cfg.maxfrsize);
723         bfa_assert(pport->cfg.rx_bbcredit);
724         bfa_assert(pport->speed_sup);
725 }
726
727 static void
728 bfa_pport_detach(struct bfa_s *bfa)
729 {
730 }
731
732 /**
733  * Called when IOC is ready.
734  */
735 static void
736 bfa_pport_start(struct bfa_s *bfa)
737 {
738         bfa_sm_send_event(BFA_PORT_MOD(bfa), BFA_PPORT_SM_START);
739 }
740
741 /**
742  * Called before IOC is stopped.
743  */
744 static void
745 bfa_pport_stop(struct bfa_s *bfa)
746 {
747         bfa_sm_send_event(BFA_PORT_MOD(bfa), BFA_PPORT_SM_STOP);
748 }
749
750 /**
751  * Called when IOC failure is detected.
752  */
753 static void
754 bfa_pport_iocdisable(struct bfa_s *bfa)
755 {
756         bfa_sm_send_event(BFA_PORT_MOD(bfa), BFA_PPORT_SM_HWFAIL);
757 }
758
759 static void
760 bfa_pport_update_linkinfo(struct bfa_pport_s *pport)
761 {
762         struct bfi_pport_event_s *pevent = pport->event_arg.i2hmsg.event;
763
764         pport->speed = pevent->link_state.speed;
765         pport->topology = pevent->link_state.topology;
766
767         if (pport->topology == BFA_PPORT_TOPOLOGY_LOOP)
768                 pport->myalpa = pevent->link_state.tl.loop_info.myalpa;
769
770         /*
771          * QoS Details
772          */
773         bfa_os_assign(pport->qos_attr, pevent->link_state.qos_attr);
774         bfa_os_assign(pport->qos_vc_attr, pevent->link_state.qos_vc_attr);
775
776         bfa_trc(pport->bfa, pport->speed);
777         bfa_trc(pport->bfa, pport->topology);
778 }
779
780 static void
781 bfa_pport_reset_linkinfo(struct bfa_pport_s *pport)
782 {
783         pport->speed = BFA_PPORT_SPEED_UNKNOWN;
784         pport->topology = BFA_PPORT_TOPOLOGY_NONE;
785 }
786
787 /**
788  * Send port enable message to firmware.
789  */
790 static          bfa_boolean_t
791 bfa_pport_send_enable(struct bfa_pport_s *port)
792 {
793         struct bfi_pport_enable_req_s *m;
794
795         /**
796          * Increment message tag before queue check, so that responses to old
797          * requests are discarded.
798          */
799         port->msgtag++;
800
801         /**
802          * check for room in queue to send request now
803          */
804         m = bfa_reqq_next(port->bfa, BFA_REQQ_PORT);
805         if (!m) {
806                 bfa_reqq_wait(port->bfa, BFA_REQQ_PORT, &port->reqq_wait);
807                 return BFA_FALSE;
808         }
809
810         bfi_h2i_set(m->mh, BFI_MC_FC_PORT, BFI_PPORT_H2I_ENABLE_REQ,
811                     bfa_lpuid(port->bfa));
812         m->nwwn = port->nwwn;
813         m->pwwn = port->pwwn;
814         m->port_cfg = port->cfg;
815         m->msgtag = port->msgtag;
816         m->port_cfg.maxfrsize = bfa_os_htons(port->cfg.maxfrsize);
817         bfa_dma_be_addr_set(m->stats_dma_addr, port->stats_pa);
818         bfa_trc(port->bfa, m->stats_dma_addr.a32.addr_lo);
819         bfa_trc(port->bfa, m->stats_dma_addr.a32.addr_hi);
820
821         /**
822          * queue I/O message to firmware
823          */
824         bfa_reqq_produce(port->bfa, BFA_REQQ_PORT);
825         return BFA_TRUE;
826 }
827
828 /**
829  * Send port disable message to firmware.
830  */
831 static          bfa_boolean_t
832 bfa_pport_send_disable(struct bfa_pport_s *port)
833 {
834         bfi_pport_disable_req_t *m;
835
836         /**
837          * Increment message tag before queue check, so that responses to old
838          * requests are discarded.
839          */
840         port->msgtag++;
841
842         /**
843          * check for room in queue to send request now
844          */
845         m = bfa_reqq_next(port->bfa, BFA_REQQ_PORT);
846         if (!m) {
847                 bfa_reqq_wait(port->bfa, BFA_REQQ_PORT, &port->reqq_wait);
848                 return BFA_FALSE;
849         }
850
851         bfi_h2i_set(m->mh, BFI_MC_FC_PORT, BFI_PPORT_H2I_DISABLE_REQ,
852                     bfa_lpuid(port->bfa));
853         m->msgtag = port->msgtag;
854
855         /**
856          * queue I/O message to firmware
857          */
858         bfa_reqq_produce(port->bfa, BFA_REQQ_PORT);
859
860         return BFA_TRUE;
861 }
862
863 static void
864 bfa_pport_set_wwns(struct bfa_pport_s *port)
865 {
866         port->pwwn = bfa_ioc_get_pwwn(&port->bfa->ioc);
867         port->nwwn = bfa_ioc_get_nwwn(&port->bfa->ioc);
868
869         bfa_trc(port->bfa, port->pwwn);
870         bfa_trc(port->bfa, port->nwwn);
871 }
872
873 static void
874 bfa_port_send_txcredit(void *port_cbarg)
875 {
876
877         struct bfa_pport_s *port = port_cbarg;
878         struct bfi_pport_set_svc_params_req_s *m;
879
880         /**
881          * check for room in queue to send request now
882          */
883         m = bfa_reqq_next(port->bfa, BFA_REQQ_PORT);
884         if (!m) {
885                 bfa_trc(port->bfa, port->cfg.tx_bbcredit);
886                 return;
887         }
888
889         bfi_h2i_set(m->mh, BFI_MC_FC_PORT, BFI_PPORT_H2I_SET_SVC_PARAMS_REQ,
890                     bfa_lpuid(port->bfa));
891         m->tx_bbcredit = bfa_os_htons((u16) port->cfg.tx_bbcredit);
892
893         /**
894          * queue I/O message to firmware
895          */
896         bfa_reqq_produce(port->bfa, BFA_REQQ_PORT);
897 }
898
899
900
901 /**
902  *  bfa_pport_public
903  */
904
905 /**
906  * Firmware message handler.
907  */
908 void
909 bfa_pport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
910 {
911         struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
912         union bfi_pport_i2h_msg_u i2hmsg;
913
914         i2hmsg.msg = msg;
915         pport->event_arg.i2hmsg = i2hmsg;
916
917         switch (msg->mhdr.msg_id) {
918         case BFI_PPORT_I2H_ENABLE_RSP:
919                 if (pport->msgtag == i2hmsg.enable_rsp->msgtag)
920                         bfa_sm_send_event(pport, BFA_PPORT_SM_FWRSP);
921                 break;
922
923         case BFI_PPORT_I2H_DISABLE_RSP:
924                 if (pport->msgtag == i2hmsg.enable_rsp->msgtag)
925                         bfa_sm_send_event(pport, BFA_PPORT_SM_FWRSP);
926                 break;
927
928         case BFI_PPORT_I2H_EVENT:
929                 switch (i2hmsg.event->link_state.linkstate) {
930                 case BFA_PPORT_LINKUP:
931                         bfa_sm_send_event(pport, BFA_PPORT_SM_LINKUP);
932                         break;
933                 case BFA_PPORT_LINKDOWN:
934                         bfa_sm_send_event(pport, BFA_PPORT_SM_LINKDOWN);
935                         break;
936                 case BFA_PPORT_TRUNK_LINKDOWN:
937                         /** todo: event notification */
938                         break;
939                 }
940                 break;
941
942         case BFI_PPORT_I2H_GET_STATS_RSP:
943         case BFI_PPORT_I2H_GET_QOS_STATS_RSP:
944                 /*
945                  * check for timer pop before processing the rsp
946                  */
947                 if (pport->stats_busy == BFA_FALSE
948                     || pport->stats_status == BFA_STATUS_ETIMER)
949                         break;
950
951                 bfa_timer_stop(&pport->timer);
952                 pport->stats_status = i2hmsg.getstats_rsp->status;
953                 bfa_cb_queue(pport->bfa, &pport->hcb_qe, __bfa_cb_port_stats,
954                              pport);
955                 break;
956         case BFI_PPORT_I2H_CLEAR_STATS_RSP:
957         case BFI_PPORT_I2H_CLEAR_QOS_STATS_RSP:
958                 /*
959                  * check for timer pop before processing the rsp
960                  */
961                 if (pport->stats_busy == BFA_FALSE
962                     || pport->stats_status == BFA_STATUS_ETIMER)
963                         break;
964
965                 bfa_timer_stop(&pport->timer);
966                 pport->stats_status = BFA_STATUS_OK;
967                 bfa_cb_queue(pport->bfa, &pport->hcb_qe,
968                              __bfa_cb_port_stats_clr, pport);
969                 break;
970
971         default:
972                 bfa_assert(0);
973         }
974 }
975
976
977
978 /**
979  *  bfa_pport_api
980  */
981
982 /**
983  * Registered callback for port events.
984  */
985 void
986 bfa_pport_event_register(struct bfa_s *bfa,
987                          void (*cbfn) (void *cbarg, bfa_pport_event_t event),
988                          void *cbarg)
989 {
990         struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
991
992         pport->event_cbfn = cbfn;
993         pport->event_cbarg = cbarg;
994 }
995
996 bfa_status_t
997 bfa_pport_enable(struct bfa_s *bfa)
998 {
999         struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1000
1001         if (pport->diag_busy)
1002                 return (BFA_STATUS_DIAG_BUSY);
1003         else if (bfa_sm_cmp_state
1004                  (BFA_PORT_MOD(bfa), bfa_pport_sm_disabling_qwait))
1005                 return (BFA_STATUS_DEVBUSY);
1006
1007         bfa_sm_send_event(BFA_PORT_MOD(bfa), BFA_PPORT_SM_ENABLE);
1008         return BFA_STATUS_OK;
1009 }
1010
1011 bfa_status_t
1012 bfa_pport_disable(struct bfa_s *bfa)
1013 {
1014         bfa_sm_send_event(BFA_PORT_MOD(bfa), BFA_PPORT_SM_DISABLE);
1015         return BFA_STATUS_OK;
1016 }
1017
1018 /**
1019  * Configure port speed.
1020  */
1021 bfa_status_t
1022 bfa_pport_cfg_speed(struct bfa_s *bfa, enum bfa_pport_speed speed)
1023 {
1024         struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1025
1026         bfa_trc(bfa, speed);
1027
1028         if ((speed != BFA_PPORT_SPEED_AUTO) && (speed > pport->speed_sup)) {
1029                 bfa_trc(bfa, pport->speed_sup);
1030                 return BFA_STATUS_UNSUPP_SPEED;
1031         }
1032
1033         pport->cfg.speed = speed;
1034
1035         return (BFA_STATUS_OK);
1036 }
1037
1038 /**
1039  * Get current speed.
1040  */
1041 enum bfa_pport_speed
1042 bfa_pport_get_speed(struct bfa_s *bfa)
1043 {
1044         struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
1045
1046         return port->speed;
1047 }
1048
1049 /**
1050  * Configure port topology.
1051  */
1052 bfa_status_t
1053 bfa_pport_cfg_topology(struct bfa_s *bfa, enum bfa_pport_topology topology)
1054 {
1055         struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1056
1057         bfa_trc(bfa, topology);
1058         bfa_trc(bfa, pport->cfg.topology);
1059
1060         switch (topology) {
1061         case BFA_PPORT_TOPOLOGY_P2P:
1062         case BFA_PPORT_TOPOLOGY_LOOP:
1063         case BFA_PPORT_TOPOLOGY_AUTO:
1064                 break;
1065
1066         default:
1067                 return BFA_STATUS_EINVAL;
1068         }
1069
1070         pport->cfg.topology = topology;
1071         return (BFA_STATUS_OK);
1072 }
1073
1074 /**
1075  * Get current topology.
1076  */
1077 enum bfa_pport_topology
1078 bfa_pport_get_topology(struct bfa_s *bfa)
1079 {
1080         struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
1081
1082         return port->topology;
1083 }
1084
1085 bfa_status_t
1086 bfa_pport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa)
1087 {
1088         struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1089
1090         bfa_trc(bfa, alpa);
1091         bfa_trc(bfa, pport->cfg.cfg_hardalpa);
1092         bfa_trc(bfa, pport->cfg.hardalpa);
1093
1094         pport->cfg.cfg_hardalpa = BFA_TRUE;
1095         pport->cfg.hardalpa = alpa;
1096
1097         return (BFA_STATUS_OK);
1098 }
1099
1100 bfa_status_t
1101 bfa_pport_clr_hardalpa(struct bfa_s *bfa)
1102 {
1103         struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1104
1105         bfa_trc(bfa, pport->cfg.cfg_hardalpa);
1106         bfa_trc(bfa, pport->cfg.hardalpa);
1107
1108         pport->cfg.cfg_hardalpa = BFA_FALSE;
1109         return (BFA_STATUS_OK);
1110 }
1111
1112 bfa_boolean_t
1113 bfa_pport_get_hardalpa(struct bfa_s *bfa, u8 *alpa)
1114 {
1115         struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
1116
1117         *alpa = port->cfg.hardalpa;
1118         return port->cfg.cfg_hardalpa;
1119 }
1120
1121 u8
1122 bfa_pport_get_myalpa(struct bfa_s *bfa)
1123 {
1124         struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
1125
1126         return port->myalpa;
1127 }
1128
1129 bfa_status_t
1130 bfa_pport_cfg_maxfrsize(struct bfa_s *bfa, u16 maxfrsize)
1131 {
1132         struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1133
1134         bfa_trc(bfa, maxfrsize);
1135         bfa_trc(bfa, pport->cfg.maxfrsize);
1136
1137         /*
1138          * with in range
1139          */
1140         if ((maxfrsize > FC_MAX_PDUSZ) || (maxfrsize < FC_MIN_PDUSZ))
1141                 return (BFA_STATUS_INVLD_DFSZ);
1142
1143         /*
1144          * power of 2, if not the max frame size of 2112
1145          */
1146         if ((maxfrsize != FC_MAX_PDUSZ) && (maxfrsize & (maxfrsize - 1)))
1147                 return (BFA_STATUS_INVLD_DFSZ);
1148
1149         pport->cfg.maxfrsize = maxfrsize;
1150         return (BFA_STATUS_OK);
1151 }
1152
1153 u16
1154 bfa_pport_get_maxfrsize(struct bfa_s *bfa)
1155 {
1156         struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
1157
1158         return port->cfg.maxfrsize;
1159 }
1160
1161 u32
1162 bfa_pport_mypid(struct bfa_s *bfa)
1163 {
1164         struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
1165
1166         return port->mypid;
1167 }
1168
1169 u8
1170 bfa_pport_get_rx_bbcredit(struct bfa_s *bfa)
1171 {
1172         struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
1173
1174         return port->cfg.rx_bbcredit;
1175 }
1176
1177 void
1178 bfa_pport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit)
1179 {
1180         struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
1181
1182         port->cfg.tx_bbcredit = (u8) tx_bbcredit;
1183         bfa_port_send_txcredit(port);
1184 }
1185
1186 /**
1187  * Get port attributes.
1188  */
1189
1190 wwn_t
1191 bfa_pport_get_wwn(struct bfa_s *bfa, bfa_boolean_t node)
1192 {
1193         struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1194         if (node)
1195                 return pport->nwwn;
1196         else
1197                 return pport->pwwn;
1198 }
1199
1200 void
1201 bfa_pport_get_attr(struct bfa_s *bfa, struct bfa_pport_attr_s *attr)
1202 {
1203         struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1204
1205         bfa_os_memset(attr, 0, sizeof(struct bfa_pport_attr_s));
1206
1207         attr->nwwn = pport->nwwn;
1208         attr->pwwn = pport->pwwn;
1209
1210         bfa_os_memcpy(&attr->pport_cfg, &pport->cfg,
1211                       sizeof(struct bfa_pport_cfg_s));
1212         /*
1213          * speed attributes
1214          */
1215         attr->pport_cfg.speed = pport->cfg.speed;
1216         attr->speed_supported = pport->speed_sup;
1217         attr->speed = pport->speed;
1218         attr->cos_supported = FC_CLASS_3;
1219
1220         /*
1221          * topology attributes
1222          */
1223         attr->pport_cfg.topology = pport->cfg.topology;
1224         attr->topology = pport->topology;
1225
1226         /*
1227          * beacon attributes
1228          */
1229         attr->beacon = pport->beacon;
1230         attr->link_e2e_beacon = pport->link_e2e_beacon;
1231         attr->plog_enabled = bfa_plog_get_setting(pport->bfa->plog);
1232
1233         attr->pport_cfg.path_tov = bfa_fcpim_path_tov_get(bfa);
1234         attr->pport_cfg.q_depth = bfa_fcpim_qdepth_get(bfa);
1235         attr->port_state = bfa_sm_to_state(hal_pport_sm_table, pport->sm);
1236         if (bfa_ioc_is_disabled(&pport->bfa->ioc))
1237                 attr->port_state = BFA_PPORT_ST_IOCDIS;
1238         else if (bfa_ioc_fw_mismatch(&pport->bfa->ioc))
1239                 attr->port_state = BFA_PPORT_ST_FWMISMATCH;
1240 }
1241
1242 static void
1243 bfa_port_stats_query(void *cbarg)
1244 {
1245         struct bfa_pport_s *port = (struct bfa_pport_s *)cbarg;
1246         bfi_pport_get_stats_req_t *msg;
1247
1248         msg = bfa_reqq_next(port->bfa, BFA_REQQ_PORT);
1249
1250         if (!msg) {
1251                 port->stats_qfull = BFA_TRUE;
1252                 bfa_reqq_winit(&port->stats_reqq_wait, bfa_port_stats_query,
1253                                port);
1254                 bfa_reqq_wait(port->bfa, BFA_REQQ_PORT, &port->stats_reqq_wait);
1255                 return;
1256         }
1257         port->stats_qfull = BFA_FALSE;
1258
1259         bfa_os_memset(msg, 0, sizeof(bfi_pport_get_stats_req_t));
1260         bfi_h2i_set(msg->mh, BFI_MC_FC_PORT, BFI_PPORT_H2I_GET_STATS_REQ,
1261                     bfa_lpuid(port->bfa));
1262         bfa_reqq_produce(port->bfa, BFA_REQQ_PORT);
1263
1264         return;
1265 }
1266
1267 static void
1268 bfa_port_stats_clear(void *cbarg)
1269 {
1270         struct bfa_pport_s *port = (struct bfa_pport_s *)cbarg;
1271         bfi_pport_clear_stats_req_t *msg;
1272
1273         msg = bfa_reqq_next(port->bfa, BFA_REQQ_PORT);
1274
1275         if (!msg) {
1276                 port->stats_qfull = BFA_TRUE;
1277                 bfa_reqq_winit(&port->stats_reqq_wait, bfa_port_stats_clear,
1278                                port);
1279                 bfa_reqq_wait(port->bfa, BFA_REQQ_PORT, &port->stats_reqq_wait);
1280                 return;
1281         }
1282         port->stats_qfull = BFA_FALSE;
1283
1284         bfa_os_memset(msg, 0, sizeof(bfi_pport_clear_stats_req_t));
1285         bfi_h2i_set(msg->mh, BFI_MC_FC_PORT, BFI_PPORT_H2I_CLEAR_STATS_REQ,
1286                     bfa_lpuid(port->bfa));
1287         bfa_reqq_produce(port->bfa, BFA_REQQ_PORT);
1288         return;
1289 }
1290
1291 static void
1292 bfa_port_qos_stats_clear(void *cbarg)
1293 {
1294         struct bfa_pport_s *port = (struct bfa_pport_s *)cbarg;
1295         bfi_pport_clear_qos_stats_req_t *msg;
1296
1297         msg = bfa_reqq_next(port->bfa, BFA_REQQ_PORT);
1298
1299         if (!msg) {
1300                 port->stats_qfull = BFA_TRUE;
1301                 bfa_reqq_winit(&port->stats_reqq_wait, bfa_port_qos_stats_clear,
1302                                port);
1303                 bfa_reqq_wait(port->bfa, BFA_REQQ_PORT, &port->stats_reqq_wait);
1304                 return;
1305         }
1306         port->stats_qfull = BFA_FALSE;
1307
1308         bfa_os_memset(msg, 0, sizeof(bfi_pport_clear_qos_stats_req_t));
1309         bfi_h2i_set(msg->mh, BFI_MC_FC_PORT, BFI_PPORT_H2I_CLEAR_QOS_STATS_REQ,
1310                     bfa_lpuid(port->bfa));
1311         bfa_reqq_produce(port->bfa, BFA_REQQ_PORT);
1312         return;
1313 }
1314
1315 static void
1316 bfa_pport_stats_swap(union bfa_pport_stats_u *d, union bfa_pport_stats_u *s)
1317 {
1318         u32       *dip = (u32 *) d;
1319         u32       *sip = (u32 *) s;
1320         int             i;
1321
1322         /*
1323          * Do 64 bit fields swap first
1324          */
1325         for (i = 0;
1326              i <
1327              ((sizeof(union bfa_pport_stats_u) -
1328                sizeof(struct bfa_qos_stats_s)) / sizeof(u32)); i = i + 2) {
1329 #ifdef __BIGENDIAN
1330                 dip[i] = bfa_os_ntohl(sip[i]);
1331                 dip[i + 1] = bfa_os_ntohl(sip[i + 1]);
1332 #else
1333                 dip[i] = bfa_os_ntohl(sip[i + 1]);
1334                 dip[i + 1] = bfa_os_ntohl(sip[i]);
1335 #endif
1336         }
1337
1338         /*
1339          * Now swap the 32 bit fields
1340          */
1341         for (; i < (sizeof(union bfa_pport_stats_u) / sizeof(u32)); ++i)
1342                 dip[i] = bfa_os_ntohl(sip[i]);
1343 }
1344
1345 static void
1346 __bfa_cb_port_stats_clr(void *cbarg, bfa_boolean_t complete)
1347 {
1348         struct bfa_pport_s *port = cbarg;
1349
1350         if (complete) {
1351                 port->stats_cbfn(port->stats_cbarg, port->stats_status);
1352         } else {
1353                 port->stats_busy = BFA_FALSE;
1354                 port->stats_status = BFA_STATUS_OK;
1355         }
1356 }
1357
1358 static void
1359 bfa_port_stats_clr_timeout(void *cbarg)
1360 {
1361         struct bfa_pport_s *port = (struct bfa_pport_s *)cbarg;
1362
1363         bfa_trc(port->bfa, port->stats_qfull);
1364
1365         if (port->stats_qfull) {
1366                 bfa_reqq_wcancel(&port->stats_reqq_wait);
1367                 port->stats_qfull = BFA_FALSE;
1368         }
1369
1370         port->stats_status = BFA_STATUS_ETIMER;
1371         bfa_cb_queue(port->bfa, &port->hcb_qe, __bfa_cb_port_stats_clr, port);
1372 }
1373
1374 static void
1375 __bfa_cb_port_stats(void *cbarg, bfa_boolean_t complete)
1376 {
1377         struct bfa_pport_s *port = cbarg;
1378
1379         if (complete) {
1380                 if (port->stats_status == BFA_STATUS_OK)
1381                         bfa_pport_stats_swap(port->stats_ret, port->stats);
1382                 port->stats_cbfn(port->stats_cbarg, port->stats_status);
1383         } else {
1384                 port->stats_busy = BFA_FALSE;
1385                 port->stats_status = BFA_STATUS_OK;
1386         }
1387 }
1388
1389 static void
1390 bfa_port_stats_timeout(void *cbarg)
1391 {
1392         struct bfa_pport_s *port = (struct bfa_pport_s *)cbarg;
1393
1394         bfa_trc(port->bfa, port->stats_qfull);
1395
1396         if (port->stats_qfull) {
1397                 bfa_reqq_wcancel(&port->stats_reqq_wait);
1398                 port->stats_qfull = BFA_FALSE;
1399         }
1400
1401         port->stats_status = BFA_STATUS_ETIMER;
1402         bfa_cb_queue(port->bfa, &port->hcb_qe, __bfa_cb_port_stats, port);
1403 }
1404
1405 #define BFA_PORT_STATS_TOV      1000
1406
1407 /**
1408  * Fetch port attributes.
1409  */
1410 bfa_status_t
1411 bfa_pport_get_stats(struct bfa_s *bfa, union bfa_pport_stats_u *stats,
1412                     bfa_cb_pport_t cbfn, void *cbarg)
1413 {
1414         struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
1415
1416         if (port->stats_busy) {
1417                 bfa_trc(bfa, port->stats_busy);
1418                 return (BFA_STATUS_DEVBUSY);
1419         }
1420
1421         port->stats_busy = BFA_TRUE;
1422         port->stats_ret = stats;
1423         port->stats_cbfn = cbfn;
1424         port->stats_cbarg = cbarg;
1425
1426         bfa_port_stats_query(port);
1427
1428         bfa_timer_start(bfa, &port->timer, bfa_port_stats_timeout, port,
1429                         BFA_PORT_STATS_TOV);
1430         return (BFA_STATUS_OK);
1431 }
1432
1433 bfa_status_t
1434 bfa_pport_clear_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn, void *cbarg)
1435 {
1436         struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
1437
1438         if (port->stats_busy) {
1439                 bfa_trc(bfa, port->stats_busy);
1440                 return (BFA_STATUS_DEVBUSY);
1441         }
1442
1443         port->stats_busy = BFA_TRUE;
1444         port->stats_cbfn = cbfn;
1445         port->stats_cbarg = cbarg;
1446
1447         bfa_port_stats_clear(port);
1448
1449         bfa_timer_start(bfa, &port->timer, bfa_port_stats_clr_timeout, port,
1450                         BFA_PORT_STATS_TOV);
1451         return (BFA_STATUS_OK);
1452 }
1453
1454 bfa_status_t
1455 bfa_pport_trunk_enable(struct bfa_s *bfa, u8 bitmap)
1456 {
1457         struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1458
1459         bfa_trc(bfa, bitmap);
1460         bfa_trc(bfa, pport->cfg.trunked);
1461         bfa_trc(bfa, pport->cfg.trunk_ports);
1462
1463         if (!bitmap || (bitmap & (bitmap - 1)))
1464                 return BFA_STATUS_EINVAL;
1465
1466         pport->cfg.trunked = BFA_TRUE;
1467         pport->cfg.trunk_ports = bitmap;
1468
1469         return BFA_STATUS_OK;
1470 }
1471
1472 void
1473 bfa_pport_qos_get_attr(struct bfa_s *bfa, struct bfa_qos_attr_s *qos_attr)
1474 {
1475         struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1476
1477         qos_attr->state = bfa_os_ntohl(pport->qos_attr.state);
1478         qos_attr->total_bb_cr = bfa_os_ntohl(pport->qos_attr.total_bb_cr);
1479 }
1480
1481 void
1482 bfa_pport_qos_get_vc_attr(struct bfa_s *bfa,
1483                           struct bfa_qos_vc_attr_s *qos_vc_attr)
1484 {
1485         struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1486         struct bfa_qos_vc_attr_s *bfa_vc_attr = &pport->qos_vc_attr;
1487         u32        i = 0;
1488
1489         qos_vc_attr->total_vc_count = bfa_os_ntohs(bfa_vc_attr->total_vc_count);
1490         qos_vc_attr->shared_credit = bfa_os_ntohs(bfa_vc_attr->shared_credit);
1491         qos_vc_attr->elp_opmode_flags =
1492                 bfa_os_ntohl(bfa_vc_attr->elp_opmode_flags);
1493
1494         /*
1495          * Individual VC info
1496          */
1497         while (i < qos_vc_attr->total_vc_count) {
1498                 qos_vc_attr->vc_info[i].vc_credit =
1499                         bfa_vc_attr->vc_info[i].vc_credit;
1500                 qos_vc_attr->vc_info[i].borrow_credit =
1501                         bfa_vc_attr->vc_info[i].borrow_credit;
1502                 qos_vc_attr->vc_info[i].priority =
1503                         bfa_vc_attr->vc_info[i].priority;
1504                 ++i;
1505         }
1506 }
1507
1508 /**
1509  * Fetch QoS Stats.
1510  */
1511 bfa_status_t
1512 bfa_pport_get_qos_stats(struct bfa_s *bfa, union bfa_pport_stats_u *stats,
1513                         bfa_cb_pport_t cbfn, void *cbarg)
1514 {
1515         /*
1516          * QoS stats is embedded in port stats
1517          */
1518         return (bfa_pport_get_stats(bfa, stats, cbfn, cbarg));
1519 }
1520
1521 bfa_status_t
1522 bfa_pport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn, void *cbarg)
1523 {
1524         struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
1525
1526         if (port->stats_busy) {
1527                 bfa_trc(bfa, port->stats_busy);
1528                 return (BFA_STATUS_DEVBUSY);
1529         }
1530
1531         port->stats_busy = BFA_TRUE;
1532         port->stats_cbfn = cbfn;
1533         port->stats_cbarg = cbarg;
1534
1535         bfa_port_qos_stats_clear(port);
1536
1537         bfa_timer_start(bfa, &port->timer, bfa_port_stats_clr_timeout, port,
1538                         BFA_PORT_STATS_TOV);
1539         return (BFA_STATUS_OK);
1540 }
1541
1542 /**
1543  * Fetch port attributes.
1544  */
1545 bfa_status_t
1546 bfa_pport_trunk_disable(struct bfa_s *bfa)
1547 {
1548         return (BFA_STATUS_OK);
1549 }
1550
1551 bfa_boolean_t
1552 bfa_pport_trunk_query(struct bfa_s *bfa, u32 *bitmap)
1553 {
1554         struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
1555
1556         *bitmap = port->cfg.trunk_ports;
1557         return port->cfg.trunked;
1558 }
1559
1560 bfa_boolean_t
1561 bfa_pport_is_disabled(struct bfa_s *bfa)
1562 {
1563         struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
1564
1565         return (bfa_sm_to_state(hal_pport_sm_table, port->sm) ==
1566                 BFA_PPORT_ST_DISABLED);
1567
1568 }
1569
1570 bfa_boolean_t
1571 bfa_pport_is_ratelim(struct bfa_s *bfa)
1572 {
1573         struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1574
1575 return (pport->cfg.ratelimit ? BFA_TRUE : BFA_FALSE);
1576
1577 }
1578
1579 void
1580 bfa_pport_cfg_qos(struct bfa_s *bfa, bfa_boolean_t on_off)
1581 {
1582         struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1583
1584         bfa_trc(bfa, on_off);
1585         bfa_trc(bfa, pport->cfg.qos_enabled);
1586
1587         pport->cfg.qos_enabled = on_off;
1588 }
1589
1590 void
1591 bfa_pport_cfg_ratelim(struct bfa_s *bfa, bfa_boolean_t on_off)
1592 {
1593         struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1594
1595         bfa_trc(bfa, on_off);
1596         bfa_trc(bfa, pport->cfg.ratelimit);
1597
1598         pport->cfg.ratelimit = on_off;
1599         if (pport->cfg.trl_def_speed == BFA_PPORT_SPEED_UNKNOWN)
1600                 pport->cfg.trl_def_speed = BFA_PPORT_SPEED_1GBPS;
1601 }
1602
1603 /**
1604  * Configure default minimum ratelim speed
1605  */
1606 bfa_status_t
1607 bfa_pport_cfg_ratelim_speed(struct bfa_s *bfa, enum bfa_pport_speed speed)
1608 {
1609         struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1610
1611         bfa_trc(bfa, speed);
1612
1613         /*
1614          * Auto and speeds greater than the supported speed, are invalid
1615          */
1616         if ((speed == BFA_PPORT_SPEED_AUTO) || (speed > pport->speed_sup)) {
1617                 bfa_trc(bfa, pport->speed_sup);
1618                 return BFA_STATUS_UNSUPP_SPEED;
1619         }
1620
1621         pport->cfg.trl_def_speed = speed;
1622
1623         return (BFA_STATUS_OK);
1624 }
1625
1626 /**
1627  * Get default minimum ratelim speed
1628  */
1629 enum bfa_pport_speed
1630 bfa_pport_get_ratelim_speed(struct bfa_s *bfa)
1631 {
1632         struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1633
1634         bfa_trc(bfa, pport->cfg.trl_def_speed);
1635         return (pport->cfg.trl_def_speed);
1636
1637 }
1638
1639 void
1640 bfa_pport_busy(struct bfa_s *bfa, bfa_boolean_t status)
1641 {
1642         struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1643
1644         bfa_trc(bfa, status);
1645         bfa_trc(bfa, pport->diag_busy);
1646
1647         pport->diag_busy = status;
1648 }
1649
1650 void
1651 bfa_pport_beacon(struct bfa_s *bfa, bfa_boolean_t beacon,
1652                  bfa_boolean_t link_e2e_beacon)
1653 {
1654         struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1655
1656         bfa_trc(bfa, beacon);
1657         bfa_trc(bfa, link_e2e_beacon);
1658         bfa_trc(bfa, pport->beacon);
1659         bfa_trc(bfa, pport->link_e2e_beacon);
1660
1661         pport->beacon = beacon;
1662         pport->link_e2e_beacon = link_e2e_beacon;
1663 }
1664
1665 bfa_boolean_t
1666 bfa_pport_is_linkup(struct bfa_s *bfa)
1667 {
1668         return bfa_sm_cmp_state(BFA_PORT_MOD(bfa), bfa_pport_sm_linkup);
1669 }
1670
1671