1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2021 Broadcom. All Rights Reserved. The term
4 * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
5 */
6
7/*
8 * NPORT
9 *
10 * Port object for physical port and NPIV ports.
11 */
12
13/*
14 * NPORT REFERENCE COUNTING
15 *
16 * A nport reference should be taken when:
17 * - an nport is allocated
18 * - a vport populates associated nport
19 * - a remote node is allocated
20 * - a unsolicited frame is processed
21 * The reference should be dropped when:
22 * - the unsolicited frame processesing is done
23 * - the remote node is removed
24 * - the vport is removed
25 * - the nport is removed
26 */
27
28#include "efc.h"
29
30void
31efc_nport_cb(void *arg, int event, void *data)
32{
33	struct efc *efc = arg;
34	struct efc_nport *nport = data;
35	unsigned long flags = 0;
36
37	efc_log_debug(efc, "nport event: %s\n", efc_sm_event_name(event));
38
39	spin_lock_irqsave(&efc->lock, flags);
40	efc_sm_post_event(&nport->sm, event, NULL);
41	spin_unlock_irqrestore(&efc->lock, flags);
42}
43
44static struct efc_nport *
45efc_nport_find_wwn(struct efc_domain *domain, uint64_t wwnn, uint64_t wwpn)
46{
47	struct efc_nport *nport = NULL;
48
49	/* Find a nport, given the WWNN and WWPN */
50	list_for_each_entry(nport, &domain->nport_list, list_entry) {
51		if (nport->wwnn == wwnn && nport->wwpn == wwpn)
52			return nport;
53	}
54	return NULL;
55}
56
57static void
58_efc_nport_free(struct kref *arg)
59{
60	struct efc_nport *nport = container_of(arg, struct efc_nport, ref);
61
62	kfree(nport);
63}
64
65struct efc_nport *
66efc_nport_alloc(struct efc_domain *domain, uint64_t wwpn, uint64_t wwnn,
67		u32 fc_id, bool enable_ini, bool enable_tgt)
68{
69	struct efc_nport *nport;
70
71	if (domain->efc->enable_ini)
72		enable_ini = 0;
73
74	/* Return a failure if this nport has already been allocated */
75	if ((wwpn != 0) || (wwnn != 0)) {
76		nport = efc_nport_find_wwn(domain, wwnn, wwpn);
77		if (nport) {
78			efc_log_err(domain->efc,
79				    "NPORT %016llX %016llX already allocated\n",
80				    wwnn, wwpn);
81			return NULL;
82		}
83	}
84
85	nport = kzalloc(sizeof(*nport), GFP_ATOMIC);
86	if (!nport)
87		return nport;
88
89	/* initialize refcount */
90	kref_init(&nport->ref);
91	nport->release = _efc_nport_free;
92
93	nport->efc = domain->efc;
94	snprintf(nport->display_name, sizeof(nport->display_name), "------");
95	nport->domain = domain;
96	xa_init(&nport->lookup);
97	nport->instance_index = domain->nport_count++;
98	nport->sm.app = nport;
99	nport->enable_ini = enable_ini;
100	nport->enable_tgt = enable_tgt;
101	nport->enable_rscn = (nport->enable_ini ||
102			(nport->enable_tgt && enable_target_rscn(nport->efc)));
103
104	/* Copy service parameters from domain */
105	memcpy(nport->service_params, domain->service_params,
106	       sizeof(struct fc_els_flogi));
107
108	/* Update requested fc_id */
109	nport->fc_id = fc_id;
110
111	/* Update the nport's service parameters for the new wwn's */
112	nport->wwpn = wwpn;
113	nport->wwnn = wwnn;
114	snprintf(nport->wwnn_str, sizeof(nport->wwnn_str), "%016llX",
115		 (unsigned long long)wwnn);
116
117	/*
118	 * if this is the "first" nport of the domain,
119	 * then make it the "phys" nport
120	 */
121	if (list_empty(&domain->nport_list))
122		domain->nport = nport;
123
124	INIT_LIST_HEAD(&nport->list_entry);
125	list_add_tail(&nport->list_entry, &domain->nport_list);
126
127	kref_get(&domain->ref);
128
129	efc_log_debug(domain->efc, "New Nport [%s]\n", nport->display_name);
130
131	return nport;
132}
133
134void
135efc_nport_free(struct efc_nport *nport)
136{
137	struct efc_domain *domain;
138
139	if (!nport)
140		return;
141
142	domain = nport->domain;
143	efc_log_debug(domain->efc, "[%s] free nport\n", nport->display_name);
144	list_del(&nport->list_entry);
145	/*
146	 * if this is the physical nport,
147	 * then clear it out of the domain
148	 */
149	if (nport == domain->nport)
150		domain->nport = NULL;
151
152	xa_destroy(&nport->lookup);
153	xa_erase(&domain->lookup, nport->fc_id);
154
155	if (list_empty(&domain->nport_list))
156		efc_domain_post_event(domain, EFC_EVT_ALL_CHILD_NODES_FREE,
157				      NULL);
158
159	kref_put(&domain->ref, domain->release);
160	kref_put(&nport->ref, nport->release);
161}
162
163struct efc_nport *
164efc_nport_find(struct efc_domain *domain, u32 d_id)
165{
166	struct efc_nport *nport;
167
168	/* Find a nport object, given an FC_ID */
169	nport = xa_load(&domain->lookup, d_id);
170	if (!nport || !kref_get_unless_zero(&nport->ref))
171		return NULL;
172
173	return nport;
174}
175
176int
177efc_nport_attach(struct efc_nport *nport, u32 fc_id)
178{
179	int rc;
180	struct efc_node *node;
181	struct efc *efc = nport->efc;
182	unsigned long index;
183
184	/* Set our lookup */
185	rc = xa_err(xa_store(&nport->domain->lookup, fc_id, nport, GFP_ATOMIC));
186	if (rc) {
187		efc_log_err(efc, "Sport lookup store failed: %d\n", rc);
188		return rc;
189	}
190
191	/* Update our display_name */
192	efc_node_fcid_display(fc_id, nport->display_name,
193			      sizeof(nport->display_name));
194
195	xa_for_each(&nport->lookup, index, node) {
196		efc_node_update_display_name(node);
197	}
198
199	efc_log_debug(nport->efc, "[%s] attach nport: fc_id x%06x\n",
200		      nport->display_name, fc_id);
201
202	/* Register a nport, given an FC_ID */
203	rc = efc_cmd_nport_attach(efc, nport, fc_id);
204	if (rc < 0) {
205		efc_log_err(nport->efc,
206			    "efc_hw_port_attach failed: %d\n", rc);
207		return -EIO;
208	}
209	return 0;
210}
211
212static void
213efc_nport_shutdown(struct efc_nport *nport)
214{
215	struct efc *efc = nport->efc;
216	struct efc_node *node;
217	unsigned long index;
218
219	xa_for_each(&nport->lookup, index, node) {
220		if (!(node->rnode.fc_id == FC_FID_FLOGI && nport->is_vport)) {
221			efc_node_post_event(node, EFC_EVT_SHUTDOWN, NULL);
222			continue;
223		}
224
225		/*
226		 * If this is a vport, logout of the fabric
227		 * controller so that it deletes the vport
228		 * on the switch.
229		 */
230		/* if link is down, don't send logo */
231		if (efc->link_status == EFC_LINK_STATUS_DOWN) {
232			efc_node_post_event(node, EFC_EVT_SHUTDOWN, NULL);
233			continue;
234		}
235
236		efc_log_debug(efc, "[%s] nport shutdown vport, send logo\n",
237			      node->display_name);
238
239		if (!efc_send_logo(node)) {
240			/* sent LOGO, wait for response */
241			efc_node_transition(node, __efc_d_wait_logo_rsp, NULL);
242			continue;
243		}
244
245		/*
246		 * failed to send LOGO,
247		 * go ahead and cleanup node anyways
248		 */
249		node_printf(node, "Failed to send LOGO\n");
250		efc_node_post_event(node, EFC_EVT_SHUTDOWN_EXPLICIT_LOGO, NULL);
251	}
252}
253
254static void
255efc_vport_link_down(struct efc_nport *nport)
256{
257	struct efc *efc = nport->efc;
258	struct efc_vport *vport;
259
260	/* Clear the nport reference in the vport specification */
261	list_for_each_entry(vport, &efc->vport_list, list_entry) {
262		if (vport->nport == nport) {
263			kref_put(&nport->ref, nport->release);
264			vport->nport = NULL;
265			break;
266		}
267	}
268}
269
270static void
271__efc_nport_common(const char *funcname, struct efc_sm_ctx *ctx,
272		   enum efc_sm_event evt, void *arg)
273{
274	struct efc_nport *nport = ctx->app;
275	struct efc_domain *domain = nport->domain;
276	struct efc *efc = nport->efc;
277
278	switch (evt) {
279	case EFC_EVT_ENTER:
280	case EFC_EVT_REENTER:
281	case EFC_EVT_EXIT:
282	case EFC_EVT_ALL_CHILD_NODES_FREE:
283		break;
284	case EFC_EVT_NPORT_ATTACH_OK:
285			efc_sm_transition(ctx, __efc_nport_attached, NULL);
286		break;
287	case EFC_EVT_SHUTDOWN:
288		/* Flag this nport as shutting down */
289		nport->shutting_down = true;
290
291		if (nport->is_vport)
292			efc_vport_link_down(nport);
293
294		if (xa_empty(&nport->lookup)) {
295			/* Remove the nport from the domain's lookup table */
296			xa_erase(&domain->lookup, nport->fc_id);
297			efc_sm_transition(ctx, __efc_nport_wait_port_free,
298					  NULL);
299			if (efc_cmd_nport_free(efc, nport)) {
300				efc_log_debug(nport->efc,
301					      "efc_hw_port_free failed\n");
302				/* Not much we can do, free the nport anyways */
303				efc_nport_free(nport);
304			}
305		} else {
306			/* sm: node list is not empty / shutdown nodes */
307			efc_sm_transition(ctx,
308					  __efc_nport_wait_shutdown, NULL);
309			efc_nport_shutdown(nport);
310		}
311		break;
312	default:
313		efc_log_debug(nport->efc, "[%s] %-20s %-20s not handled\n",
314			      nport->display_name, funcname,
315			      efc_sm_event_name(evt));
316	}
317}
318
319void
320__efc_nport_allocated(struct efc_sm_ctx *ctx,
321		      enum efc_sm_event evt, void *arg)
322{
323	struct efc_nport *nport = ctx->app;
324	struct efc_domain *domain = nport->domain;
325
326	nport_sm_trace(nport);
327
328	switch (evt) {
329	/* the physical nport is attached */
330	case EFC_EVT_NPORT_ATTACH_OK:
331		WARN_ON(nport != domain->nport);
332		efc_sm_transition(ctx, __efc_nport_attached, NULL);
333		break;
334
335	case EFC_EVT_NPORT_ALLOC_OK:
336		/* ignore */
337		break;
338	default:
339		__efc_nport_common(__func__, ctx, evt, arg);
340	}
341}
342
343void
344__efc_nport_vport_init(struct efc_sm_ctx *ctx,
345		       enum efc_sm_event evt, void *arg)
346{
347	struct efc_nport *nport = ctx->app;
348	struct efc *efc = nport->efc;
349
350	nport_sm_trace(nport);
351
352	switch (evt) {
353	case EFC_EVT_ENTER: {
354		__be64 be_wwpn = cpu_to_be64(nport->wwpn);
355
356		if (nport->wwpn == 0)
357			efc_log_debug(efc, "vport: letting f/w select WWN\n");
358
359		if (nport->fc_id != U32_MAX) {
360			efc_log_debug(efc, "vport: hard coding port id: %x\n",
361				      nport->fc_id);
362		}
363
364		efc_sm_transition(ctx, __efc_nport_vport_wait_alloc, NULL);
365		/* If wwpn is zero, then we'll let the f/w assign wwpn*/
366		if (efc_cmd_nport_alloc(efc, nport, nport->domain,
367					nport->wwpn == 0 ? NULL :
368					(uint8_t *)&be_wwpn)) {
369			efc_log_err(efc, "Can't allocate port\n");
370			break;
371		}
372
373		break;
374	}
375	default:
376		__efc_nport_common(__func__, ctx, evt, arg);
377	}
378}
379
380void
381__efc_nport_vport_wait_alloc(struct efc_sm_ctx *ctx,
382			     enum efc_sm_event evt, void *arg)
383{
384	struct efc_nport *nport = ctx->app;
385	struct efc *efc = nport->efc;
386
387	nport_sm_trace(nport);
388
389	switch (evt) {
390	case EFC_EVT_NPORT_ALLOC_OK: {
391		struct fc_els_flogi *sp;
392
393		sp = (struct fc_els_flogi *)nport->service_params;
394
395		if (nport->wwnn == 0) {
396			nport->wwnn = be64_to_cpu(nport->sli_wwnn);
397			nport->wwpn = be64_to_cpu(nport->sli_wwpn);
398			snprintf(nport->wwnn_str, sizeof(nport->wwnn_str),
399				 "%016llX", nport->wwpn);
400		}
401
402		/* Update the nport's service parameters */
403		sp->fl_wwpn = cpu_to_be64(nport->wwpn);
404		sp->fl_wwnn = cpu_to_be64(nport->wwnn);
405
406		/*
407		 * if nport->fc_id is uninitialized,
408		 * then request that the fabric node use FDISC
409		 * to find an fc_id.
410		 * Otherwise we're restoring vports, or we're in
411		 * fabric emulation mode, so attach the fc_id
412		 */
413		if (nport->fc_id == U32_MAX) {
414			struct efc_node *fabric;
415
416			fabric = efc_node_alloc(nport, FC_FID_FLOGI, false,
417						false);
418			if (!fabric) {
419				efc_log_err(efc, "efc_node_alloc() failed\n");
420				return;
421			}
422			efc_node_transition(fabric, __efc_vport_fabric_init,
423					    NULL);
424		} else {
425			snprintf(nport->wwnn_str, sizeof(nport->wwnn_str),
426				 "%016llX", nport->wwpn);
427			efc_nport_attach(nport, nport->fc_id);
428		}
429		efc_sm_transition(ctx, __efc_nport_vport_allocated, NULL);
430		break;
431	}
432	default:
433		__efc_nport_common(__func__, ctx, evt, arg);
434	}
435}
436
437void
438__efc_nport_vport_allocated(struct efc_sm_ctx *ctx,
439			    enum efc_sm_event evt, void *arg)
440{
441	struct efc_nport *nport = ctx->app;
442	struct efc *efc = nport->efc;
443
444	nport_sm_trace(nport);
445
446	/*
447	 * This state is entered after the nport is allocated;
448	 * it then waits for a fabric node
449	 * FDISC to complete, which requests a nport attach.
450	 * The nport attach complete is handled in this state.
451	 */
452	switch (evt) {
453	case EFC_EVT_NPORT_ATTACH_OK: {
454		struct efc_node *node;
455
456		/* Find our fabric node, and forward this event */
457		node = efc_node_find(nport, FC_FID_FLOGI);
458		if (!node) {
459			efc_log_debug(efc, "can't find node %06x\n", FC_FID_FLOGI);
460			break;
461		}
462		/* sm: / forward nport attach to fabric node */
463		efc_node_post_event(node, evt, NULL);
464		efc_sm_transition(ctx, __efc_nport_attached, NULL);
465		break;
466	}
467	default:
468		__efc_nport_common(__func__, ctx, evt, arg);
469	}
470}
471
472static void
473efc_vport_update_spec(struct efc_nport *nport)
474{
475	struct efc *efc = nport->efc;
476	struct efc_vport *vport;
477	unsigned long flags = 0;
478
479	spin_lock_irqsave(&efc->vport_lock, flags);
480	list_for_each_entry(vport, &efc->vport_list, list_entry) {
481		if (vport->nport == nport) {
482			vport->wwnn = nport->wwnn;
483			vport->wwpn = nport->wwpn;
484			vport->tgt_data = nport->tgt_data;
485			vport->ini_data = nport->ini_data;
486			break;
487		}
488	}
489	spin_unlock_irqrestore(&efc->vport_lock, flags);
490}
491
492void
493__efc_nport_attached(struct efc_sm_ctx *ctx,
494		     enum efc_sm_event evt, void *arg)
495{
496	struct efc_nport *nport = ctx->app;
497	struct efc *efc = nport->efc;
498
499	nport_sm_trace(nport);
500
501	switch (evt) {
502	case EFC_EVT_ENTER: {
503		struct efc_node *node;
504		unsigned long index;
505
506		efc_log_debug(efc,
507			      "[%s] NPORT attached WWPN %016llX WWNN %016llX\n",
508			      nport->display_name,
509			      nport->wwpn, nport->wwnn);
510
511		xa_for_each(&nport->lookup, index, node)
512			efc_node_update_display_name(node);
513
514		efc->tt.new_nport(efc, nport);
515
516		/*
517		 * Update the vport (if its not the physical nport)
518		 * parameters
519		 */
520		if (nport->is_vport)
521			efc_vport_update_spec(nport);
522		break;
523	}
524
525	case EFC_EVT_EXIT:
526		efc_log_debug(efc,
527			      "[%s] NPORT deattached WWPN %016llX WWNN %016llX\n",
528			      nport->display_name,
529			      nport->wwpn, nport->wwnn);
530
531		efc->tt.del_nport(efc, nport);
532		break;
533	default:
534		__efc_nport_common(__func__, ctx, evt, arg);
535	}
536}
537
538void
539__efc_nport_wait_shutdown(struct efc_sm_ctx *ctx,
540			  enum efc_sm_event evt, void *arg)
541{
542	struct efc_nport *nport = ctx->app;
543	struct efc_domain *domain = nport->domain;
544	struct efc *efc = nport->efc;
545
546	nport_sm_trace(nport);
547
548	switch (evt) {
549	case EFC_EVT_NPORT_ALLOC_OK:
550	case EFC_EVT_NPORT_ALLOC_FAIL:
551	case EFC_EVT_NPORT_ATTACH_OK:
552	case EFC_EVT_NPORT_ATTACH_FAIL:
553		/* ignore these events - just wait for the all free event */
554		break;
555
556	case EFC_EVT_ALL_CHILD_NODES_FREE: {
557		/*
558		 * Remove the nport from the domain's
559		 * sparse vector lookup table
560		 */
561		xa_erase(&domain->lookup, nport->fc_id);
562		efc_sm_transition(ctx, __efc_nport_wait_port_free, NULL);
563		if (efc_cmd_nport_free(efc, nport)) {
564			efc_log_err(nport->efc, "efc_hw_port_free failed\n");
565			/* Not much we can do, free the nport anyways */
566			efc_nport_free(nport);
567		}
568		break;
569	}
570	default:
571		__efc_nport_common(__func__, ctx, evt, arg);
572	}
573}
574
575void
576__efc_nport_wait_port_free(struct efc_sm_ctx *ctx,
577			   enum efc_sm_event evt, void *arg)
578{
579	struct efc_nport *nport = ctx->app;
580
581	nport_sm_trace(nport);
582
583	switch (evt) {
584	case EFC_EVT_NPORT_ATTACH_OK:
585		/* Ignore as we are waiting for the free CB */
586		break;
587	case EFC_EVT_NPORT_FREE_OK: {
588		/* All done, free myself */
589		efc_nport_free(nport);
590		break;
591	}
592	default:
593		__efc_nport_common(__func__, ctx, evt, arg);
594	}
595}
596
597static int
598efc_vport_nport_alloc(struct efc_domain *domain, struct efc_vport *vport)
599{
600	struct efc_nport *nport;
601
602	lockdep_assert_held(&domain->efc->lock);
603
604	nport = efc_nport_alloc(domain, vport->wwpn, vport->wwnn, vport->fc_id,
605				vport->enable_ini, vport->enable_tgt);
606	vport->nport = nport;
607	if (!nport)
608		return -EIO;
609
610	kref_get(&nport->ref);
611	nport->is_vport = true;
612	nport->tgt_data = vport->tgt_data;
613	nport->ini_data = vport->ini_data;
614
615	efc_sm_transition(&nport->sm, __efc_nport_vport_init, NULL);
616
617	return 0;
618}
619
620int
621efc_vport_start(struct efc_domain *domain)
622{
623	struct efc *efc = domain->efc;
624	struct efc_vport *vport;
625	struct efc_vport *next;
626	int rc = 0;
627	unsigned long flags = 0;
628
629	/* Use the vport spec to find the associated vports and start them */
630	spin_lock_irqsave(&efc->vport_lock, flags);
631	list_for_each_entry_safe(vport, next, &efc->vport_list, list_entry) {
632		if (!vport->nport) {
633			if (efc_vport_nport_alloc(domain, vport))
634				rc = -EIO;
635		}
636	}
637	spin_unlock_irqrestore(&efc->vport_lock, flags);
638
639	return rc;
640}
641
642int
643efc_nport_vport_new(struct efc_domain *domain, uint64_t wwpn, uint64_t wwnn,
644		    u32 fc_id, bool ini, bool tgt, void *tgt_data,
645		    void *ini_data)
646{
647	struct efc *efc = domain->efc;
648	struct efc_vport *vport;
649	int rc = 0;
650	unsigned long flags = 0;
651
652	if (ini && domain->efc->enable_ini == 0) {
653		efc_log_debug(efc, "driver initiator mode not enabled\n");
654		return -EIO;
655	}
656
657	if (tgt && domain->efc->enable_tgt == 0) {
658		efc_log_debug(efc, "driver target mode not enabled\n");
659		return -EIO;
660	}
661
662	/*
663	 * Create a vport spec if we need to recreate
664	 * this vport after a link up event
665	 */
666	vport = efc_vport_create_spec(domain->efc, wwnn, wwpn, fc_id, ini, tgt,
667				      tgt_data, ini_data);
668	if (!vport) {
669		efc_log_err(efc, "failed to create vport object entry\n");
670		return -EIO;
671	}
672
673	spin_lock_irqsave(&efc->lock, flags);
674	rc = efc_vport_nport_alloc(domain, vport);
675	spin_unlock_irqrestore(&efc->lock, flags);
676
677	return rc;
678}
679
680int
681efc_nport_vport_del(struct efc *efc, struct efc_domain *domain,
682		    u64 wwpn, uint64_t wwnn)
683{
684	struct efc_nport *nport;
685	struct efc_vport *vport;
686	struct efc_vport *next;
687	unsigned long flags = 0;
688
689	spin_lock_irqsave(&efc->vport_lock, flags);
690	/* walk the efc_vport_list and remove from there */
691	list_for_each_entry_safe(vport, next, &efc->vport_list, list_entry) {
692		if (vport->wwpn == wwpn && vport->wwnn == wwnn) {
693			list_del(&vport->list_entry);
694			kfree(vport);
695			break;
696		}
697	}
698	spin_unlock_irqrestore(&efc->vport_lock, flags);
699
700	if (!domain) {
701		/* No domain means no nport to look for */
702		return 0;
703	}
704
705	spin_lock_irqsave(&efc->lock, flags);
706	list_for_each_entry(nport, &domain->nport_list, list_entry) {
707		if (nport->wwpn == wwpn && nport->wwnn == wwnn) {
708			kref_put(&nport->ref, nport->release);
709			/* Shutdown this NPORT */
710			efc_sm_post_event(&nport->sm, EFC_EVT_SHUTDOWN, NULL);
711			break;
712		}
713	}
714
715	spin_unlock_irqrestore(&efc->lock, flags);
716	return 0;
717}
718
719void
720efc_vport_del_all(struct efc *efc)
721{
722	struct efc_vport *vport;
723	struct efc_vport *next;
724	unsigned long flags = 0;
725
726	spin_lock_irqsave(&efc->vport_lock, flags);
727	list_for_each_entry_safe(vport, next, &efc->vport_list, list_entry) {
728		list_del(&vport->list_entry);
729		kfree(vport);
730	}
731	spin_unlock_irqrestore(&efc->vport_lock, flags);
732}
733
734struct efc_vport *
735efc_vport_create_spec(struct efc *efc, uint64_t wwnn, uint64_t wwpn,
736		      u32 fc_id, bool enable_ini,
737		      bool enable_tgt, void *tgt_data, void *ini_data)
738{
739	struct efc_vport *vport;
740	unsigned long flags = 0;
741
742	/*
743	 * walk the efc_vport_list and return failure
744	 * if a valid(vport with non zero WWPN and WWNN) vport entry
745	 * is already created
746	 */
747	spin_lock_irqsave(&efc->vport_lock, flags);
748	list_for_each_entry(vport, &efc->vport_list, list_entry) {
749		if ((wwpn && vport->wwpn == wwpn) &&
750		    (wwnn && vport->wwnn == wwnn)) {
751			efc_log_err(efc,
752				    "VPORT %016llX %016llX already allocated\n",
753				    wwnn, wwpn);
754			spin_unlock_irqrestore(&efc->vport_lock, flags);
755			return NULL;
756		}
757	}
758
759	vport = kzalloc(sizeof(*vport), GFP_ATOMIC);
760	if (!vport) {
761		spin_unlock_irqrestore(&efc->vport_lock, flags);
762		return NULL;
763	}
764
765	vport->wwnn = wwnn;
766	vport->wwpn = wwpn;
767	vport->fc_id = fc_id;
768	vport->enable_tgt = enable_tgt;
769	vport->enable_ini = enable_ini;
770	vport->tgt_data = tgt_data;
771	vport->ini_data = ini_data;
772
773	INIT_LIST_HEAD(&vport->list_entry);
774	list_add_tail(&vport->list_entry, &efc->vport_list);
775	spin_unlock_irqrestore(&efc->vport_lock, flags);
776	return vport;
777}
778