[go: nahoru, domu]

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