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