xref: /linux/drivers/scsi/bfa/bfa_fcs_lport.c (revision a234ca0faa65dcd5cc473915bd925130ebb7b74b)
1 /*
2  * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
3  * All rights reserved
4  * www.brocade.com
5  *
6  * Linux driver for Brocade Fibre Channel Host Bus Adapter.
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License (GPL) Version 2 as
10  * published by the Free Software Foundation
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  */
17 
18 /**
19  *  bfa_fcs_port.c BFA FCS port
20  */
21 
22 #include <fcs/bfa_fcs.h>
23 #include <fcs/bfa_fcs_lport.h>
24 #include <fcs/bfa_fcs_rport.h>
25 #include <fcb/bfa_fcb_port.h>
26 #include <bfa_svc.h>
27 #include <log/bfa_log_fcs.h>
28 #include "fcs.h"
29 #include "fcs_lport.h"
30 #include "fcs_vport.h"
31 #include "fcs_rport.h"
32 #include "fcs_fcxp.h"
33 #include "fcs_trcmod.h"
34 #include "lport_priv.h"
35 #include <aen/bfa_aen_lport.h>
36 
37 BFA_TRC_FILE(FCS, PORT);
38 
39 /**
40  * Forward declarations
41  */
42 
43 static void     bfa_fcs_port_aen_post(struct bfa_fcs_port_s *port,
44 				      enum bfa_lport_aen_event event);
45 static void     bfa_fcs_port_send_ls_rjt(struct bfa_fcs_port_s *port,
46 			struct fchs_s *rx_fchs, u8 reason_code,
47 			u8 reason_code_expl);
48 static void     bfa_fcs_port_plogi(struct bfa_fcs_port_s *port,
49 			struct fchs_s *rx_fchs,
50 			struct fc_logi_s *plogi);
51 static void     bfa_fcs_port_online_actions(struct bfa_fcs_port_s *port);
52 static void     bfa_fcs_port_offline_actions(struct bfa_fcs_port_s *port);
53 static void     bfa_fcs_port_unknown_init(struct bfa_fcs_port_s *port);
54 static void     bfa_fcs_port_unknown_online(struct bfa_fcs_port_s *port);
55 static void     bfa_fcs_port_unknown_offline(struct bfa_fcs_port_s *port);
56 static void     bfa_fcs_port_deleted(struct bfa_fcs_port_s *port);
57 static void     bfa_fcs_port_echo(struct bfa_fcs_port_s *port,
58 			struct fchs_s *rx_fchs,
59 			struct fc_echo_s *echo, u16 len);
60 static void     bfa_fcs_port_rnid(struct bfa_fcs_port_s *port,
61 			struct fchs_s *rx_fchs,
62 			struct fc_rnid_cmd_s *rnid, u16 len);
63 static void     bfa_fs_port_get_gen_topo_data(struct bfa_fcs_port_s *port,
64 			struct fc_rnid_general_topology_data_s *gen_topo_data);
65 
66 static struct {
67 	void            (*init) (struct bfa_fcs_port_s *port);
68 	void            (*online) (struct bfa_fcs_port_s *port);
69 	void            (*offline) (struct bfa_fcs_port_s *port);
70 } __port_action[] = {
71 	{
72 	bfa_fcs_port_unknown_init, bfa_fcs_port_unknown_online,
73 			bfa_fcs_port_unknown_offline}, {
74 	bfa_fcs_port_fab_init, bfa_fcs_port_fab_online,
75 			bfa_fcs_port_fab_offline}, {
76 	bfa_fcs_port_loop_init, bfa_fcs_port_loop_online,
77 			bfa_fcs_port_loop_offline}, {
78 bfa_fcs_port_n2n_init, bfa_fcs_port_n2n_online,
79 			bfa_fcs_port_n2n_offline},};
80 
81 /**
82  *  fcs_port_sm FCS logical port state machine
83  */
84 
85 enum bfa_fcs_port_event {
86 	BFA_FCS_PORT_SM_CREATE = 1,
87 	BFA_FCS_PORT_SM_ONLINE = 2,
88 	BFA_FCS_PORT_SM_OFFLINE = 3,
89 	BFA_FCS_PORT_SM_DELETE = 4,
90 	BFA_FCS_PORT_SM_DELRPORT = 5,
91 };
92 
93 static void     bfa_fcs_port_sm_uninit(struct bfa_fcs_port_s *port,
94 				       enum bfa_fcs_port_event event);
95 static void     bfa_fcs_port_sm_init(struct bfa_fcs_port_s *port,
96 				     enum bfa_fcs_port_event event);
97 static void     bfa_fcs_port_sm_online(struct bfa_fcs_port_s *port,
98 				       enum bfa_fcs_port_event event);
99 static void     bfa_fcs_port_sm_offline(struct bfa_fcs_port_s *port,
100 					enum bfa_fcs_port_event event);
101 static void     bfa_fcs_port_sm_deleting(struct bfa_fcs_port_s *port,
102 					 enum bfa_fcs_port_event event);
103 
104 static void
105 bfa_fcs_port_sm_uninit(struct bfa_fcs_port_s *port,
106 			enum bfa_fcs_port_event event)
107 {
108 	bfa_trc(port->fcs, port->port_cfg.pwwn);
109 	bfa_trc(port->fcs, event);
110 
111 	switch (event) {
112 	case BFA_FCS_PORT_SM_CREATE:
113 		bfa_sm_set_state(port, bfa_fcs_port_sm_init);
114 		break;
115 
116 	default:
117 		bfa_sm_fault(port->fcs, event);
118 	}
119 }
120 
121 static void
122 bfa_fcs_port_sm_init(struct bfa_fcs_port_s *port, enum bfa_fcs_port_event event)
123 {
124 	bfa_trc(port->fcs, port->port_cfg.pwwn);
125 	bfa_trc(port->fcs, event);
126 
127 	switch (event) {
128 	case BFA_FCS_PORT_SM_ONLINE:
129 		bfa_sm_set_state(port, bfa_fcs_port_sm_online);
130 		bfa_fcs_port_online_actions(port);
131 		break;
132 
133 	case BFA_FCS_PORT_SM_DELETE:
134 		bfa_sm_set_state(port, bfa_fcs_port_sm_uninit);
135 		bfa_fcs_port_deleted(port);
136 		break;
137 
138 	case BFA_FCS_PORT_SM_OFFLINE:
139 		break;
140 
141 	default:
142 		bfa_sm_fault(port->fcs, event);
143 	}
144 }
145 
146 static void
147 bfa_fcs_port_sm_online(struct bfa_fcs_port_s *port,
148 			enum bfa_fcs_port_event event)
149 {
150 	struct bfa_fcs_rport_s *rport;
151 	struct list_head *qe, *qen;
152 
153 	bfa_trc(port->fcs, port->port_cfg.pwwn);
154 	bfa_trc(port->fcs, event);
155 
156 	switch (event) {
157 	case BFA_FCS_PORT_SM_OFFLINE:
158 		bfa_sm_set_state(port, bfa_fcs_port_sm_offline);
159 		bfa_fcs_port_offline_actions(port);
160 		break;
161 
162 	case BFA_FCS_PORT_SM_DELETE:
163 
164 		__port_action[port->fabric->fab_type].offline(port);
165 
166 		if (port->num_rports == 0) {
167 			bfa_sm_set_state(port, bfa_fcs_port_sm_uninit);
168 			bfa_fcs_port_deleted(port);
169 		} else {
170 			bfa_sm_set_state(port, bfa_fcs_port_sm_deleting);
171 			list_for_each_safe(qe, qen, &port->rport_q) {
172 				rport = (struct bfa_fcs_rport_s *)qe;
173 				bfa_fcs_rport_delete(rport);
174 			}
175 		}
176 		break;
177 
178 	case BFA_FCS_PORT_SM_DELRPORT:
179 		break;
180 
181 	default:
182 		bfa_sm_fault(port->fcs, event);
183 	}
184 }
185 
186 static void
187 bfa_fcs_port_sm_offline(struct bfa_fcs_port_s *port,
188 			enum bfa_fcs_port_event event)
189 {
190 	struct bfa_fcs_rport_s *rport;
191 	struct list_head *qe, *qen;
192 
193 	bfa_trc(port->fcs, port->port_cfg.pwwn);
194 	bfa_trc(port->fcs, event);
195 
196 	switch (event) {
197 	case BFA_FCS_PORT_SM_ONLINE:
198 		bfa_sm_set_state(port, bfa_fcs_port_sm_online);
199 		bfa_fcs_port_online_actions(port);
200 		break;
201 
202 	case BFA_FCS_PORT_SM_DELETE:
203 		if (port->num_rports == 0) {
204 			bfa_sm_set_state(port, bfa_fcs_port_sm_uninit);
205 			bfa_fcs_port_deleted(port);
206 		} else {
207 			bfa_sm_set_state(port, bfa_fcs_port_sm_deleting);
208 			list_for_each_safe(qe, qen, &port->rport_q) {
209 				rport = (struct bfa_fcs_rport_s *)qe;
210 				bfa_fcs_rport_delete(rport);
211 			}
212 		}
213 		break;
214 
215 	case BFA_FCS_PORT_SM_DELRPORT:
216 	case BFA_FCS_PORT_SM_OFFLINE:
217 		break;
218 
219 	default:
220 		bfa_sm_fault(port->fcs, event);
221 	}
222 }
223 
224 static void
225 bfa_fcs_port_sm_deleting(struct bfa_fcs_port_s *port,
226 			 enum bfa_fcs_port_event event)
227 {
228 	bfa_trc(port->fcs, port->port_cfg.pwwn);
229 	bfa_trc(port->fcs, event);
230 
231 	switch (event) {
232 	case BFA_FCS_PORT_SM_DELRPORT:
233 		if (port->num_rports == 0) {
234 			bfa_sm_set_state(port, bfa_fcs_port_sm_uninit);
235 			bfa_fcs_port_deleted(port);
236 		}
237 		break;
238 
239 	default:
240 		bfa_sm_fault(port->fcs, event);
241 	}
242 }
243 
244 
245 
246 /**
247  *  fcs_port_pvt
248  */
249 
250 /**
251  * Send AEN notification
252  */
253 static void
254 bfa_fcs_port_aen_post(struct bfa_fcs_port_s *port,
255 		      enum bfa_lport_aen_event event)
256 {
257 	union bfa_aen_data_u aen_data;
258 	struct bfa_log_mod_s *logmod = port->fcs->logm;
259 	enum bfa_port_role role = port->port_cfg.roles;
260 	wwn_t           lpwwn = bfa_fcs_port_get_pwwn(port);
261 	char            lpwwn_ptr[BFA_STRING_32];
262 	char           *role_str[BFA_PORT_ROLE_FCP_MAX / 2 + 1] =
263 		{ "Initiator", "Target", "IPFC" };
264 
265 	wwn2str(lpwwn_ptr, lpwwn);
266 
267 	bfa_assert(role <= BFA_PORT_ROLE_FCP_MAX);
268 
269 	bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, event), lpwwn_ptr,
270 		role_str[role/2]);
271 
272 	aen_data.lport.vf_id = port->fabric->vf_id;
273 	aen_data.lport.roles = role;
274 	aen_data.lport.ppwwn =
275 		bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(port->fcs));
276 	aen_data.lport.lpwwn = lpwwn;
277 }
278 
279 /*
280  * Send a LS reject
281  */
282 static void
283 bfa_fcs_port_send_ls_rjt(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
284 			 u8 reason_code, u8 reason_code_expl)
285 {
286 	struct fchs_s          fchs;
287 	struct bfa_fcxp_s *fcxp;
288 	struct bfa_rport_s *bfa_rport = NULL;
289 	int             len;
290 
291 	bfa_trc(port->fcs, rx_fchs->s_id);
292 
293 	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
294 	if (!fcxp)
295 		return;
296 
297 	len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
298 			      bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
299 			      reason_code, reason_code_expl);
300 
301 	bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
302 		      BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
303 		      FC_MAX_PDUSZ, 0);
304 }
305 
306 /**
307  * Process incoming plogi from a remote port.
308  */
309 static void
310 bfa_fcs_port_plogi(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
311 			struct fc_logi_s *plogi)
312 {
313 	struct bfa_fcs_rport_s *rport;
314 
315 	bfa_trc(port->fcs, rx_fchs->d_id);
316 	bfa_trc(port->fcs, rx_fchs->s_id);
317 
318 	/*
319 	 * If min cfg mode is enabled, drop any incoming PLOGIs
320 	 */
321 	if (__fcs_min_cfg(port->fcs)) {
322 		bfa_trc(port->fcs, rx_fchs->s_id);
323 		return;
324 	}
325 
326 	if (fc_plogi_parse(rx_fchs) != FC_PARSE_OK) {
327 		bfa_trc(port->fcs, rx_fchs->s_id);
328 		/*
329 		 * send a LS reject
330 		 */
331 		bfa_fcs_port_send_ls_rjt(port, rx_fchs,
332 					 FC_LS_RJT_RSN_PROTOCOL_ERROR,
333 					 FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS);
334 		return;
335 	}
336 
337 	/**
338 * Direct Attach P2P mode : verify address assigned by the r-port.
339 	 */
340 	if ((!bfa_fcs_fabric_is_switched(port->fabric))
341 	    &&
342 	    (memcmp
343 	     ((void *)&bfa_fcs_port_get_pwwn(port), (void *)&plogi->port_name,
344 	      sizeof(wwn_t)) < 0)) {
345 		if (BFA_FCS_PID_IS_WKA(rx_fchs->d_id)) {
346 			/*
347 			 * Address assigned to us cannot be a WKA
348 			 */
349 			bfa_fcs_port_send_ls_rjt(port, rx_fchs,
350 					FC_LS_RJT_RSN_PROTOCOL_ERROR,
351 					FC_LS_RJT_EXP_INVALID_NPORT_ID);
352 			return;
353 		}
354 		port->pid = rx_fchs->d_id;
355 	}
356 
357 	/**
358 	 * First, check if we know the device by pwwn.
359 	 */
360 	rport = bfa_fcs_port_get_rport_by_pwwn(port, plogi->port_name);
361 	if (rport) {
362 		/**
363 		 * Direct Attach P2P mode: handle address assigned by the rport.
364 		 */
365 		if ((!bfa_fcs_fabric_is_switched(port->fabric))
366 		    &&
367 		    (memcmp
368 		     ((void *)&bfa_fcs_port_get_pwwn(port),
369 		      (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
370 			port->pid = rx_fchs->d_id;
371 			rport->pid = rx_fchs->s_id;
372 		}
373 		bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
374 		return;
375 	}
376 
377 	/**
378 	 * Next, lookup rport by PID.
379 	 */
380 	rport = bfa_fcs_port_get_rport_by_pid(port, rx_fchs->s_id);
381 	if (!rport) {
382 		/**
383 		 * Inbound PLOGI from a new device.
384 		 */
385 		bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
386 		return;
387 	}
388 
389 	/**
390 	 * Rport is known only by PID.
391 	 */
392 	if (rport->pwwn) {
393 		/**
394 		 * This is a different device with the same pid. Old device
395 		 * disappeared. Send implicit LOGO to old device.
396 		 */
397 		bfa_assert(rport->pwwn != plogi->port_name);
398 		bfa_fcs_rport_logo_imp(rport);
399 
400 		/**
401 		 * Inbound PLOGI from a new device (with old PID).
402 		 */
403 		bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
404 		return;
405 	}
406 
407 	/**
408 	 * PLOGI crossing each other.
409 	 */
410 	bfa_assert(rport->pwwn == WWN_NULL);
411 	bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
412 }
413 
414 /*
415  * Process incoming ECHO.
416  * Since it does not require a login, it is processed here.
417  */
418 static void
419 bfa_fcs_port_echo(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
420 			struct fc_echo_s *echo, u16 rx_len)
421 {
422 	struct fchs_s          fchs;
423 	struct bfa_fcxp_s *fcxp;
424 	struct bfa_rport_s *bfa_rport = NULL;
425 	int             len, pyld_len;
426 
427 	bfa_trc(port->fcs, rx_fchs->s_id);
428 	bfa_trc(port->fcs, rx_fchs->d_id);
429 	bfa_trc(port->fcs, rx_len);
430 
431 	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
432 	if (!fcxp)
433 		return;
434 
435 	len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
436 			      bfa_fcs_port_get_fcid(port), rx_fchs->ox_id);
437 
438 	/*
439 	 * Copy the payload (if any) from the echo frame
440 	 */
441 	pyld_len = rx_len - sizeof(struct fchs_s);
442 	bfa_trc(port->fcs, pyld_len);
443 
444 	if (pyld_len > len)
445 		memcpy(((u8 *) bfa_fcxp_get_reqbuf(fcxp)) +
446 		       sizeof(struct fc_echo_s), (echo + 1),
447 		       (pyld_len - sizeof(struct fc_echo_s)));
448 
449 	bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
450 		      BFA_FALSE, FC_CLASS_3, pyld_len, &fchs, NULL, NULL,
451 		      FC_MAX_PDUSZ, 0);
452 }
453 
454 /*
455  * Process incoming RNID.
456  * Since it does not require a login, it is processed here.
457  */
458 static void
459 bfa_fcs_port_rnid(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
460 			struct fc_rnid_cmd_s *rnid, u16 rx_len)
461 {
462 	struct fc_rnid_common_id_data_s common_id_data;
463 	struct fc_rnid_general_topology_data_s gen_topo_data;
464 	struct fchs_s          fchs;
465 	struct bfa_fcxp_s *fcxp;
466 	struct bfa_rport_s *bfa_rport = NULL;
467 	u16        len;
468 	u32        data_format;
469 
470 	bfa_trc(port->fcs, rx_fchs->s_id);
471 	bfa_trc(port->fcs, rx_fchs->d_id);
472 	bfa_trc(port->fcs, rx_len);
473 
474 	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
475 	if (!fcxp)
476 		return;
477 
478 	/*
479 	 * Check Node Indentification Data Format
480 	 * We only support General Topology Discovery Format.
481 	 * For any other requested Data Formats, we return Common Node Id Data
482 	 * only, as per FC-LS.
483 	 */
484 	bfa_trc(port->fcs, rnid->node_id_data_format);
485 	if (rnid->node_id_data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) {
486 		data_format = RNID_NODEID_DATA_FORMAT_DISCOVERY;
487 		/*
488 		 * Get General topology data for this port
489 		 */
490 		bfa_fs_port_get_gen_topo_data(port, &gen_topo_data);
491 	} else {
492 		data_format = RNID_NODEID_DATA_FORMAT_COMMON;
493 	}
494 
495 	/*
496 	 * Copy the Node Id Info
497 	 */
498 	common_id_data.port_name = bfa_fcs_port_get_pwwn(port);
499 	common_id_data.node_name = bfa_fcs_port_get_nwwn(port);
500 
501 	len = fc_rnid_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
502 				bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
503 				data_format, &common_id_data, &gen_topo_data);
504 
505 	bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
506 		      BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
507 		      FC_MAX_PDUSZ, 0);
508 
509 	return;
510 }
511 
512 /*
513  *  Fill out General Topolpgy Discovery Data for RNID ELS.
514  */
515 static void
516 bfa_fs_port_get_gen_topo_data(struct bfa_fcs_port_s *port,
517 			struct fc_rnid_general_topology_data_s *gen_topo_data)
518 {
519 
520 	bfa_os_memset(gen_topo_data, 0,
521 		      sizeof(struct fc_rnid_general_topology_data_s));
522 
523 	gen_topo_data->asso_type = bfa_os_htonl(RNID_ASSOCIATED_TYPE_HOST);
524 	gen_topo_data->phy_port_num = 0;	/* @todo */
525 	gen_topo_data->num_attached_nodes = bfa_os_htonl(1);
526 }
527 
528 static void
529 bfa_fcs_port_online_actions(struct bfa_fcs_port_s *port)
530 {
531 	bfa_trc(port->fcs, port->fabric->oper_type);
532 
533 	__port_action[port->fabric->fab_type].init(port);
534 	__port_action[port->fabric->fab_type].online(port);
535 
536 	bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_ONLINE);
537 	bfa_fcb_port_online(port->fcs->bfad, port->port_cfg.roles,
538 			port->fabric->vf_drv, (port->vport == NULL) ?
539 			NULL : port->vport->vport_drv);
540 }
541 
542 static void
543 bfa_fcs_port_offline_actions(struct bfa_fcs_port_s *port)
544 {
545 	struct list_head *qe, *qen;
546 	struct bfa_fcs_rport_s *rport;
547 
548 	bfa_trc(port->fcs, port->fabric->oper_type);
549 
550 	__port_action[port->fabric->fab_type].offline(port);
551 
552 	if (bfa_fcs_fabric_is_online(port->fabric) == BFA_TRUE)
553 		bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_DISCONNECT);
554 	else
555 		bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_OFFLINE);
556 	bfa_fcb_port_offline(port->fcs->bfad, port->port_cfg.roles,
557 			port->fabric->vf_drv,
558 			(port->vport == NULL) ? NULL : port->vport->vport_drv);
559 
560 	list_for_each_safe(qe, qen, &port->rport_q) {
561 		rport = (struct bfa_fcs_rport_s *)qe;
562 		bfa_fcs_rport_offline(rport);
563 	}
564 }
565 
566 static void
567 bfa_fcs_port_unknown_init(struct bfa_fcs_port_s *port)
568 {
569 	bfa_assert(0);
570 }
571 
572 static void
573 bfa_fcs_port_unknown_online(struct bfa_fcs_port_s *port)
574 {
575 	bfa_assert(0);
576 }
577 
578 static void
579 bfa_fcs_port_unknown_offline(struct bfa_fcs_port_s *port)
580 {
581 	bfa_assert(0);
582 }
583 
584 static void
585 bfa_fcs_port_deleted(struct bfa_fcs_port_s *port)
586 {
587 	bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_DELETE);
588 
589 	/*
590 	 * Base port will be deleted by the OS driver
591 	 */
592 	if (port->vport) {
593 		bfa_fcb_port_delete(port->fcs->bfad, port->port_cfg.roles,
594 			port->fabric->vf_drv,
595 			port->vport ? port->vport->vport_drv : NULL);
596 		bfa_fcs_vport_delete_comp(port->vport);
597 	} else {
598 		bfa_fcs_fabric_port_delete_comp(port->fabric);
599 	}
600 }
601 
602 
603 
604 /**
605  *  fcs_lport_api BFA FCS port API
606  */
607 /**
608  *   Module initialization
609  */
610 void
611 bfa_fcs_port_modinit(struct bfa_fcs_s *fcs)
612 {
613 
614 }
615 
616 /**
617  *   Module cleanup
618  */
619 void
620 bfa_fcs_port_modexit(struct bfa_fcs_s *fcs)
621 {
622 	bfa_fcs_modexit_comp(fcs);
623 }
624 
625 /**
626  * 		Unsolicited frame receive handling.
627  */
628 void
629 bfa_fcs_port_uf_recv(struct bfa_fcs_port_s *lport, struct fchs_s *fchs,
630 			u16 len)
631 {
632 	u32        pid = fchs->s_id;
633 	struct bfa_fcs_rport_s *rport = NULL;
634 	struct fc_els_cmd_s   *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
635 
636 	bfa_stats(lport, uf_recvs);
637 
638 	if (!bfa_fcs_port_is_online(lport)) {
639 		bfa_stats(lport, uf_recv_drops);
640 		return;
641 	}
642 
643 	/**
644 	 * First, handle ELSs that donot require a login.
645 	 */
646 	/*
647 	 * Handle PLOGI first
648 	 */
649 	if ((fchs->type == FC_TYPE_ELS) &&
650 		(els_cmd->els_code == FC_ELS_PLOGI)) {
651 		bfa_fcs_port_plogi(lport, fchs, (struct fc_logi_s *) els_cmd);
652 		return;
653 	}
654 
655 	/*
656 	 * Handle ECHO separately.
657 	 */
658 	if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_ECHO)) {
659 		bfa_fcs_port_echo(lport, fchs,
660 			(struct fc_echo_s *) els_cmd, len);
661 		return;
662 	}
663 
664 	/*
665 	 * Handle RNID separately.
666 	 */
667 	if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_RNID)) {
668 		bfa_fcs_port_rnid(lport, fchs,
669 			(struct fc_rnid_cmd_s *) els_cmd, len);
670 		return;
671 	}
672 
673 	/**
674 	 * look for a matching remote port ID
675 	 */
676 	rport = bfa_fcs_port_get_rport_by_pid(lport, pid);
677 	if (rport) {
678 		bfa_trc(rport->fcs, fchs->s_id);
679 		bfa_trc(rport->fcs, fchs->d_id);
680 		bfa_trc(rport->fcs, fchs->type);
681 
682 		bfa_fcs_rport_uf_recv(rport, fchs, len);
683 		return;
684 	}
685 
686 	/**
687 	 * Only handles ELS frames for now.
688 	 */
689 	if (fchs->type != FC_TYPE_ELS) {
690 		bfa_trc(lport->fcs, fchs->type);
691 		bfa_assert(0);
692 		return;
693 	}
694 
695 	bfa_trc(lport->fcs, els_cmd->els_code);
696 	if (els_cmd->els_code == FC_ELS_RSCN) {
697 		bfa_fcs_port_scn_process_rscn(lport, fchs, len);
698 		return;
699 	}
700 
701 	if (els_cmd->els_code == FC_ELS_LOGO) {
702 		/**
703 		 * @todo Handle LOGO frames received.
704 		 */
705 		bfa_trc(lport->fcs, els_cmd->els_code);
706 		return;
707 	}
708 
709 	if (els_cmd->els_code == FC_ELS_PRLI) {
710 		/**
711 		 * @todo Handle PRLI frames received.
712 		 */
713 		bfa_trc(lport->fcs, els_cmd->els_code);
714 		return;
715 	}
716 
717 	/**
718 	 * Unhandled ELS frames. Send a LS_RJT.
719 	 */
720 	bfa_fcs_port_send_ls_rjt(lport, fchs, FC_LS_RJT_RSN_CMD_NOT_SUPP,
721 				 FC_LS_RJT_EXP_NO_ADDL_INFO);
722 
723 }
724 
725 /**
726  *   PID based Lookup for a R-Port in the Port R-Port Queue
727  */
728 struct bfa_fcs_rport_s *
729 bfa_fcs_port_get_rport_by_pid(struct bfa_fcs_port_s *port, u32 pid)
730 {
731 	struct bfa_fcs_rport_s *rport;
732 	struct list_head *qe;
733 
734 	list_for_each(qe, &port->rport_q) {
735 		rport = (struct bfa_fcs_rport_s *)qe;
736 		if (rport->pid == pid)
737 			return rport;
738 	}
739 
740 	bfa_trc(port->fcs, pid);
741 	return NULL;
742 }
743 
744 /**
745  *   PWWN based Lookup for a R-Port in the Port R-Port Queue
746  */
747 struct bfa_fcs_rport_s *
748 bfa_fcs_port_get_rport_by_pwwn(struct bfa_fcs_port_s *port, wwn_t pwwn)
749 {
750 	struct bfa_fcs_rport_s *rport;
751 	struct list_head *qe;
752 
753 	list_for_each(qe, &port->rport_q) {
754 		rport = (struct bfa_fcs_rport_s *)qe;
755 		if (wwn_is_equal(rport->pwwn, pwwn))
756 			return rport;
757 	}
758 
759 	bfa_trc(port->fcs, pwwn);
760 	return NULL;
761 }
762 
763 /**
764  *   NWWN based Lookup for a R-Port in the Port R-Port Queue
765  */
766 struct bfa_fcs_rport_s *
767 bfa_fcs_port_get_rport_by_nwwn(struct bfa_fcs_port_s *port, wwn_t nwwn)
768 {
769 	struct bfa_fcs_rport_s *rport;
770 	struct list_head *qe;
771 
772 	list_for_each(qe, &port->rport_q) {
773 		rport = (struct bfa_fcs_rport_s *)qe;
774 		if (wwn_is_equal(rport->nwwn, nwwn))
775 			return rport;
776 	}
777 
778 	bfa_trc(port->fcs, nwwn);
779 	return NULL;
780 }
781 
782 /**
783  * Called by rport module when new rports are discovered.
784  */
785 void
786 bfa_fcs_port_add_rport(struct bfa_fcs_port_s *port,
787 		       struct bfa_fcs_rport_s *rport)
788 {
789 	list_add_tail(&rport->qe, &port->rport_q);
790 	port->num_rports++;
791 }
792 
793 /**
794  * Called by rport module to when rports are deleted.
795  */
796 void
797 bfa_fcs_port_del_rport(struct bfa_fcs_port_s *port,
798 		       struct bfa_fcs_rport_s *rport)
799 {
800 	bfa_assert(bfa_q_is_on_q(&port->rport_q, rport));
801 	list_del(&rport->qe);
802 	port->num_rports--;
803 
804 	bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELRPORT);
805 }
806 
807 /**
808  * Called by fabric for base port when fabric login is complete.
809  * Called by vport for virtual ports when FDISC is complete.
810  */
811 void
812 bfa_fcs_port_online(struct bfa_fcs_port_s *port)
813 {
814 	bfa_sm_send_event(port, BFA_FCS_PORT_SM_ONLINE);
815 }
816 
817 /**
818  * Called by fabric for base port when fabric goes offline.
819  * Called by vport for virtual ports when virtual port becomes offline.
820  */
821 void
822 bfa_fcs_port_offline(struct bfa_fcs_port_s *port)
823 {
824 	bfa_sm_send_event(port, BFA_FCS_PORT_SM_OFFLINE);
825 }
826 
827 /**
828  * Called by fabric to delete base lport and associated resources.
829  *
830  * Called by vport to delete lport and associated resources. Should call
831  * bfa_fcs_vport_delete_comp() for vports on completion.
832  */
833 void
834 bfa_fcs_port_delete(struct bfa_fcs_port_s *port)
835 {
836 	bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELETE);
837 }
838 
839 /**
840  * Called by fabric in private loop topology to process LIP event.
841  */
842 void
843 bfa_fcs_port_lip(struct bfa_fcs_port_s *port)
844 {
845 }
846 
847 /**
848  * Return TRUE if port is online, else return FALSE
849  */
850 bfa_boolean_t
851 bfa_fcs_port_is_online(struct bfa_fcs_port_s *port)
852 {
853 	return bfa_sm_cmp_state(port, bfa_fcs_port_sm_online);
854 }
855 
856 /**
857  * Attach time initialization of logical ports.
858  */
859 void
860 bfa_fcs_lport_attach(struct bfa_fcs_port_s *lport, struct bfa_fcs_s *fcs,
861 		uint16_t vf_id, struct bfa_fcs_vport_s *vport)
862 {
863 	lport->fcs = fcs;
864 	lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id);
865 	lport->vport = vport;
866 	lport->lp_tag = (vport) ? bfa_lps_get_tag(vport->lps) :
867 			 bfa_lps_get_tag(lport->fabric->lps);
868 
869 	INIT_LIST_HEAD(&lport->rport_q);
870 	lport->num_rports = 0;
871 }
872 
873 /**
874  * Logical port initialization of base or virtual port.
875  * Called by fabric for base port or by vport for virtual ports.
876  */
877 
878 void
879 bfa_fcs_lport_init(struct bfa_fcs_port_s *lport,
880 		struct bfa_port_cfg_s *port_cfg)
881 {
882 	struct bfa_fcs_vport_s *vport = lport->vport;
883 
884 	bfa_os_assign(lport->port_cfg, *port_cfg);
885 
886 	lport->bfad_port = bfa_fcb_port_new(lport->fcs->bfad, lport,
887 				lport->port_cfg.roles,
888 				lport->fabric->vf_drv,
889 				vport ? vport->vport_drv : NULL);
890 
891 	bfa_fcs_port_aen_post(lport, BFA_LPORT_AEN_NEW);
892 
893 	bfa_sm_set_state(lport, bfa_fcs_port_sm_uninit);
894 	bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE);
895 }
896 
897 /**
898  *  fcs_lport_api
899  */
900 
901 void
902 bfa_fcs_port_get_attr(struct bfa_fcs_port_s *port,
903 		      struct bfa_port_attr_s *port_attr)
904 {
905 	if (bfa_sm_cmp_state(port, bfa_fcs_port_sm_online))
906 		port_attr->pid = port->pid;
907 	else
908 		port_attr->pid = 0;
909 
910 	port_attr->port_cfg = port->port_cfg;
911 
912 	if (port->fabric) {
913 		port_attr->port_type = bfa_fcs_fabric_port_type(port->fabric);
914 		port_attr->loopback = bfa_fcs_fabric_is_loopback(port->fabric);
915 		port_attr->authfail =
916 				bfa_fcs_fabric_is_auth_failed(port->fabric);
917 		port_attr->fabric_name = bfa_fcs_port_get_fabric_name(port);
918 		memcpy(port_attr->fabric_ip_addr,
919 		       bfa_fcs_port_get_fabric_ipaddr(port),
920 		       BFA_FCS_FABRIC_IPADDR_SZ);
921 
922 		if (port->vport != NULL) {
923 			port_attr->port_type = BFA_PPORT_TYPE_VPORT;
924 			port_attr->fpma_mac =
925 				bfa_lps_get_lp_mac(port->vport->lps);
926 		} else
927 			port_attr->fpma_mac =
928 				bfa_lps_get_lp_mac(port->fabric->lps);
929 
930 	} else {
931 		port_attr->port_type = BFA_PPORT_TYPE_UNKNOWN;
932 		port_attr->state = BFA_PORT_UNINIT;
933 	}
934 
935 }
936 
937 
938