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