• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/scsi/bfa/
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/**
19 *  rport.c Remote port implementation.
20 */
21
22#include <linux/slab.h>
23#include <bfa.h>
24#include <bfa_svc.h>
25#include "fcbuild.h"
26#include "fcs_vport.h"
27#include "fcs_lport.h"
28#include "fcs_rport.h"
29#include "fcs_fcpim.h"
30#include "fcs_fcptm.h"
31#include "fcs_trcmod.h"
32#include "fcs_fcxp.h"
33#include "fcs.h"
34#include <fcb/bfa_fcb_rport.h>
35#include <aen/bfa_aen_rport.h>
36
37BFA_TRC_FILE(FCS, RPORT);
38
39/* In millisecs */
40static u32 bfa_fcs_rport_del_timeout =
41			BFA_FCS_RPORT_DEF_DEL_TIMEOUT * 1000;
42
43/*
44 * forward declarations
45 */
46static struct bfa_fcs_rport_s *bfa_fcs_rport_alloc(struct bfa_fcs_port_s *port,
47						   wwn_t pwwn, u32 rpid);
48static void     bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport);
49static void     bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport);
50static void     bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport);
51static void     bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport);
52static void     bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport,
53				     struct fc_logi_s *plogi);
54static void     bfa_fcs_rport_fc4_pause(struct bfa_fcs_rport_s *rport);
55static void     bfa_fcs_rport_fc4_resume(struct bfa_fcs_rport_s *rport);
56static void     bfa_fcs_rport_timeout(void *arg);
57static void     bfa_fcs_rport_send_plogi(void *rport_cbarg,
58					 struct bfa_fcxp_s *fcxp_alloced);
59static void     bfa_fcs_rport_send_plogiacc(void *rport_cbarg,
60					    struct bfa_fcxp_s *fcxp_alloced);
61static void     bfa_fcs_rport_plogi_response(void *fcsarg,
62					     struct bfa_fcxp_s *fcxp,
63					     void *cbarg,
64					     bfa_status_t req_status,
65					     u32 rsp_len,
66					     u32 resid_len,
67					     struct fchs_s *rsp_fchs);
68static void     bfa_fcs_rport_send_adisc(void *rport_cbarg,
69					 struct bfa_fcxp_s *fcxp_alloced);
70static void     bfa_fcs_rport_adisc_response(void *fcsarg,
71					     struct bfa_fcxp_s *fcxp,
72					     void *cbarg,
73					     bfa_status_t req_status,
74					     u32 rsp_len,
75					     u32 resid_len,
76					     struct fchs_s *rsp_fchs);
77static void     bfa_fcs_rport_send_gidpn(void *rport_cbarg,
78					 struct bfa_fcxp_s *fcxp_alloced);
79static void     bfa_fcs_rport_gidpn_response(void *fcsarg,
80					     struct bfa_fcxp_s *fcxp,
81					     void *cbarg,
82					     bfa_status_t req_status,
83					     u32 rsp_len,
84					     u32 resid_len,
85					     struct fchs_s *rsp_fchs);
86static void     bfa_fcs_rport_send_logo(void *rport_cbarg,
87					struct bfa_fcxp_s *fcxp_alloced);
88static void     bfa_fcs_rport_send_logo_acc(void *rport_cbarg);
89static void     bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
90			struct fchs_s *rx_fchs, u16 len);
91static void     bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport,
92			struct fchs_s *rx_fchs, u8 reason_code,
93			u8 reason_code_expl);
94static void     bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
95			struct fchs_s *rx_fchs, u16 len);
96static void	bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport);
97/**
98 *  fcs_rport_sm FCS rport state machine events
99 */
100
101enum rport_event {
102	RPSM_EVENT_PLOGI_SEND = 1,	/*  new rport; start with PLOGI */
103	RPSM_EVENT_PLOGI_RCVD = 2,	/*  Inbound PLOGI from remote port */
104	RPSM_EVENT_PLOGI_COMP = 3,	/*  PLOGI completed to rport */
105	RPSM_EVENT_LOGO_RCVD = 4,	/*  LOGO from remote device */
106	RPSM_EVENT_LOGO_IMP = 5,	/*  implicit logo for SLER */
107	RPSM_EVENT_FCXP_SENT = 6,	/*  Frame from has been sent */
108	RPSM_EVENT_DELETE = 7,	/*  RPORT delete request */
109	RPSM_EVENT_SCN = 8,	/*  state change notification */
110	RPSM_EVENT_ACCEPTED = 9,/*  Good response from remote device */
111	RPSM_EVENT_FAILED = 10,	/*  Request to rport failed.  */
112	RPSM_EVENT_TIMEOUT = 11,	/*  Rport SM timeout event */
113	RPSM_EVENT_HCB_ONLINE = 12,	/*  BFA rport online callback */
114	RPSM_EVENT_HCB_OFFLINE = 13,	/*  BFA rport offline callback */
115	RPSM_EVENT_FC4_OFFLINE = 14,	/*  FC-4 offline complete */
116	RPSM_EVENT_ADDRESS_CHANGE = 15,	/*  Rport's PID has changed */
117	RPSM_EVENT_ADDRESS_DISC = 16,	/*  Need to Discover rport's PID */
118	RPSM_EVENT_PRLO_RCVD = 17,      /*  PRLO from remote device      */
119};
120
121static void     bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport,
122					enum rport_event event);
123static void     bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
124					       enum rport_event event);
125static void     bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
126						  enum rport_event event);
127static void     bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
128					     enum rport_event event);
129static void     bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport,
130				       enum rport_event event);
131static void     bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
132					    enum rport_event event);
133static void     bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport,
134					enum rport_event event);
135static void     bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
136						 enum rport_event event);
137static void     bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport,
138					 enum rport_event event);
139static void     bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
140					       enum rport_event event);
141static void     bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport,
142				       enum rport_event event);
143static void     bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
144					     enum rport_event event);
145static void     bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
146					      enum rport_event event);
147static void     bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
148					     enum rport_event event);
149static void     bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
150					     enum rport_event event);
151static void     bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
152					     enum rport_event event);
153static void     bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
154					      enum rport_event event);
155static void     bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
156					      enum rport_event event);
157static void     bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport,
158					 enum rport_event event);
159static void     bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
160						enum rport_event event);
161static void     bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
162					      enum rport_event event);
163static void     bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
164					     enum rport_event event);
165static void     bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
166					     enum rport_event event);
167
168static struct bfa_sm_table_s rport_sm_table[] = {
169	{BFA_SM(bfa_fcs_rport_sm_uninit), BFA_RPORT_UNINIT},
170	{BFA_SM(bfa_fcs_rport_sm_plogi_sending), BFA_RPORT_PLOGI},
171	{BFA_SM(bfa_fcs_rport_sm_plogiacc_sending), BFA_RPORT_ONLINE},
172	{BFA_SM(bfa_fcs_rport_sm_plogi_retry), BFA_RPORT_PLOGI_RETRY},
173	{BFA_SM(bfa_fcs_rport_sm_plogi), BFA_RPORT_PLOGI},
174	{BFA_SM(bfa_fcs_rport_sm_hal_online), BFA_RPORT_ONLINE},
175	{BFA_SM(bfa_fcs_rport_sm_online), BFA_RPORT_ONLINE},
176	{BFA_SM(bfa_fcs_rport_sm_nsquery_sending), BFA_RPORT_NSQUERY},
177	{BFA_SM(bfa_fcs_rport_sm_nsquery), BFA_RPORT_NSQUERY},
178	{BFA_SM(bfa_fcs_rport_sm_adisc_sending), BFA_RPORT_ADISC},
179	{BFA_SM(bfa_fcs_rport_sm_adisc), BFA_RPORT_ADISC},
180	{BFA_SM(bfa_fcs_rport_sm_fc4_logorcv), BFA_RPORT_LOGORCV},
181	{BFA_SM(bfa_fcs_rport_sm_fc4_logosend), BFA_RPORT_LOGO},
182	{BFA_SM(bfa_fcs_rport_sm_fc4_offline), BFA_RPORT_OFFLINE},
183	{BFA_SM(bfa_fcs_rport_sm_hcb_offline), BFA_RPORT_OFFLINE},
184	{BFA_SM(bfa_fcs_rport_sm_hcb_logorcv), BFA_RPORT_LOGORCV},
185	{BFA_SM(bfa_fcs_rport_sm_hcb_logosend), BFA_RPORT_LOGO},
186	{BFA_SM(bfa_fcs_rport_sm_logo_sending), BFA_RPORT_LOGO},
187	{BFA_SM(bfa_fcs_rport_sm_offline), BFA_RPORT_OFFLINE},
188	{BFA_SM(bfa_fcs_rport_sm_nsdisc_sending), BFA_RPORT_NSDISC},
189	{BFA_SM(bfa_fcs_rport_sm_nsdisc_retry), BFA_RPORT_NSDISC},
190	{BFA_SM(bfa_fcs_rport_sm_nsdisc_sent), BFA_RPORT_NSDISC},
191};
192
193/**
194 * 		Beginning state.
195 */
196static void
197bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, enum rport_event event)
198{
199	bfa_trc(rport->fcs, rport->pwwn);
200	bfa_trc(rport->fcs, rport->pid);
201	bfa_trc(rport->fcs, event);
202
203	switch (event) {
204	case RPSM_EVENT_PLOGI_SEND:
205		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
206		rport->plogi_retries = 0;
207		bfa_fcs_rport_send_plogi(rport, NULL);
208		break;
209
210	case RPSM_EVENT_PLOGI_RCVD:
211		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
212		bfa_fcs_rport_send_plogiacc(rport, NULL);
213		break;
214
215	case RPSM_EVENT_PLOGI_COMP:
216		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
217		bfa_fcs_rport_hal_online(rport);
218		break;
219
220	case RPSM_EVENT_ADDRESS_CHANGE:
221	case RPSM_EVENT_ADDRESS_DISC:
222		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
223		rport->ns_retries = 0;
224		bfa_fcs_rport_send_gidpn(rport, NULL);
225		break;
226
227	default:
228		bfa_sm_fault(rport->fcs, event);
229	}
230}
231
232/**
233 * 		PLOGI is being sent.
234 */
235static void
236bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
237			       enum rport_event event)
238{
239	bfa_trc(rport->fcs, rport->pwwn);
240	bfa_trc(rport->fcs, rport->pid);
241	bfa_trc(rport->fcs, event);
242
243	switch (event) {
244	case RPSM_EVENT_FCXP_SENT:
245		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi);
246		break;
247
248	case RPSM_EVENT_DELETE:
249		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
250		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
251		bfa_fcs_rport_free(rport);
252		break;
253
254	case RPSM_EVENT_PLOGI_RCVD:
255		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
256		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
257		bfa_fcs_rport_send_plogiacc(rport, NULL);
258		break;
259
260	case RPSM_EVENT_ADDRESS_CHANGE:
261		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
262		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
263		rport->ns_retries = 0;
264		bfa_fcs_rport_send_gidpn(rport, NULL);
265		break;
266
267	case RPSM_EVENT_LOGO_IMP:
268		rport->pid = 0;
269		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
270		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
271		bfa_timer_start(rport->fcs->bfa, &rport->timer,
272				bfa_fcs_rport_timeout, rport,
273				bfa_fcs_rport_del_timeout);
274		break;
275
276	case RPSM_EVENT_SCN:
277		break;
278
279	default:
280		bfa_sm_fault(rport->fcs, event);
281	}
282}
283
284/**
285 * 		PLOGI is being sent.
286 */
287static void
288bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
289				  enum rport_event event)
290{
291	bfa_trc(rport->fcs, rport->pwwn);
292	bfa_trc(rport->fcs, rport->pid);
293	bfa_trc(rport->fcs, event);
294
295	switch (event) {
296	case RPSM_EVENT_FCXP_SENT:
297		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
298		bfa_fcs_rport_hal_online(rport);
299		break;
300
301	case RPSM_EVENT_DELETE:
302		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
303		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
304		bfa_fcs_rport_free(rport);
305		break;
306
307	case RPSM_EVENT_SCN:
308		/**
309		 * Ignore, SCN is possibly online notification.
310		 */
311		break;
312
313	case RPSM_EVENT_ADDRESS_CHANGE:
314		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
315		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
316		rport->ns_retries = 0;
317		bfa_fcs_rport_send_gidpn(rport, NULL);
318		break;
319
320	case RPSM_EVENT_LOGO_IMP:
321		rport->pid = 0;
322		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
323		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
324		bfa_timer_start(rport->fcs->bfa, &rport->timer,
325				bfa_fcs_rport_timeout, rport,
326				bfa_fcs_rport_del_timeout);
327		break;
328
329	case RPSM_EVENT_HCB_OFFLINE:
330		/**
331		 * Ignore BFA callback, on a PLOGI receive we call bfa offline.
332		 */
333		break;
334
335	default:
336		bfa_sm_fault(rport->fcs, event);
337	}
338}
339
340/**
341 * 		PLOGI is sent.
342 */
343static void
344bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
345			enum rport_event event)
346{
347	bfa_trc(rport->fcs, rport->pwwn);
348	bfa_trc(rport->fcs, rport->pid);
349	bfa_trc(rport->fcs, event);
350
351	switch (event) {
352	case RPSM_EVENT_SCN:
353		bfa_timer_stop(&rport->timer);
354		/*
355		 * !! fall through !!
356		 */
357
358	case RPSM_EVENT_TIMEOUT:
359		if (rport->plogi_retries < BFA_FCS_RPORT_MAX_RETRIES) {
360			rport->plogi_retries++;
361			bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
362			bfa_fcs_rport_send_plogi(rport, NULL);
363		} else {
364			rport->pid = 0;
365			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
366			bfa_timer_start(rport->fcs->bfa, &rport->timer,
367					bfa_fcs_rport_timeout, rport,
368					bfa_fcs_rport_del_timeout);
369		}
370		break;
371
372	case RPSM_EVENT_DELETE:
373		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
374		bfa_timer_stop(&rport->timer);
375		bfa_fcs_rport_free(rport);
376		break;
377
378	case RPSM_EVENT_PRLO_RCVD:
379	case RPSM_EVENT_LOGO_RCVD:
380		break;
381
382	case RPSM_EVENT_PLOGI_RCVD:
383		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
384		bfa_timer_stop(&rport->timer);
385		bfa_fcs_rport_send_plogiacc(rport, NULL);
386		break;
387
388	case RPSM_EVENT_ADDRESS_CHANGE:
389		bfa_timer_stop(&rport->timer);
390		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
391		rport->ns_retries = 0;
392		bfa_fcs_rport_send_gidpn(rport, NULL);
393		break;
394
395	case RPSM_EVENT_LOGO_IMP:
396		rport->pid = 0;
397		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
398		bfa_timer_stop(&rport->timer);
399		bfa_timer_start(rport->fcs->bfa, &rport->timer,
400				bfa_fcs_rport_timeout, rport,
401				bfa_fcs_rport_del_timeout);
402		break;
403
404	case RPSM_EVENT_PLOGI_COMP:
405		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
406		bfa_timer_stop(&rport->timer);
407		bfa_fcs_rport_hal_online(rport);
408		break;
409
410	default:
411		bfa_sm_fault(rport->fcs, event);
412	}
413}
414
415/**
416 * 		PLOGI is sent.
417 */
418static void
419bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
420{
421	bfa_trc(rport->fcs, rport->pwwn);
422	bfa_trc(rport->fcs, rport->pid);
423	bfa_trc(rport->fcs, event);
424
425	switch (event) {
426	case RPSM_EVENT_ACCEPTED:
427		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
428		rport->plogi_retries = 0;
429		bfa_fcs_rport_hal_online(rport);
430		break;
431
432	case RPSM_EVENT_LOGO_RCVD:
433		bfa_fcs_rport_send_logo_acc(rport);
434		/*
435		 * !! fall through !!
436		 */
437	case RPSM_EVENT_PRLO_RCVD:
438		if (rport->prlo == BFA_TRUE)
439			bfa_fcs_rport_send_prlo_acc(rport);
440
441		bfa_fcxp_discard(rport->fcxp);
442		/*
443		 * !! fall through !!
444		 */
445	case RPSM_EVENT_FAILED:
446		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);
447		bfa_timer_start(rport->fcs->bfa, &rport->timer,
448				bfa_fcs_rport_timeout, rport,
449				BFA_FCS_RETRY_TIMEOUT);
450		break;
451
452	case RPSM_EVENT_LOGO_IMP:
453		rport->pid = 0;
454		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
455		bfa_fcxp_discard(rport->fcxp);
456		bfa_timer_start(rport->fcs->bfa, &rport->timer,
457				bfa_fcs_rport_timeout, rport,
458				bfa_fcs_rport_del_timeout);
459		break;
460
461	case RPSM_EVENT_ADDRESS_CHANGE:
462		bfa_fcxp_discard(rport->fcxp);
463		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
464		rport->ns_retries = 0;
465		bfa_fcs_rport_send_gidpn(rport, NULL);
466		break;
467
468	case RPSM_EVENT_PLOGI_RCVD:
469		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
470		bfa_fcxp_discard(rport->fcxp);
471		bfa_fcs_rport_send_plogiacc(rport, NULL);
472		break;
473
474	case RPSM_EVENT_SCN:
475		/**
476		 * Ignore SCN - wait for PLOGI response.
477		 */
478		break;
479
480	case RPSM_EVENT_DELETE:
481		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
482		bfa_fcxp_discard(rport->fcxp);
483		bfa_fcs_rport_free(rport);
484		break;
485
486	case RPSM_EVENT_PLOGI_COMP:
487		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
488		bfa_fcxp_discard(rport->fcxp);
489		bfa_fcs_rport_hal_online(rport);
490		break;
491
492	default:
493		bfa_sm_fault(rport->fcs, event);
494	}
495}
496
497/**
498 * 		PLOGI is complete. Awaiting BFA rport online callback. FC-4s
499 * 		are offline.
500 */
501static void
502bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
503			enum rport_event event)
504{
505	bfa_trc(rport->fcs, rport->pwwn);
506	bfa_trc(rport->fcs, rport->pid);
507	bfa_trc(rport->fcs, event);
508
509	switch (event) {
510	case RPSM_EVENT_HCB_ONLINE:
511		bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
512		bfa_fcs_rport_online_action(rport);
513		break;
514
515	case RPSM_EVENT_PRLO_RCVD:
516		break;
517
518	case RPSM_EVENT_LOGO_RCVD:
519		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
520		bfa_rport_offline(rport->bfa_rport);
521		break;
522
523	case RPSM_EVENT_LOGO_IMP:
524	case RPSM_EVENT_ADDRESS_CHANGE:
525		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
526		bfa_rport_offline(rport->bfa_rport);
527		break;
528
529	case RPSM_EVENT_PLOGI_RCVD:
530		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
531		bfa_rport_offline(rport->bfa_rport);
532		bfa_fcs_rport_send_plogiacc(rport, NULL);
533		break;
534
535	case RPSM_EVENT_DELETE:
536		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
537		bfa_rport_offline(rport->bfa_rport);
538		break;
539
540	case RPSM_EVENT_SCN:
541		/**
542		 * @todo
543		 * Ignore SCN - PLOGI just completed, FC-4 login should detect
544		 * device failures.
545		 */
546		break;
547
548	default:
549		bfa_sm_fault(rport->fcs, event);
550	}
551}
552
553/**
554 * 		Rport is ONLINE. FC-4s active.
555 */
556static void
557bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)
558{
559	bfa_trc(rport->fcs, rport->pwwn);
560	bfa_trc(rport->fcs, rport->pid);
561	bfa_trc(rport->fcs, event);
562
563	switch (event) {
564	case RPSM_EVENT_SCN:
565		/**
566		 * Pause FC-4 activity till rport is authenticated.
567		 * In switched fabrics, check presence of device in nameserver
568		 * first.
569		 */
570		bfa_fcs_rport_fc4_pause(rport);
571
572		if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
573			bfa_sm_set_state(rport,
574					 bfa_fcs_rport_sm_nsquery_sending);
575			rport->ns_retries = 0;
576			bfa_fcs_rport_send_gidpn(rport, NULL);
577		} else {
578			bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending);
579			bfa_fcs_rport_send_adisc(rport, NULL);
580		}
581		break;
582
583	case RPSM_EVENT_PLOGI_RCVD:
584	case RPSM_EVENT_LOGO_IMP:
585	case RPSM_EVENT_ADDRESS_CHANGE:
586		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
587		bfa_fcs_rport_offline_action(rport);
588		break;
589
590	case RPSM_EVENT_DELETE:
591		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
592		bfa_fcs_rport_offline_action(rport);
593		break;
594
595	case RPSM_EVENT_LOGO_RCVD:
596	case RPSM_EVENT_PRLO_RCVD:
597		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
598		bfa_fcs_rport_offline_action(rport);
599		break;
600
601	case RPSM_EVENT_PLOGI_COMP:
602		break;
603
604	default:
605		bfa_sm_fault(rport->fcs, event);
606	}
607}
608
609/**
610 * 		An SCN event is received in ONLINE state. NS query is being sent
611 * 		prior to ADISC authentication with rport. FC-4s are paused.
612 */
613static void
614bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
615				 enum rport_event event)
616{
617	bfa_trc(rport->fcs, rport->pwwn);
618	bfa_trc(rport->fcs, rport->pid);
619	bfa_trc(rport->fcs, event);
620
621	switch (event) {
622	case RPSM_EVENT_FCXP_SENT:
623		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsquery);
624		break;
625
626	case RPSM_EVENT_DELETE:
627		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
628		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
629		bfa_fcs_rport_offline_action(rport);
630		break;
631
632	case RPSM_EVENT_SCN:
633		/**
634		 * ignore SCN, wait for response to query itself
635		 */
636		break;
637
638	case RPSM_EVENT_LOGO_RCVD:
639	case RPSM_EVENT_PRLO_RCVD:
640		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
641		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
642		bfa_fcs_rport_offline_action(rport);
643		break;
644
645	case RPSM_EVENT_LOGO_IMP:
646		rport->pid = 0;
647		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
648		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
649		bfa_timer_start(rport->fcs->bfa, &rport->timer,
650				bfa_fcs_rport_timeout, rport,
651				bfa_fcs_rport_del_timeout);
652		break;
653
654	case RPSM_EVENT_PLOGI_RCVD:
655	case RPSM_EVENT_ADDRESS_CHANGE:
656	case RPSM_EVENT_PLOGI_COMP:
657		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
658		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
659		bfa_fcs_rport_offline_action(rport);
660		break;
661
662	default:
663		bfa_sm_fault(rport->fcs, event);
664	}
665}
666
667/**
668 * 	An SCN event is received in ONLINE state. NS query is sent to rport.
669 * 	FC-4s are paused.
670 */
671static void
672bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
673{
674	bfa_trc(rport->fcs, rport->pwwn);
675	bfa_trc(rport->fcs, rport->pid);
676	bfa_trc(rport->fcs, event);
677
678	switch (event) {
679	case RPSM_EVENT_ACCEPTED:
680		bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending);
681		bfa_fcs_rport_send_adisc(rport, NULL);
682		break;
683
684	case RPSM_EVENT_FAILED:
685		rport->ns_retries++;
686		if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {
687			bfa_sm_set_state(rport,
688					 bfa_fcs_rport_sm_nsquery_sending);
689			bfa_fcs_rport_send_gidpn(rport, NULL);
690		} else {
691			bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
692			bfa_fcs_rport_offline_action(rport);
693		}
694		break;
695
696	case RPSM_EVENT_DELETE:
697		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
698		bfa_fcxp_discard(rport->fcxp);
699		bfa_fcs_rport_offline_action(rport);
700		break;
701
702	case RPSM_EVENT_SCN:
703		break;
704
705	case RPSM_EVENT_LOGO_RCVD:
706	case RPSM_EVENT_PRLO_RCVD:
707		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
708		bfa_fcxp_discard(rport->fcxp);
709		bfa_fcs_rport_offline_action(rport);
710		break;
711
712	case RPSM_EVENT_PLOGI_COMP:
713	case RPSM_EVENT_ADDRESS_CHANGE:
714	case RPSM_EVENT_PLOGI_RCVD:
715	case RPSM_EVENT_LOGO_IMP:
716		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
717		bfa_fcxp_discard(rport->fcxp);
718		bfa_fcs_rport_offline_action(rport);
719		break;
720
721	default:
722		bfa_sm_fault(rport->fcs, event);
723	}
724}
725
726/**
727 * 	An SCN event is received in ONLINE state. ADISC is being sent for
728 * 	authenticating with rport. FC-4s are paused.
729 */
730static void
731bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
732			       enum rport_event event)
733{
734	bfa_trc(rport->fcs, rport->pwwn);
735	bfa_trc(rport->fcs, rport->pid);
736	bfa_trc(rport->fcs, event);
737
738	switch (event) {
739	case RPSM_EVENT_FCXP_SENT:
740		bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc);
741		break;
742
743	case RPSM_EVENT_DELETE:
744		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
745		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
746		bfa_fcs_rport_offline_action(rport);
747		break;
748
749	case RPSM_EVENT_LOGO_IMP:
750	case RPSM_EVENT_ADDRESS_CHANGE:
751		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
752		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
753		bfa_fcs_rport_offline_action(rport);
754		break;
755
756	case RPSM_EVENT_LOGO_RCVD:
757	case RPSM_EVENT_PRLO_RCVD:
758		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
759		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
760		bfa_fcs_rport_offline_action(rport);
761		break;
762
763	case RPSM_EVENT_SCN:
764		break;
765
766	case RPSM_EVENT_PLOGI_RCVD:
767		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
768		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
769		bfa_fcs_rport_offline_action(rport);
770		break;
771
772	default:
773		bfa_sm_fault(rport->fcs, event);
774	}
775}
776
777/**
778 * 		An SCN event is received in ONLINE state. ADISC is to rport.
779 * 		FC-4s are paused.
780 */
781static void
782bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)
783{
784	bfa_trc(rport->fcs, rport->pwwn);
785	bfa_trc(rport->fcs, rport->pid);
786	bfa_trc(rport->fcs, event);
787
788	switch (event) {
789	case RPSM_EVENT_ACCEPTED:
790		bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
791		bfa_fcs_rport_fc4_resume(rport);
792		break;
793
794	case RPSM_EVENT_PLOGI_RCVD:
795		/**
796		 * Too complex to cleanup FC-4 & rport and then acc to PLOGI.
797		 * At least go offline when a PLOGI is received.
798		 */
799		bfa_fcxp_discard(rport->fcxp);
800		/*
801		 * !!! fall through !!!
802		 */
803
804	case RPSM_EVENT_FAILED:
805	case RPSM_EVENT_ADDRESS_CHANGE:
806		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
807		bfa_fcs_rport_offline_action(rport);
808		break;
809
810	case RPSM_EVENT_DELETE:
811		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
812		bfa_fcxp_discard(rport->fcxp);
813		bfa_fcs_rport_offline_action(rport);
814		break;
815
816	case RPSM_EVENT_SCN:
817		/**
818		 * already processing RSCN
819		 */
820		break;
821
822	case RPSM_EVENT_LOGO_IMP:
823		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
824		bfa_fcxp_discard(rport->fcxp);
825		bfa_fcs_rport_offline_action(rport);
826		break;
827
828	case RPSM_EVENT_LOGO_RCVD:
829	case RPSM_EVENT_PRLO_RCVD:
830		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
831		bfa_fcxp_discard(rport->fcxp);
832		bfa_fcs_rport_offline_action(rport);
833		break;
834
835	default:
836		bfa_sm_fault(rport->fcs, event);
837	}
838}
839
840/**
841 * 		Rport has sent LOGO. Awaiting FC-4 offline completion callback.
842 */
843static void
844bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
845			enum rport_event event)
846{
847	bfa_trc(rport->fcs, rport->pwwn);
848	bfa_trc(rport->fcs, rport->pid);
849	bfa_trc(rport->fcs, event);
850
851	switch (event) {
852	case RPSM_EVENT_FC4_OFFLINE:
853		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
854		bfa_rport_offline(rport->bfa_rport);
855		break;
856
857	case RPSM_EVENT_DELETE:
858		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
859		break;
860
861	case RPSM_EVENT_LOGO_RCVD:
862	case RPSM_EVENT_PRLO_RCVD:
863	case RPSM_EVENT_ADDRESS_CHANGE:
864		break;
865
866	default:
867		bfa_sm_fault(rport->fcs, event);
868	}
869}
870
871/**
872 * 		LOGO needs to be sent to rport. Awaiting FC-4 offline completion
873 * 		callback.
874 */
875static void
876bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
877			      enum rport_event event)
878{
879	bfa_trc(rport->fcs, rport->pwwn);
880	bfa_trc(rport->fcs, rport->pid);
881	bfa_trc(rport->fcs, event);
882
883	switch (event) {
884	case RPSM_EVENT_FC4_OFFLINE:
885		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
886		bfa_rport_offline(rport->bfa_rport);
887		break;
888
889	default:
890		bfa_sm_fault(rport->fcs, event);
891	}
892}
893
894/**
895 * 	Rport is going offline. Awaiting FC-4 offline completion callback.
896 */
897static void
898bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
899			enum rport_event event)
900{
901	bfa_trc(rport->fcs, rport->pwwn);
902	bfa_trc(rport->fcs, rport->pid);
903	bfa_trc(rport->fcs, event);
904
905	switch (event) {
906	case RPSM_EVENT_FC4_OFFLINE:
907		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
908		bfa_rport_offline(rport->bfa_rport);
909		break;
910
911	case RPSM_EVENT_SCN:
912	case RPSM_EVENT_LOGO_IMP:
913	case RPSM_EVENT_LOGO_RCVD:
914	case RPSM_EVENT_PRLO_RCVD:
915	case RPSM_EVENT_ADDRESS_CHANGE:
916		/**
917		 * rport is already going offline.
918		 * SCN - ignore and wait till transitioning to offline state
919		 */
920		break;
921
922	case RPSM_EVENT_DELETE:
923		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
924		break;
925
926	default:
927		bfa_sm_fault(rport->fcs, event);
928	}
929}
930
931/**
932 * 		Rport is offline. FC-4s are offline. Awaiting BFA rport offline
933 * 		callback.
934 */
935static void
936bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
937			enum rport_event event)
938{
939	bfa_trc(rport->fcs, rport->pwwn);
940	bfa_trc(rport->fcs, rport->pid);
941	bfa_trc(rport->fcs, event);
942
943	switch (event) {
944	case RPSM_EVENT_HCB_OFFLINE:
945	case RPSM_EVENT_ADDRESS_CHANGE:
946		if (bfa_fcs_port_is_online(rport->port)) {
947			if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
948				bfa_sm_set_state(rport,
949					bfa_fcs_rport_sm_nsdisc_sending);
950				rport->ns_retries = 0;
951				bfa_fcs_rport_send_gidpn(rport, NULL);
952			} else {
953				bfa_sm_set_state(rport,
954					bfa_fcs_rport_sm_plogi_sending);
955				rport->plogi_retries = 0;
956				bfa_fcs_rport_send_plogi(rport, NULL);
957			}
958		} else {
959			rport->pid = 0;
960			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
961			bfa_timer_start(rport->fcs->bfa, &rport->timer,
962					bfa_fcs_rport_timeout, rport,
963					bfa_fcs_rport_del_timeout);
964		}
965		break;
966
967	case RPSM_EVENT_DELETE:
968		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
969		bfa_fcs_rport_free(rport);
970		break;
971
972	case RPSM_EVENT_SCN:
973	case RPSM_EVENT_LOGO_RCVD:
974	case RPSM_EVENT_PRLO_RCVD:
975		/**
976		 * Ignore, already offline.
977		 */
978		break;
979
980	default:
981		bfa_sm_fault(rport->fcs, event);
982	}
983}
984
985/**
986 * 		Rport is offline. FC-4s are offline. Awaiting BFA rport offline
987 * 		callback to send LOGO accept.
988 */
989static void
990bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
991			enum rport_event event)
992{
993	bfa_trc(rport->fcs, rport->pwwn);
994	bfa_trc(rport->fcs, rport->pid);
995	bfa_trc(rport->fcs, event);
996
997	switch (event) {
998	case RPSM_EVENT_HCB_OFFLINE:
999	case RPSM_EVENT_ADDRESS_CHANGE:
1000		if (rport->pid && (rport->prlo == BFA_TRUE))
1001			bfa_fcs_rport_send_prlo_acc(rport);
1002		if (rport->pid && (rport->prlo == BFA_FALSE))
1003			bfa_fcs_rport_send_logo_acc(rport);
1004
1005		/*
1006		 * If the lport is online and if the rport is not a well known
1007		 * address port, we try to re-discover the r-port.
1008		 */
1009		if (bfa_fcs_port_is_online(rport->port)
1010		    && (!BFA_FCS_PID_IS_WKA(rport->pid))) {
1011			bfa_sm_set_state(rport,
1012					 bfa_fcs_rport_sm_nsdisc_sending);
1013			rport->ns_retries = 0;
1014			bfa_fcs_rport_send_gidpn(rport, NULL);
1015		} else {
1016			/*
1017			 * if it is not a well known address, reset the pid to
1018			 *
1019			 */
1020			if (!BFA_FCS_PID_IS_WKA(rport->pid))
1021				rport->pid = 0;
1022			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1023			bfa_timer_start(rport->fcs->bfa, &rport->timer,
1024					bfa_fcs_rport_timeout, rport,
1025					bfa_fcs_rport_del_timeout);
1026		}
1027		break;
1028
1029	case RPSM_EVENT_DELETE:
1030		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
1031		break;
1032
1033	case RPSM_EVENT_LOGO_IMP:
1034		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
1035		break;
1036
1037	case RPSM_EVENT_LOGO_RCVD:
1038	case RPSM_EVENT_PRLO_RCVD:
1039		/**
1040		 * Ignore - already processing a LOGO.
1041		 */
1042		break;
1043
1044	default:
1045		bfa_sm_fault(rport->fcs, event);
1046	}
1047}
1048
1049/**
1050 * Rport is being deleted. FC-4s are offline. Awaiting BFA rport offline
1051 * callback to send LOGO.
1052 */
1053static void
1054bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
1055			      enum rport_event event)
1056{
1057	bfa_trc(rport->fcs, rport->pwwn);
1058	bfa_trc(rport->fcs, rport->pid);
1059	bfa_trc(rport->fcs, event);
1060
1061	switch (event) {
1062	case RPSM_EVENT_HCB_OFFLINE:
1063		bfa_sm_set_state(rport, bfa_fcs_rport_sm_logo_sending);
1064		bfa_fcs_rport_send_logo(rport, NULL);
1065		break;
1066
1067	case RPSM_EVENT_LOGO_RCVD:
1068	case RPSM_EVENT_PRLO_RCVD:
1069	case RPSM_EVENT_ADDRESS_CHANGE:
1070		break;
1071
1072	default:
1073		bfa_sm_fault(rport->fcs, event);
1074	}
1075}
1076
1077/**
1078 * 		Rport is being deleted. FC-4s are offline. LOGO is being sent.
1079 */
1080static void
1081bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
1082			      enum rport_event event)
1083{
1084	bfa_trc(rport->fcs, rport->pwwn);
1085	bfa_trc(rport->fcs, rport->pid);
1086	bfa_trc(rport->fcs, event);
1087
1088	switch (event) {
1089	case RPSM_EVENT_FCXP_SENT:
1090		/*
1091		 * Once LOGO is sent, we donot wait for the response
1092		 */
1093		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1094		bfa_fcs_rport_free(rport);
1095		break;
1096
1097	case RPSM_EVENT_SCN:
1098	case RPSM_EVENT_ADDRESS_CHANGE:
1099		break;
1100
1101	case RPSM_EVENT_LOGO_RCVD:
1102	case RPSM_EVENT_PRLO_RCVD:
1103		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1104		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1105		bfa_fcs_rport_free(rport);
1106		break;
1107
1108	default:
1109		bfa_sm_fault(rport->fcs, event);
1110	}
1111}
1112
1113/**
1114 * 		Rport is offline. FC-4s are offline. BFA rport is offline.
1115 * 		Timer active to delete stale rport.
1116 */
1117static void
1118bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)
1119{
1120	bfa_trc(rport->fcs, rport->pwwn);
1121	bfa_trc(rport->fcs, rport->pid);
1122	bfa_trc(rport->fcs, event);
1123
1124	switch (event) {
1125	case RPSM_EVENT_TIMEOUT:
1126		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1127		bfa_fcs_rport_free(rport);
1128		break;
1129
1130	case RPSM_EVENT_SCN:
1131	case RPSM_EVENT_ADDRESS_CHANGE:
1132		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
1133		bfa_timer_stop(&rport->timer);
1134		rport->ns_retries = 0;
1135		bfa_fcs_rport_send_gidpn(rport, NULL);
1136		break;
1137
1138	case RPSM_EVENT_DELETE:
1139		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1140		bfa_timer_stop(&rport->timer);
1141		bfa_fcs_rport_free(rport);
1142		break;
1143
1144	case RPSM_EVENT_PLOGI_RCVD:
1145		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
1146		bfa_timer_stop(&rport->timer);
1147		bfa_fcs_rport_send_plogiacc(rport, NULL);
1148		break;
1149
1150	case RPSM_EVENT_LOGO_RCVD:
1151	case RPSM_EVENT_PRLO_RCVD:
1152	case RPSM_EVENT_LOGO_IMP:
1153		break;
1154
1155	case RPSM_EVENT_PLOGI_COMP:
1156		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
1157		bfa_timer_stop(&rport->timer);
1158		bfa_fcs_rport_hal_online(rport);
1159		break;
1160
1161	case RPSM_EVENT_PLOGI_SEND:
1162		bfa_timer_stop(&rport->timer);
1163		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
1164		rport->plogi_retries = 0;
1165		bfa_fcs_rport_send_plogi(rport, NULL);
1166		break;
1167
1168	default:
1169		bfa_sm_fault(rport->fcs, event);
1170	}
1171}
1172
1173/**
1174 * 	Rport address has changed. Nameserver discovery request is being sent.
1175 */
1176static void
1177bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
1178				enum rport_event event)
1179{
1180	bfa_trc(rport->fcs, rport->pwwn);
1181	bfa_trc(rport->fcs, rport->pid);
1182	bfa_trc(rport->fcs, event);
1183
1184	switch (event) {
1185	case RPSM_EVENT_FCXP_SENT:
1186		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sent);
1187		break;
1188
1189	case RPSM_EVENT_DELETE:
1190		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1191		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1192		bfa_fcs_rport_free(rport);
1193		break;
1194
1195	case RPSM_EVENT_PLOGI_RCVD:
1196		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
1197		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1198		bfa_fcs_rport_send_plogiacc(rport, NULL);
1199		break;
1200
1201	case RPSM_EVENT_SCN:
1202	case RPSM_EVENT_LOGO_RCVD:
1203	case RPSM_EVENT_PRLO_RCVD:
1204	case RPSM_EVENT_PLOGI_SEND:
1205		break;
1206
1207	case RPSM_EVENT_ADDRESS_CHANGE:
1208		rport->ns_retries = 0;	/* reset the retry count */
1209		break;
1210
1211	case RPSM_EVENT_LOGO_IMP:
1212		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1213		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1214		bfa_timer_start(rport->fcs->bfa, &rport->timer,
1215				bfa_fcs_rport_timeout, rport,
1216				bfa_fcs_rport_del_timeout);
1217		break;
1218
1219	case RPSM_EVENT_PLOGI_COMP:
1220		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
1221		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1222		bfa_fcs_rport_hal_online(rport);
1223		break;
1224
1225	default:
1226		bfa_sm_fault(rport->fcs, event);
1227	}
1228}
1229
1230/**
1231 * 		Nameserver discovery failed. Waiting for timeout to retry.
1232 */
1233static void
1234bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
1235			      enum rport_event event)
1236{
1237	bfa_trc(rport->fcs, rport->pwwn);
1238	bfa_trc(rport->fcs, rport->pid);
1239	bfa_trc(rport->fcs, event);
1240
1241	switch (event) {
1242	case RPSM_EVENT_TIMEOUT:
1243		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
1244		bfa_fcs_rport_send_gidpn(rport, NULL);
1245		break;
1246
1247	case RPSM_EVENT_SCN:
1248	case RPSM_EVENT_ADDRESS_CHANGE:
1249		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
1250		bfa_timer_stop(&rport->timer);
1251		rport->ns_retries = 0;
1252		bfa_fcs_rport_send_gidpn(rport, NULL);
1253		break;
1254
1255	case RPSM_EVENT_DELETE:
1256		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1257		bfa_timer_stop(&rport->timer);
1258		bfa_fcs_rport_free(rport);
1259		break;
1260
1261	case RPSM_EVENT_PLOGI_RCVD:
1262		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
1263		bfa_timer_stop(&rport->timer);
1264		bfa_fcs_rport_send_plogiacc(rport, NULL);
1265		break;
1266
1267	case RPSM_EVENT_LOGO_IMP:
1268		rport->pid = 0;
1269		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1270		bfa_timer_stop(&rport->timer);
1271		bfa_timer_start(rport->fcs->bfa, &rport->timer,
1272				bfa_fcs_rport_timeout, rport,
1273				bfa_fcs_rport_del_timeout);
1274		break;
1275
1276	case RPSM_EVENT_LOGO_RCVD:
1277		bfa_fcs_rport_send_logo_acc(rport);
1278		break;
1279
1280	case RPSM_EVENT_PRLO_RCVD:
1281		bfa_fcs_rport_send_prlo_acc(rport);
1282		break;
1283
1284	case RPSM_EVENT_PLOGI_COMP:
1285		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
1286		bfa_timer_stop(&rport->timer);
1287		bfa_fcs_rport_hal_online(rport);
1288		break;
1289
1290	default:
1291		bfa_sm_fault(rport->fcs, event);
1292	}
1293}
1294
1295/**
1296 * Rport address has changed. Nameserver discovery request is sent.
1297 */
1298static void
1299bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
1300			enum rport_event event)
1301{
1302	bfa_trc(rport->fcs, rport->pwwn);
1303	bfa_trc(rport->fcs, rport->pid);
1304	bfa_trc(rport->fcs, event);
1305
1306	switch (event) {
1307	case RPSM_EVENT_ACCEPTED:
1308	case RPSM_EVENT_ADDRESS_CHANGE:
1309		if (rport->pid) {
1310			bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
1311			bfa_fcs_rport_send_plogi(rport, NULL);
1312		} else {
1313			bfa_sm_set_state(rport,
1314					 bfa_fcs_rport_sm_nsdisc_sending);
1315			rport->ns_retries = 0;
1316			bfa_fcs_rport_send_gidpn(rport, NULL);
1317		}
1318		break;
1319
1320	case RPSM_EVENT_FAILED:
1321		rport->ns_retries++;
1322		if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {
1323			bfa_sm_set_state(rport,
1324					 bfa_fcs_rport_sm_nsdisc_sending);
1325			bfa_fcs_rport_send_gidpn(rport, NULL);
1326		} else {
1327			rport->pid = 0;
1328			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1329			bfa_timer_start(rport->fcs->bfa, &rport->timer,
1330					bfa_fcs_rport_timeout, rport,
1331					bfa_fcs_rport_del_timeout);
1332		};
1333		break;
1334
1335	case RPSM_EVENT_DELETE:
1336		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1337		bfa_fcxp_discard(rport->fcxp);
1338		bfa_fcs_rport_free(rport);
1339		break;
1340
1341	case RPSM_EVENT_PLOGI_RCVD:
1342		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
1343		bfa_fcxp_discard(rport->fcxp);
1344		bfa_fcs_rport_send_plogiacc(rport, NULL);
1345		break;
1346
1347	case RPSM_EVENT_LOGO_IMP:
1348		rport->pid = 0;
1349		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1350		bfa_fcxp_discard(rport->fcxp);
1351		bfa_timer_start(rport->fcs->bfa, &rport->timer,
1352				bfa_fcs_rport_timeout, rport,
1353				bfa_fcs_rport_del_timeout);
1354		break;
1355
1356	case RPSM_EVENT_PRLO_RCVD:
1357		bfa_fcs_rport_send_prlo_acc(rport);
1358		break;
1359
1360	case RPSM_EVENT_SCN:
1361		/**
1362		 * ignore, wait for NS query response
1363		 */
1364		break;
1365
1366	case RPSM_EVENT_LOGO_RCVD:
1367		/**
1368		 * Not logged-in yet. Accept LOGO.
1369		 */
1370		bfa_fcs_rport_send_logo_acc(rport);
1371		break;
1372
1373	case RPSM_EVENT_PLOGI_COMP:
1374		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
1375		bfa_fcxp_discard(rport->fcxp);
1376		bfa_fcs_rport_hal_online(rport);
1377		break;
1378
1379	default:
1380		bfa_sm_fault(rport->fcs, event);
1381	}
1382}
1383
1384
1385
1386/**
1387 *  fcs_rport_private FCS RPORT provate functions
1388 */
1389
1390static void
1391bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1392{
1393	struct bfa_fcs_rport_s *rport = rport_cbarg;
1394	struct bfa_fcs_port_s *port = rport->port;
1395	struct fchs_s          fchs;
1396	int             len;
1397	struct bfa_fcxp_s *fcxp;
1398
1399	bfa_trc(rport->fcs, rport->pwwn);
1400
1401	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1402	if (!fcxp) {
1403		bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1404				    bfa_fcs_rport_send_plogi, rport);
1405		return;
1406	}
1407	rport->fcxp = fcxp;
1408
1409	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
1410			     bfa_fcs_port_get_fcid(port), 0,
1411			     port->port_cfg.pwwn, port->port_cfg.nwwn,
1412			     bfa_fcport_get_maxfrsize(port->fcs->bfa));
1413
1414	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1415		      FC_CLASS_3, len, &fchs, bfa_fcs_rport_plogi_response,
1416		      (void *)rport, FC_MAX_PDUSZ, FC_ELS_TOV);
1417
1418	rport->stats.plogis++;
1419	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1420}
1421
1422static void
1423bfa_fcs_rport_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
1424			     bfa_status_t req_status, u32 rsp_len,
1425			     u32 resid_len, struct fchs_s *rsp_fchs)
1426{
1427	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
1428	struct fc_logi_s	*plogi_rsp;
1429	struct fc_ls_rjt_s	*ls_rjt;
1430	struct bfa_fcs_rport_s *twin;
1431	struct list_head *qe;
1432
1433	bfa_trc(rport->fcs, rport->pwwn);
1434
1435	/*
1436	 * Sanity Checks
1437	 */
1438	if (req_status != BFA_STATUS_OK) {
1439		bfa_trc(rport->fcs, req_status);
1440		rport->stats.plogi_failed++;
1441		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1442		return;
1443	}
1444
1445	plogi_rsp = (struct fc_logi_s *) BFA_FCXP_RSP_PLD(fcxp);
1446
1447	/**
1448	 * Check for failure first.
1449	 */
1450	if (plogi_rsp->els_cmd.els_code != FC_ELS_ACC) {
1451		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
1452
1453		bfa_trc(rport->fcs, ls_rjt->reason_code);
1454		bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
1455
1456		rport->stats.plogi_rejects++;
1457		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1458		return;
1459	}
1460
1461	/**
1462	 * PLOGI is complete. Make sure this device is not one of the known
1463	 * device with a new FC port address.
1464	 */
1465	list_for_each(qe, &rport->port->rport_q) {
1466		twin = (struct bfa_fcs_rport_s *)qe;
1467		if (twin == rport)
1468			continue;
1469		if (!rport->pwwn && (plogi_rsp->port_name == twin->pwwn)) {
1470			bfa_trc(rport->fcs, twin->pid);
1471			bfa_trc(rport->fcs, rport->pid);
1472
1473			/*
1474			 * Update plogi stats in twin
1475			 */
1476			twin->stats.plogis += rport->stats.plogis;
1477			twin->stats.plogi_rejects += rport->stats.plogi_rejects;
1478			twin->stats.plogi_timeouts +=
1479				rport->stats.plogi_timeouts;
1480			twin->stats.plogi_failed += rport->stats.plogi_failed;
1481			twin->stats.plogi_rcvd += rport->stats.plogi_rcvd;
1482			twin->stats.plogi_accs++;
1483
1484			bfa_fcs_rport_delete(rport);
1485
1486			bfa_fcs_rport_update(twin, plogi_rsp);
1487			twin->pid = rsp_fchs->s_id;
1488			bfa_sm_send_event(twin, RPSM_EVENT_PLOGI_COMP);
1489			return;
1490		}
1491	}
1492
1493	/**
1494	 * Normal login path -- no evil twins.
1495	 */
1496	rport->stats.plogi_accs++;
1497	bfa_fcs_rport_update(rport, plogi_rsp);
1498	bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
1499}
1500
1501static void
1502bfa_fcs_rport_send_plogiacc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1503{
1504	struct bfa_fcs_rport_s *rport = rport_cbarg;
1505	struct bfa_fcs_port_s *port = rport->port;
1506	struct fchs_s          fchs;
1507	int             len;
1508	struct bfa_fcxp_s *fcxp;
1509
1510	bfa_trc(rport->fcs, rport->pwwn);
1511	bfa_trc(rport->fcs, rport->reply_oxid);
1512
1513	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1514	if (!fcxp) {
1515		bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1516				    bfa_fcs_rport_send_plogiacc, rport);
1517		return;
1518	}
1519	rport->fcxp = fcxp;
1520
1521	len = fc_plogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
1522				 bfa_fcs_port_get_fcid(port), rport->reply_oxid,
1523				 port->port_cfg.pwwn, port->port_cfg.nwwn,
1524				 bfa_fcport_get_maxfrsize(port->fcs->bfa));
1525
1526	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1527		      FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
1528
1529	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1530}
1531
1532static void
1533bfa_fcs_rport_send_adisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1534{
1535	struct bfa_fcs_rport_s *rport = rport_cbarg;
1536	struct bfa_fcs_port_s *port = rport->port;
1537	struct fchs_s          fchs;
1538	int             len;
1539	struct bfa_fcxp_s *fcxp;
1540
1541	bfa_trc(rport->fcs, rport->pwwn);
1542
1543	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1544	if (!fcxp) {
1545		bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1546				    bfa_fcs_rport_send_adisc, rport);
1547		return;
1548	}
1549	rport->fcxp = fcxp;
1550
1551	len = fc_adisc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
1552			     bfa_fcs_port_get_fcid(port), 0,
1553			     port->port_cfg.pwwn, port->port_cfg.nwwn);
1554
1555	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1556		      FC_CLASS_3, len, &fchs, bfa_fcs_rport_adisc_response,
1557		      rport, FC_MAX_PDUSZ, FC_ELS_TOV);
1558
1559	rport->stats.adisc_sent++;
1560	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1561}
1562
1563static void
1564bfa_fcs_rport_adisc_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
1565			     bfa_status_t req_status, u32 rsp_len,
1566			     u32 resid_len, struct fchs_s *rsp_fchs)
1567{
1568	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
1569	void           *pld = bfa_fcxp_get_rspbuf(fcxp);
1570	struct fc_ls_rjt_s    *ls_rjt;
1571
1572	if (req_status != BFA_STATUS_OK) {
1573		bfa_trc(rport->fcs, req_status);
1574		rport->stats.adisc_failed++;
1575		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1576		return;
1577	}
1578
1579	if (fc_adisc_rsp_parse((struct fc_adisc_s *)pld, rsp_len, rport->pwwn,
1580		rport->nwwn)  == FC_PARSE_OK) {
1581		rport->stats.adisc_accs++;
1582		bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
1583		return;
1584	}
1585
1586	rport->stats.adisc_rejects++;
1587	ls_rjt = pld;
1588	bfa_trc(rport->fcs, ls_rjt->els_cmd.els_code);
1589	bfa_trc(rport->fcs, ls_rjt->reason_code);
1590	bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
1591	bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1592}
1593
1594static void
1595bfa_fcs_rport_send_gidpn(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1596{
1597	struct bfa_fcs_rport_s *rport = rport_cbarg;
1598	struct bfa_fcs_port_s *port = rport->port;
1599	struct fchs_s          fchs;
1600	struct bfa_fcxp_s *fcxp;
1601	int             len;
1602
1603	bfa_trc(rport->fcs, rport->pid);
1604
1605	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1606	if (!fcxp) {
1607		bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1608				    bfa_fcs_rport_send_gidpn, rport);
1609		return;
1610	}
1611	rport->fcxp = fcxp;
1612
1613	len = fc_gidpn_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
1614			     bfa_fcs_port_get_fcid(port), 0, rport->pwwn);
1615
1616	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1617		      FC_CLASS_3, len, &fchs, bfa_fcs_rport_gidpn_response,
1618		      (void *)rport, FC_MAX_PDUSZ, FC_FCCT_TOV);
1619
1620	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1621}
1622
1623static void
1624bfa_fcs_rport_gidpn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
1625			     bfa_status_t req_status, u32 rsp_len,
1626			     u32 resid_len, struct fchs_s *rsp_fchs)
1627{
1628	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
1629	struct bfa_fcs_rport_s *twin;
1630	struct list_head *qe;
1631	struct ct_hdr_s       	*cthdr;
1632	struct fcgs_gidpn_resp_s	*gidpn_rsp;
1633
1634	bfa_trc(rport->fcs, rport->pwwn);
1635
1636	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
1637	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
1638
1639	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
1640		/*
1641		 * Check if the pid is the same as before.
1642		 */
1643		gidpn_rsp = (struct fcgs_gidpn_resp_s *) (cthdr + 1);
1644
1645		if (gidpn_rsp->dap == rport->pid) {
1646			/*
1647			 * Device is online
1648			 */
1649			bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
1650		} else {
1651			/*
1652			 * Device's PID has changed. We need to cleanup and
1653			 * re-login. If there is another device with the the
1654			 * newly discovered pid, send an scn notice so that its
1655			 * new pid can be discovered.
1656			 */
1657			list_for_each(qe, &rport->port->rport_q) {
1658				twin = (struct bfa_fcs_rport_s *)qe;
1659				if (twin == rport)
1660					continue;
1661				if (gidpn_rsp->dap == twin->pid) {
1662					bfa_trc(rport->fcs, twin->pid);
1663					bfa_trc(rport->fcs, rport->pid);
1664
1665					twin->pid = 0;
1666					bfa_sm_send_event(twin,
1667						RPSM_EVENT_ADDRESS_CHANGE);
1668				}
1669			}
1670			rport->pid = gidpn_rsp->dap;
1671			bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_CHANGE);
1672		}
1673		return;
1674	}
1675
1676	/*
1677	 * Reject Response
1678	 */
1679	switch (cthdr->reason_code) {
1680	case CT_RSN_LOGICAL_BUSY:
1681		/*
1682		 * Need to retry
1683		 */
1684		bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
1685		break;
1686
1687	case CT_RSN_UNABLE_TO_PERF:
1688		/*
1689		 * device doesn't exist : Start timer to cleanup this later.
1690		 */
1691		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1692		break;
1693
1694	default:
1695		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1696		break;
1697	}
1698}
1699
1700/**
1701 *    Called to send a logout to the rport.
1702 */
1703static void
1704bfa_fcs_rport_send_logo(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1705{
1706	struct bfa_fcs_rport_s *rport = rport_cbarg;
1707	struct bfa_fcs_port_s *port;
1708	struct fchs_s          fchs;
1709	struct bfa_fcxp_s *fcxp;
1710	u16        len;
1711
1712	bfa_trc(rport->fcs, rport->pid);
1713
1714	port = rport->port;
1715
1716	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1717	if (!fcxp) {
1718		bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1719				    bfa_fcs_rport_send_logo, rport);
1720		return;
1721	}
1722	rport->fcxp = fcxp;
1723
1724	len = fc_logo_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
1725			    bfa_fcs_port_get_fcid(port), 0,
1726			    bfa_fcs_port_get_pwwn(port));
1727
1728	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1729		      FC_CLASS_3, len, &fchs, NULL, rport, FC_MAX_PDUSZ,
1730		      FC_ELS_TOV);
1731
1732	rport->stats.logos++;
1733	bfa_fcxp_discard(rport->fcxp);
1734	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1735}
1736
1737/**
1738 *    Send ACC for a LOGO received.
1739 */
1740static void
1741bfa_fcs_rport_send_logo_acc(void *rport_cbarg)
1742{
1743	struct bfa_fcs_rport_s *rport = rport_cbarg;
1744	struct bfa_fcs_port_s *port;
1745	struct fchs_s          fchs;
1746	struct bfa_fcxp_s *fcxp;
1747	u16        len;
1748
1749	bfa_trc(rport->fcs, rport->pid);
1750
1751	port = rport->port;
1752
1753	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
1754	if (!fcxp)
1755		return;
1756
1757	rport->stats.logo_rcvd++;
1758	len = fc_logo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
1759				bfa_fcs_port_get_fcid(port), rport->reply_oxid);
1760
1761	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1762		      FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
1763}
1764
1765/**
1766 *     This routine will be called by bfa_timer on timer timeouts.
1767 *
1768 * 	param[in] 	rport 			- pointer to bfa_fcs_port_ns_t.
1769 * 	param[out]	rport_status 	- pointer to return vport status in
1770 *
1771 * 	return
1772 * 		void
1773 *
1774*  	Special Considerations:
1775 *
1776 * 	note
1777 */
1778static void
1779bfa_fcs_rport_timeout(void *arg)
1780{
1781	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)arg;
1782
1783	rport->stats.plogi_timeouts++;
1784	bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
1785}
1786
1787static void
1788bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
1789			struct fchs_s *rx_fchs, u16 len)
1790{
1791	struct bfa_fcxp_s *fcxp;
1792	struct fchs_s          fchs;
1793	struct bfa_fcs_port_s *port = rport->port;
1794	struct fc_prli_s      *prli;
1795
1796	bfa_trc(port->fcs, rx_fchs->s_id);
1797	bfa_trc(port->fcs, rx_fchs->d_id);
1798
1799	rport->stats.prli_rcvd++;
1800
1801	if (BFA_FCS_VPORT_IS_TARGET_MODE(port)) {
1802		/*
1803		 * Target Mode : Let the fcptm handle it
1804		 */
1805		bfa_fcs_tin_rx_prli(rport->tin, rx_fchs, len);
1806		return;
1807	}
1808
1809	/*
1810	 * We are either in Initiator or ipfc Mode
1811	 */
1812	prli = (struct fc_prli_s *) (rx_fchs + 1);
1813
1814	if (prli->parampage.servparams.initiator) {
1815		bfa_trc(rport->fcs, prli->parampage.type);
1816		rport->scsi_function = BFA_RPORT_INITIATOR;
1817		bfa_fcs_itnim_is_initiator(rport->itnim);
1818	} else {
1819		/*
1820		 * @todo: PRLI from a target ?
1821		 */
1822		bfa_trc(port->fcs, rx_fchs->s_id);
1823		rport->scsi_function = BFA_RPORT_TARGET;
1824	}
1825
1826	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
1827	if (!fcxp)
1828		return;
1829
1830	len = fc_prli_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
1831				bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
1832				port->port_cfg.roles);
1833
1834	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1835		      FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
1836}
1837
1838static void
1839bfa_fcs_rport_process_rpsc(struct bfa_fcs_rport_s *rport,
1840			struct fchs_s *rx_fchs, u16 len)
1841{
1842	struct bfa_fcxp_s *fcxp;
1843	struct fchs_s          fchs;
1844	struct bfa_fcs_port_s *port = rport->port;
1845	struct fc_rpsc_speed_info_s speeds;
1846	struct bfa_pport_attr_s pport_attr;
1847
1848	bfa_trc(port->fcs, rx_fchs->s_id);
1849	bfa_trc(port->fcs, rx_fchs->d_id);
1850
1851	rport->stats.rpsc_rcvd++;
1852	speeds.port_speed_cap =
1853		RPSC_SPEED_CAP_1G | RPSC_SPEED_CAP_2G | RPSC_SPEED_CAP_4G |
1854		RPSC_SPEED_CAP_8G;
1855
1856	/*
1857	 * get curent speed from pport attributes from BFA
1858	 */
1859	bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
1860
1861	speeds.port_op_speed = fc_bfa_speed_to_rpsc_operspeed(pport_attr.speed);
1862
1863	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
1864	if (!fcxp)
1865		return;
1866
1867	len = fc_rpsc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
1868				bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
1869				&speeds);
1870
1871	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1872		      FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
1873}
1874
1875static void
1876bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
1877			struct fchs_s *rx_fchs, u16 len)
1878{
1879	struct bfa_fcxp_s *fcxp;
1880	struct fchs_s          fchs;
1881	struct bfa_fcs_port_s *port = rport->port;
1882	struct fc_adisc_s      *adisc;
1883
1884	bfa_trc(port->fcs, rx_fchs->s_id);
1885	bfa_trc(port->fcs, rx_fchs->d_id);
1886
1887	rport->stats.adisc_rcvd++;
1888
1889	if (BFA_FCS_VPORT_IS_TARGET_MODE(port)) {
1890		/*
1891		 * @todo : Target Mode handling
1892		 */
1893		bfa_trc(port->fcs, rx_fchs->d_id);
1894		bfa_assert(0);
1895		return;
1896	}
1897
1898	adisc = (struct fc_adisc_s *) (rx_fchs + 1);
1899
1900	/*
1901	 * Accept if the itnim for this rport is online. Else reject the ADISC
1902	 */
1903	if (bfa_fcs_itnim_get_online_state(rport->itnim) == BFA_STATUS_OK) {
1904
1905		fcxp = bfa_fcs_fcxp_alloc(port->fcs);
1906		if (!fcxp)
1907			return;
1908
1909		len = fc_adisc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
1910					 rx_fchs->s_id,
1911					 bfa_fcs_port_get_fcid(port),
1912					 rx_fchs->ox_id, port->port_cfg.pwwn,
1913					 port->port_cfg.nwwn);
1914
1915		bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
1916			      BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
1917			      FC_MAX_PDUSZ, 0);
1918	} else {
1919		rport->stats.adisc_rejected++;
1920		bfa_fcs_rport_send_ls_rjt(rport, rx_fchs,
1921					  FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD,
1922					  FC_LS_RJT_EXP_LOGIN_REQUIRED);
1923	}
1924
1925}
1926
1927static void
1928bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport)
1929{
1930	struct bfa_fcs_port_s *port = rport->port;
1931	struct bfa_rport_info_s rport_info;
1932
1933	rport_info.pid = rport->pid;
1934	rport_info.local_pid = port->pid;
1935	rport_info.lp_tag = port->lp_tag;
1936	rport_info.vf_id = port->fabric->vf_id;
1937	rport_info.vf_en = port->fabric->is_vf;
1938	rport_info.fc_class = rport->fc_cos;
1939	rport_info.cisc = rport->cisc;
1940	rport_info.max_frmsz = rport->maxfrsize;
1941	bfa_rport_online(rport->bfa_rport, &rport_info);
1942}
1943
1944static void
1945bfa_fcs_rport_fc4_pause(struct bfa_fcs_rport_s *rport)
1946{
1947	if (bfa_fcs_port_is_initiator(rport->port))
1948		bfa_fcs_itnim_pause(rport->itnim);
1949
1950	if (bfa_fcs_port_is_target(rport->port))
1951		bfa_fcs_tin_pause(rport->tin);
1952}
1953
1954static void
1955bfa_fcs_rport_fc4_resume(struct bfa_fcs_rport_s *rport)
1956{
1957	if (bfa_fcs_port_is_initiator(rport->port))
1958		bfa_fcs_itnim_resume(rport->itnim);
1959
1960	if (bfa_fcs_port_is_target(rport->port))
1961		bfa_fcs_tin_resume(rport->tin);
1962}
1963
1964static struct bfa_fcs_rport_s *
1965bfa_fcs_rport_alloc(struct bfa_fcs_port_s *port, wwn_t pwwn, u32 rpid)
1966{
1967	struct bfa_fcs_s *fcs = port->fcs;
1968	struct bfa_fcs_rport_s *rport;
1969	struct bfad_rport_s *rport_drv;
1970
1971	/**
1972	 * allocate rport
1973	 */
1974	if (bfa_fcb_rport_alloc(fcs->bfad, &rport, &rport_drv)
1975	    != BFA_STATUS_OK) {
1976		bfa_trc(fcs, rpid);
1977		return NULL;
1978	}
1979
1980	/*
1981	 * Initialize r-port
1982	 */
1983	rport->port = port;
1984	rport->fcs = fcs;
1985	rport->rp_drv = rport_drv;
1986	rport->pid = rpid;
1987	rport->pwwn = pwwn;
1988
1989	/**
1990	 * allocate BFA rport
1991	 */
1992	rport->bfa_rport = bfa_rport_create(port->fcs->bfa, rport);
1993	if (!rport->bfa_rport) {
1994		bfa_trc(fcs, rpid);
1995		kfree(rport_drv);
1996		return NULL;
1997	}
1998
1999	/**
2000	 * allocate FC-4s
2001	 */
2002	bfa_assert(bfa_fcs_port_is_initiator(port) ^
2003		   bfa_fcs_port_is_target(port));
2004
2005	if (bfa_fcs_port_is_initiator(port)) {
2006		rport->itnim = bfa_fcs_itnim_create(rport);
2007		if (!rport->itnim) {
2008			bfa_trc(fcs, rpid);
2009			bfa_rport_delete(rport->bfa_rport);
2010			kfree(rport_drv);
2011			return NULL;
2012		}
2013	}
2014
2015	if (bfa_fcs_port_is_target(port)) {
2016		rport->tin = bfa_fcs_tin_create(rport);
2017		if (!rport->tin) {
2018			bfa_trc(fcs, rpid);
2019			bfa_rport_delete(rport->bfa_rport);
2020			kfree(rport_drv);
2021			return NULL;
2022		}
2023	}
2024
2025	bfa_fcs_port_add_rport(port, rport);
2026
2027	bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
2028
2029	/*
2030	 * Initialize the Rport Features(RPF) Sub Module
2031	 */
2032	if (!BFA_FCS_PID_IS_WKA(rport->pid))
2033		bfa_fcs_rpf_init(rport);
2034
2035	return rport;
2036}
2037
2038
2039static void
2040bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport)
2041{
2042	struct bfa_fcs_port_s *port = rport->port;
2043
2044	/**
2045	 * - delete FC-4s
2046	 * - delete BFA rport
2047	 * - remove from queue of rports
2048	 */
2049	if (bfa_fcs_port_is_initiator(port))
2050		bfa_fcs_itnim_delete(rport->itnim);
2051
2052	if (bfa_fcs_port_is_target(port))
2053		bfa_fcs_tin_delete(rport->tin);
2054
2055	bfa_rport_delete(rport->bfa_rport);
2056	bfa_fcs_port_del_rport(port, rport);
2057	kfree(rport->rp_drv);
2058}
2059
2060static void
2061bfa_fcs_rport_aen_post(struct bfa_fcs_rport_s *rport,
2062		       enum bfa_rport_aen_event event,
2063		       struct bfa_rport_aen_data_s *data)
2064{
2065	union bfa_aen_data_u aen_data;
2066	struct bfa_log_mod_s *logmod = rport->fcs->logm;
2067	wwn_t           lpwwn = bfa_fcs_port_get_pwwn(rport->port);
2068	wwn_t           rpwwn = rport->pwwn;
2069	char            lpwwn_ptr[BFA_STRING_32];
2070	char            rpwwn_ptr[BFA_STRING_32];
2071	char           *prio_str[] = { "unknown", "high", "medium", "low" };
2072
2073	wwn2str(lpwwn_ptr, lpwwn);
2074	wwn2str(rpwwn_ptr, rpwwn);
2075
2076	switch (event) {
2077	case BFA_RPORT_AEN_ONLINE:
2078	case BFA_RPORT_AEN_OFFLINE:
2079	case BFA_RPORT_AEN_DISCONNECT:
2080		bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, event),
2081			rpwwn_ptr, lpwwn_ptr);
2082		break;
2083	case BFA_RPORT_AEN_QOS_PRIO:
2084		aen_data.rport.priv.qos = data->priv.qos;
2085		bfa_log(logmod, BFA_AEN_RPORT_QOS_PRIO,
2086			prio_str[aen_data.rport.priv.qos.qos_priority],
2087			rpwwn_ptr, lpwwn_ptr);
2088		break;
2089	case BFA_RPORT_AEN_QOS_FLOWID:
2090		aen_data.rport.priv.qos = data->priv.qos;
2091		bfa_log(logmod, BFA_AEN_RPORT_QOS_FLOWID,
2092			aen_data.rport.priv.qos.qos_flow_id, rpwwn_ptr,
2093			lpwwn_ptr);
2094		break;
2095	default:
2096		break;
2097	}
2098
2099	aen_data.rport.vf_id = rport->port->fabric->vf_id;
2100	aen_data.rport.ppwwn =
2101		bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(rport->fcs));
2102	aen_data.rport.lpwwn = lpwwn;
2103	aen_data.rport.rpwwn = rpwwn;
2104}
2105
2106static void
2107bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport)
2108{
2109	struct bfa_fcs_port_s *port = rport->port;
2110
2111	rport->stats.onlines++;
2112
2113	if (bfa_fcs_port_is_initiator(port)) {
2114		bfa_fcs_itnim_rport_online(rport->itnim);
2115		if (!BFA_FCS_PID_IS_WKA(rport->pid))
2116			bfa_fcs_rpf_rport_online(rport);
2117	};
2118
2119	if (bfa_fcs_port_is_target(port))
2120		bfa_fcs_tin_rport_online(rport->tin);
2121
2122	/*
2123	 * Don't post events for well known addresses
2124	 */
2125	if (!BFA_FCS_PID_IS_WKA(rport->pid))
2126		bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_ONLINE, NULL);
2127}
2128
2129static void
2130bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport)
2131{
2132	struct bfa_fcs_port_s *port = rport->port;
2133
2134	rport->stats.offlines++;
2135
2136	/*
2137	 * Don't post events for well known addresses
2138	 */
2139	if (!BFA_FCS_PID_IS_WKA(rport->pid)) {
2140		if (bfa_fcs_port_is_online(rport->port) == BFA_TRUE) {
2141			bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_DISCONNECT,
2142					       NULL);
2143		} else {
2144			bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_OFFLINE,
2145					       NULL);
2146		}
2147	}
2148
2149	if (bfa_fcs_port_is_initiator(port)) {
2150		bfa_fcs_itnim_rport_offline(rport->itnim);
2151		if (!BFA_FCS_PID_IS_WKA(rport->pid))
2152			bfa_fcs_rpf_rport_offline(rport);
2153	}
2154
2155	if (bfa_fcs_port_is_target(port))
2156		bfa_fcs_tin_rport_offline(rport->tin);
2157}
2158
2159/**
2160 * Update rport parameters from PLOGI or PLOGI accept.
2161 */
2162static void
2163bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi)
2164{
2165	struct bfa_fcs_port_s *port = rport->port;
2166
2167	/**
2168	 * - port name
2169	 * - node name
2170	 */
2171	rport->pwwn = plogi->port_name;
2172	rport->nwwn = plogi->node_name;
2173
2174	/**
2175	 * - class of service
2176	 */
2177	rport->fc_cos = 0;
2178	if (plogi->class3.class_valid)
2179		rport->fc_cos = FC_CLASS_3;
2180
2181	if (plogi->class2.class_valid)
2182		rport->fc_cos |= FC_CLASS_2;
2183
2184	/**
2185	 * - CISC
2186	 * - MAX receive frame size
2187	 */
2188	rport->cisc = plogi->csp.cisc;
2189	rport->maxfrsize = bfa_os_ntohs(plogi->class3.rxsz);
2190
2191	bfa_trc(port->fcs, bfa_os_ntohs(plogi->csp.bbcred));
2192	bfa_trc(port->fcs, port->fabric->bb_credit);
2193	/**
2194	 * Direct Attach P2P mode :
2195	 * This is to handle a bug (233476) in IBM targets in Direct Attach
2196	 * Mode. Basically, in FLOGI Accept the target would have erroneously
2197	 * set the BB Credit to the value used in the FLOGI sent by the HBA.
2198	 * It uses the correct value (its own BB credit) in PLOGI.
2199	 */
2200	if ((!bfa_fcs_fabric_is_switched(port->fabric))
2201	    && (bfa_os_ntohs(plogi->csp.bbcred) < port->fabric->bb_credit)) {
2202
2203		bfa_trc(port->fcs, bfa_os_ntohs(plogi->csp.bbcred));
2204		bfa_trc(port->fcs, port->fabric->bb_credit);
2205
2206		port->fabric->bb_credit = bfa_os_ntohs(plogi->csp.bbcred);
2207		bfa_fcport_set_tx_bbcredit(port->fcs->bfa,
2208					  port->fabric->bb_credit);
2209	}
2210
2211}
2212
2213/**
2214 *   Called to handle LOGO received from an existing remote port.
2215 */
2216static void
2217bfa_fcs_rport_process_logo(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs)
2218{
2219	rport->reply_oxid = fchs->ox_id;
2220	bfa_trc(rport->fcs, rport->reply_oxid);
2221
2222	rport->prlo = BFA_FALSE;
2223	rport->stats.logo_rcvd++;
2224	bfa_sm_send_event(rport, RPSM_EVENT_LOGO_RCVD);
2225}
2226
2227
2228
2229/**
2230 *  fcs_rport_public FCS rport public interfaces
2231 */
2232
2233/**
2234 * 	Called by bport/vport to create a remote port instance for a discovered
2235 * 	remote device.
2236 *
2237 * @param[in] port	- base port or vport
2238 * @param[in] rpid	- remote port ID
2239 *
2240 * @return None
2241 */
2242struct bfa_fcs_rport_s *
2243bfa_fcs_rport_create(struct bfa_fcs_port_s *port, u32 rpid)
2244{
2245	struct bfa_fcs_rport_s *rport;
2246
2247	bfa_trc(port->fcs, rpid);
2248	rport = bfa_fcs_rport_alloc(port, WWN_NULL, rpid);
2249	if (!rport)
2250		return NULL;
2251
2252	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
2253	return rport;
2254}
2255
2256/**
2257 * Called to create a rport for which only the wwn is known.
2258 *
2259 * @param[in] port	- base port
2260 * @param[in] rpwwn	- remote port wwn
2261 *
2262 * @return None
2263 */
2264struct bfa_fcs_rport_s *
2265bfa_fcs_rport_create_by_wwn(struct bfa_fcs_port_s *port, wwn_t rpwwn)
2266{
2267	struct bfa_fcs_rport_s *rport;
2268
2269	bfa_trc(port->fcs, rpwwn);
2270	rport = bfa_fcs_rport_alloc(port, rpwwn, 0);
2271	if (!rport)
2272		return NULL;
2273
2274	bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_DISC);
2275	return rport;
2276}
2277
2278/**
2279 * Called by bport in private loop topology to indicate that a
2280 * rport has been discovered and plogi has been completed.
2281 *
2282 * @param[in] port	- base port or vport
2283 * @param[in] rpid	- remote port ID
2284 */
2285void
2286bfa_fcs_rport_start(struct bfa_fcs_port_s *port, struct fchs_s *fchs,
2287			struct fc_logi_s *plogi)
2288{
2289	struct bfa_fcs_rport_s *rport;
2290
2291	rport = bfa_fcs_rport_alloc(port, WWN_NULL, fchs->s_id);
2292	if (!rport)
2293		return;
2294
2295	bfa_fcs_rport_update(rport, plogi);
2296
2297	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_COMP);
2298}
2299
2300/**
2301 *   Called by bport/vport to handle PLOGI received from a new remote port.
2302 *   If an existing rport does a plogi, it will be handled separately.
2303 */
2304void
2305bfa_fcs_rport_plogi_create(struct bfa_fcs_port_s *port, struct fchs_s *fchs,
2306			   struct fc_logi_s *plogi)
2307{
2308	struct bfa_fcs_rport_s *rport;
2309
2310	rport = bfa_fcs_rport_alloc(port, plogi->port_name, fchs->s_id);
2311	if (!rport)
2312		return;
2313
2314	bfa_fcs_rport_update(rport, plogi);
2315
2316	rport->reply_oxid = fchs->ox_id;
2317	bfa_trc(rport->fcs, rport->reply_oxid);
2318
2319	rport->stats.plogi_rcvd++;
2320	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
2321}
2322
2323static int
2324wwn_compare(wwn_t wwn1, wwn_t wwn2)
2325{
2326	u8        *b1 = (u8 *) &wwn1;
2327	u8        *b2 = (u8 *) &wwn2;
2328	int             i;
2329
2330	for (i = 0; i < sizeof(wwn_t); i++) {
2331		if (b1[i] < b2[i])
2332			return -1;
2333		if (b1[i] > b2[i])
2334			return 1;
2335	}
2336	return 0;
2337}
2338
2339/**
2340 *   Called by bport/vport to handle PLOGI received from an existing
2341 * 	 remote port.
2342 */
2343void
2344bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
2345		    struct fc_logi_s *plogi)
2346{
2347	/**
2348	 * @todo Handle P2P and initiator-initiator.
2349	 */
2350
2351	bfa_fcs_rport_update(rport, plogi);
2352
2353	rport->reply_oxid = rx_fchs->ox_id;
2354	bfa_trc(rport->fcs, rport->reply_oxid);
2355
2356	/**
2357	 * In Switched fabric topology,
2358	 * PLOGI to each other. If our pwwn is smaller, ignore it,
2359	 * if it is not a well known address.
2360	 * If the link topology is N2N,
2361	 * this Plogi should be accepted.
2362	 */
2363	if ((wwn_compare(rport->port->port_cfg.pwwn, rport->pwwn) == -1)
2364	    && (bfa_fcs_fabric_is_switched(rport->port->fabric))
2365	    && (!BFA_FCS_PID_IS_WKA(rport->pid))) {
2366		bfa_trc(rport->fcs, rport->pid);
2367		return;
2368	}
2369
2370	rport->stats.plogi_rcvd++;
2371	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
2372}
2373
2374/**
2375 * Called by bport/vport to delete a remote port instance.
2376 *
2377* Rport delete is called under the following conditions:
2378 * 		- vport is deleted
2379 * 		- vf is deleted
2380 * 		- explicit request from OS to delete rport (vmware)
2381 */
2382void
2383bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport)
2384{
2385	bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
2386}
2387
2388/**
2389 * Called by bport/vport to  when a target goes offline.
2390 *
2391 */
2392void
2393bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport)
2394{
2395	bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
2396}
2397
2398/**
2399 * Called by bport in n2n when a target (attached port) becomes online.
2400 *
2401 */
2402void
2403bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport)
2404{
2405	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
2406}
2407
2408/**
2409 *   Called by bport/vport to notify SCN for the remote port
2410 */
2411void
2412bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport)
2413{
2414
2415	rport->stats.rscns++;
2416	bfa_sm_send_event(rport, RPSM_EVENT_SCN);
2417}
2418
2419/**
2420 *   Called by  fcpim to notify that the ITN cleanup is done.
2421 */
2422void
2423bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport)
2424{
2425	bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE);
2426}
2427
2428/**
2429 *   Called by fcptm to notify that the ITN cleanup is done.
2430 */
2431void
2432bfa_fcs_rport_tin_ack(struct bfa_fcs_rport_s *rport)
2433{
2434	bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE);
2435}
2436
2437/**
2438 *     This routine BFA callback for bfa_rport_online() call.
2439 *
2440 * 	param[in] 	cb_arg	-  rport struct.
2441 *
2442 * 	return
2443 * 		void
2444 *
2445* 	Special Considerations:
2446 *
2447 * 	note
2448 */
2449void
2450bfa_cb_rport_online(void *cbarg)
2451{
2452
2453	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
2454
2455	bfa_trc(rport->fcs, rport->pwwn);
2456	bfa_sm_send_event(rport, RPSM_EVENT_HCB_ONLINE);
2457}
2458
2459/**
2460 *     This routine BFA callback for bfa_rport_offline() call.
2461 *
2462 * 	param[in] 	rport 	-
2463 *
2464 * 	return
2465 * 		void
2466 *
2467 * 	Special Considerations:
2468 *
2469 * 	note
2470 */
2471void
2472bfa_cb_rport_offline(void *cbarg)
2473{
2474	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
2475
2476	bfa_trc(rport->fcs, rport->pwwn);
2477	bfa_sm_send_event(rport, RPSM_EVENT_HCB_OFFLINE);
2478}
2479
2480/**
2481 * This routine is a static BFA callback when there is a QoS flow_id
2482 * change notification
2483 *
2484 * @param[in] 	rport 	-
2485 *
2486 * @return  	void
2487 *
2488 * Special Considerations:
2489 *
2490 * @note
2491 */
2492void
2493bfa_cb_rport_qos_scn_flowid(void *cbarg,
2494			    struct bfa_rport_qos_attr_s old_qos_attr,
2495			    struct bfa_rport_qos_attr_s new_qos_attr)
2496{
2497	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
2498	struct bfa_rport_aen_data_s aen_data;
2499
2500	bfa_trc(rport->fcs, rport->pwwn);
2501	aen_data.priv.qos = new_qos_attr;
2502	bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_FLOWID, &aen_data);
2503}
2504
2505/**
2506 * This routine is a static BFA callback when there is a QoS priority
2507 * change notification
2508 *
2509 * @param[in] 	rport 	-
2510 *
2511 * @return 	void
2512 *
2513 * Special Considerations:
2514 *
2515 * @note
2516 */
2517void
2518bfa_cb_rport_qos_scn_prio(void *cbarg, struct bfa_rport_qos_attr_s old_qos_attr,
2519			  struct bfa_rport_qos_attr_s new_qos_attr)
2520{
2521	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
2522	struct bfa_rport_aen_data_s aen_data;
2523
2524	bfa_trc(rport->fcs, rport->pwwn);
2525	aen_data.priv.qos = new_qos_attr;
2526	bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_PRIO, &aen_data);
2527}
2528
2529/**
2530 * 		Called to process any unsolicted frames from this remote port
2531 */
2532void
2533bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport)
2534{
2535	bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
2536}
2537
2538/**
2539 * 		Called to process any unsolicted frames from this remote port
2540 */
2541void
2542bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs,
2543			u16 len)
2544{
2545	struct bfa_fcs_port_s *port = rport->port;
2546	struct fc_els_cmd_s   *els_cmd;
2547
2548	bfa_trc(rport->fcs, fchs->s_id);
2549	bfa_trc(rport->fcs, fchs->d_id);
2550	bfa_trc(rport->fcs, fchs->type);
2551
2552	if (fchs->type != FC_TYPE_ELS)
2553		return;
2554
2555	els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
2556
2557	bfa_trc(rport->fcs, els_cmd->els_code);
2558
2559	switch (els_cmd->els_code) {
2560	case FC_ELS_LOGO:
2561		bfa_fcs_rport_process_logo(rport, fchs);
2562		break;
2563
2564	case FC_ELS_ADISC:
2565		bfa_fcs_rport_process_adisc(rport, fchs, len);
2566		break;
2567
2568	case FC_ELS_PRLO:
2569		if (bfa_fcs_port_is_initiator(port))
2570			bfa_fcs_fcpim_uf_recv(rport->itnim, fchs, len);
2571
2572		if (bfa_fcs_port_is_target(port))
2573			bfa_fcs_fcptm_uf_recv(rport->tin, fchs, len);
2574		break;
2575
2576	case FC_ELS_PRLI:
2577		bfa_fcs_rport_process_prli(rport, fchs, len);
2578		break;
2579
2580	case FC_ELS_RPSC:
2581		bfa_fcs_rport_process_rpsc(rport, fchs, len);
2582		break;
2583
2584	default:
2585		bfa_fcs_rport_send_ls_rjt(rport, fchs,
2586					  FC_LS_RJT_RSN_CMD_NOT_SUPP,
2587					  FC_LS_RJT_EXP_NO_ADDL_INFO);
2588		break;
2589	}
2590}
2591
2592/* Send best case acc to prlo */
2593static void
2594bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport)
2595{
2596	struct bfa_fcs_port_s *port = rport->port;
2597	struct fchs_s fchs;
2598	struct bfa_fcxp_s *fcxp;
2599	int len;
2600
2601	bfa_trc(rport->fcs, rport->pid);
2602
2603	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
2604	if (!fcxp)
2605		return;
2606
2607	len = fc_prlo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2608			rport->pid, bfa_fcs_port_get_fcid(port),
2609			rport->reply_oxid, 0);
2610
2611	bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id,
2612			port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs,
2613			NULL, NULL, FC_MAX_PDUSZ, 0);
2614}
2615
2616/*
2617 * Send a LS reject
2618 */
2619static void
2620bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
2621			  u8 reason_code, u8 reason_code_expl)
2622{
2623	struct bfa_fcs_port_s *port = rport->port;
2624	struct fchs_s          fchs;
2625	struct bfa_fcxp_s *fcxp;
2626	int             len;
2627
2628	bfa_trc(rport->fcs, rx_fchs->s_id);
2629
2630	fcxp = bfa_fcs_fcxp_alloc(rport->fcs);
2631	if (!fcxp)
2632		return;
2633
2634	len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
2635			      bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
2636			      reason_code, reason_code_expl);
2637
2638	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2639		      FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
2640}
2641
2642/**
2643 * Return state of rport.
2644 */
2645int
2646bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport)
2647{
2648	return bfa_sm_to_state(rport_sm_table, rport->sm);
2649}
2650
2651/**
2652 * 		 Called by the Driver to set rport delete/ageout timeout
2653 *
2654 * 	param[in]		rport timeout value in seconds.
2655 *
2656 * 	return None
2657 */
2658void
2659bfa_fcs_rport_set_del_timeout(u8 rport_tmo)
2660{
2661	/*
2662	 * convert to Millisecs
2663	 */
2664	if (rport_tmo > 0)
2665		bfa_fcs_rport_del_timeout = rport_tmo * 1000;
2666}
2667
2668void
2669bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, uint16_t ox_id)
2670{
2671	bfa_trc(rport->fcs, rport->pid);
2672
2673	rport->prlo = BFA_TRUE;
2674	rport->reply_oxid = ox_id;
2675	bfa_sm_send_event(rport, RPSM_EVENT_PRLO_RCVD);
2676}
2677