1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte  * CDDL HEADER START
3fcf3ce44SJohn Forte  *
4fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte  *
8fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte  * and limitations under the License.
12fcf3ce44SJohn Forte  *
13fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte  *
19fcf3ce44SJohn Forte  * CDDL HEADER END
20fcf3ce44SJohn Forte  */
21fcf3ce44SJohn Forte /*
22fcf3ce44SJohn Forte  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23fcf3ce44SJohn Forte  * Use is subject to license terms.
2448bbca81SDaniel Hoffman  * Copyright (c) 2016 by Delphix. All rights reserved.
25fcf3ce44SJohn Forte  */
26fcf3ce44SJohn Forte 
27fcf3ce44SJohn Forte /*
28fcf3ce44SJohn Forte  * SunOS 5.x Multithreaded STREAMS DLPI FCIP Module
29fcf3ce44SJohn Forte  * This is a pseudo driver module to handle encapsulation of IP and ARP
30fcf3ce44SJohn Forte  * datagrams over FibreChannel interfaces. FCIP is a cloneable STREAMS
31fcf3ce44SJohn Forte  * driver module which interfaces with IP/ARP using DLPI. This module
32fcf3ce44SJohn Forte  * is a Style-2 DLS provider.
33fcf3ce44SJohn Forte  *
34fcf3ce44SJohn Forte  * The implementation of this module is based on RFC 2625 which gives
35fcf3ce44SJohn Forte  * details on the encapsulation of IP/ARP data over FibreChannel.
36fcf3ce44SJohn Forte  * The fcip module needs to resolve an IP address to a port address before
37fcf3ce44SJohn Forte  * sending data to a destination port. A FC device port has 2 addresses
38fcf3ce44SJohn Forte  * associated with it: A 8 byte World Wide unique Port Name and a 3 byte
39fcf3ce44SJohn Forte  * volatile Port number or Port_ID.
40fcf3ce44SJohn Forte  *
41fcf3ce44SJohn Forte  * The mapping between a IP address and the World Wide Port Name is handled
42fcf3ce44SJohn Forte  * by the ARP layer since the IP over FC draft requires the MAC address to
43fcf3ce44SJohn Forte  * be the least significant six bytes of the WorldWide Port Names. The
44fcf3ce44SJohn Forte  * fcip module however needs to identify the destination port uniquely when
45fcf3ce44SJohn Forte  * the destination FC device has multiple FC ports.
46fcf3ce44SJohn Forte  *
47fcf3ce44SJohn Forte  * The FC layer mapping between the World Wide Port Name and the Port_ID
48fcf3ce44SJohn Forte  * will be handled through the use of a fabric name server or through the
49fcf3ce44SJohn Forte  * use of the FARP ELS command as described in the draft. Since the Port_IDs
50fcf3ce44SJohn Forte  * are volatile, the mapping between the World Wide Port Name and Port_IDs
51fcf3ce44SJohn Forte  * must be maintained and validated before use each time a datagram
52fcf3ce44SJohn Forte  * needs to be sent to the destination ports. The FC transport module
53fcf3ce44SJohn Forte  * informs the fcip module of all changes to states of ports on the
54fcf3ce44SJohn Forte  * fabric through registered callbacks. This enables the fcip module
55fcf3ce44SJohn Forte  * to maintain the WW_PN to Port_ID mappings current.
56fcf3ce44SJohn Forte  *
57fcf3ce44SJohn Forte  * For details on how this module interfaces with the FibreChannel Transport
58fcf3ce44SJohn Forte  * modules, refer to PSARC/1997/385. Chapter 3 of the FibreChannel Transport
59fcf3ce44SJohn Forte  * Programming guide details the APIs between ULPs and the Transport.
60fcf3ce44SJohn Forte  *
61fcf3ce44SJohn Forte  * Now for some Caveats:
62fcf3ce44SJohn Forte  *
63fcf3ce44SJohn Forte  * RFC 2625 requires that a FibreChannel Port name (the Port WWN) have
64fcf3ce44SJohn Forte  * the NAA bits set to '0001' indicating a IEEE 48bit address which
65fcf3ce44SJohn Forte  * corresponds to a ULA (Universal LAN MAC address). But with FibreChannel
66fcf3ce44SJohn Forte  * adapters containing 2 or more ports, IEEE naming cannot identify the
67fcf3ce44SJohn Forte  * ports on an adapter uniquely so we will in the first implementation
68fcf3ce44SJohn Forte  * be operating only on Port 0 of each adapter.
69fcf3ce44SJohn Forte  */
70fcf3ce44SJohn Forte 
71fcf3ce44SJohn Forte #include	<sys/types.h>
72fcf3ce44SJohn Forte #include	<sys/errno.h>
73fcf3ce44SJohn Forte #include	<sys/debug.h>
74fcf3ce44SJohn Forte #include	<sys/time.h>
75fcf3ce44SJohn Forte #include	<sys/sysmacros.h>
76fcf3ce44SJohn Forte #include	<sys/systm.h>
77fcf3ce44SJohn Forte #include	<sys/user.h>
78fcf3ce44SJohn Forte #include	<sys/stropts.h>
79fcf3ce44SJohn Forte #include	<sys/stream.h>
80fcf3ce44SJohn Forte #include	<sys/strlog.h>
81fcf3ce44SJohn Forte #include	<sys/strsubr.h>
82fcf3ce44SJohn Forte #include	<sys/cmn_err.h>
83fcf3ce44SJohn Forte #include	<sys/cpu.h>
84fcf3ce44SJohn Forte #include	<sys/kmem.h>
85fcf3ce44SJohn Forte #include	<sys/conf.h>
86fcf3ce44SJohn Forte #include	<sys/ddi.h>
87fcf3ce44SJohn Forte #include	<sys/sunddi.h>
88fcf3ce44SJohn Forte #include	<sys/ksynch.h>
89fcf3ce44SJohn Forte #include	<sys/stat.h>
90fcf3ce44SJohn Forte #include	<sys/kstat.h>
91fcf3ce44SJohn Forte #include	<sys/vtrace.h>
92fcf3ce44SJohn Forte #include	<sys/strsun.h>
93fcf3ce44SJohn Forte #include	<sys/varargs.h>
94fcf3ce44SJohn Forte #include	<sys/modctl.h>
95fcf3ce44SJohn Forte #include 	<sys/thread.h>
96fcf3ce44SJohn Forte #include 	<sys/var.h>
97fcf3ce44SJohn Forte #include 	<sys/proc.h>
98fcf3ce44SJohn Forte #include	<inet/common.h>
99fcf3ce44SJohn Forte #include	<netinet/ip6.h>
100fcf3ce44SJohn Forte #include	<inet/ip.h>
101fcf3ce44SJohn Forte #include	<inet/arp.h>
102fcf3ce44SJohn Forte #include	<inet/mi.h>
103fcf3ce44SJohn Forte #include	<inet/nd.h>
104fcf3ce44SJohn Forte #include	<sys/dlpi.h>
105fcf3ce44SJohn Forte #include	<sys/ethernet.h>
106fcf3ce44SJohn Forte #include	<sys/file.h>
107fcf3ce44SJohn Forte #include	<sys/syslog.h>
108fcf3ce44SJohn Forte #include	<sys/disp.h>
109fcf3ce44SJohn Forte #include	<sys/taskq.h>
110fcf3ce44SJohn Forte 
111fcf3ce44SJohn Forte /*
112fcf3ce44SJohn Forte  * Leadville includes
113fcf3ce44SJohn Forte  */
114fcf3ce44SJohn Forte 
115fcf3ce44SJohn Forte #include	<sys/fibre-channel/fc.h>
116fcf3ce44SJohn Forte #include	<sys/fibre-channel/impl/fc_ulpif.h>
117fcf3ce44SJohn Forte #include	<sys/fibre-channel/ulp/fcip.h>
118fcf3ce44SJohn Forte 
119fcf3ce44SJohn Forte /*
120fcf3ce44SJohn Forte  * TNF Probe/trace facility include
121fcf3ce44SJohn Forte  */
122fcf3ce44SJohn Forte #if defined(lint) || defined(FCIP_TNF_ENABLED)
123fcf3ce44SJohn Forte #include <sys/tnf_probe.h>
124fcf3ce44SJohn Forte #endif
125fcf3ce44SJohn Forte 
126fcf3ce44SJohn Forte #define	FCIP_ESBALLOC
127fcf3ce44SJohn Forte 
128fcf3ce44SJohn Forte /*
129fcf3ce44SJohn Forte  * Function prototypes
130fcf3ce44SJohn Forte  */
131fcf3ce44SJohn Forte 
132fcf3ce44SJohn Forte /* standard loadable modules entry points */
133fcf3ce44SJohn Forte static int	fcip_attach(dev_info_t *, ddi_attach_cmd_t);
134fcf3ce44SJohn Forte static int 	fcip_detach(dev_info_t *, ddi_detach_cmd_t);
135fcf3ce44SJohn Forte static void 	fcip_dodetach(struct fcipstr *slp);
136fcf3ce44SJohn Forte static int fcip_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd,
137fcf3ce44SJohn Forte     void *arg, void **result);
138fcf3ce44SJohn Forte 
139fcf3ce44SJohn Forte 
140fcf3ce44SJohn Forte /* streams specific */
141fcf3ce44SJohn Forte static void fcip_setipq(struct fcip *fptr);
142fcf3ce44SJohn Forte static int fcip_wput(queue_t *, mblk_t *);
143fcf3ce44SJohn Forte static int fcip_wsrv(queue_t *);
144fcf3ce44SJohn Forte static void fcip_proto(queue_t *, mblk_t *);
145fcf3ce44SJohn Forte static void fcip_ioctl(queue_t *, mblk_t *);
146fcf3ce44SJohn Forte static int fcip_open(queue_t *wq, dev_t *devp, int flag,
147fcf3ce44SJohn Forte 		int sflag, cred_t *credp);
1485e1743f0SToomas Soome static int fcip_close(queue_t *rq, int flag, cred_t *credp);
149fcf3ce44SJohn Forte static int fcip_start(queue_t *wq, mblk_t *mp, struct fcip *fptr,
150fcf3ce44SJohn Forte     struct fcip_dest *fdestp, int flags);
151fcf3ce44SJohn Forte static void fcip_sendup(struct fcip *fptr, mblk_t *mp,
152fcf3ce44SJohn Forte     struct fcipstr *(*acceptfunc)());
153fcf3ce44SJohn Forte static struct fcipstr *fcip_accept(struct fcipstr *slp, struct fcip *fptr,
154fcf3ce44SJohn Forte     int type, la_wwn_t *dhostp);
155fcf3ce44SJohn Forte static mblk_t *fcip_addudind(struct fcip *fptr, mblk_t *mp,
156fcf3ce44SJohn Forte     fcph_network_hdr_t *nhdr, int type);
157fcf3ce44SJohn Forte static int fcip_setup_mac_addr(struct fcip *fptr);
158fcf3ce44SJohn Forte static void fcip_kstat_init(struct fcip *fptr);
159fcf3ce44SJohn Forte static int fcip_stat_update(kstat_t *, int);
160fcf3ce44SJohn Forte 
161fcf3ce44SJohn Forte 
162fcf3ce44SJohn Forte /* dlpi specific */
163fcf3ce44SJohn Forte static void fcip_spareq(queue_t *wq, mblk_t *mp);
164fcf3ce44SJohn Forte static void fcip_pareq(queue_t *wq, mblk_t *mp);
165fcf3ce44SJohn Forte static void fcip_ubreq(queue_t *wq, mblk_t *mp);
166fcf3ce44SJohn Forte static void fcip_breq(queue_t *wq, mblk_t *mp);
167fcf3ce44SJohn Forte static void fcip_dreq(queue_t *wq, mblk_t *mp);
168fcf3ce44SJohn Forte static void fcip_areq(queue_t *wq, mblk_t *mp);
169fcf3ce44SJohn Forte static void fcip_udreq(queue_t *wq, mblk_t *mp);
170fcf3ce44SJohn Forte static void fcip_ireq(queue_t *wq, mblk_t *mp);
171fcf3ce44SJohn Forte static void fcip_dl_ioc_hdr_info(queue_t *wq, mblk_t *mp);
172fcf3ce44SJohn Forte 
173fcf3ce44SJohn Forte 
174fcf3ce44SJohn Forte /* solaris sundry, DR/CPR etc */
175fcf3ce44SJohn Forte static int fcip_cache_constructor(void *buf, void *arg, int size);
176fcf3ce44SJohn Forte static void fcip_cache_destructor(void *buf, void *size);
177fcf3ce44SJohn Forte static int fcip_handle_suspend(fcip_port_info_t *fport, fc_detach_cmd_t cmd);
178fcf3ce44SJohn Forte static int fcip_handle_resume(fcip_port_info_t *fport,
179fcf3ce44SJohn Forte     fc_ulp_port_info_t *port_info, fc_attach_cmd_t cmd);
180fcf3ce44SJohn Forte static fcip_port_info_t *fcip_softstate_free(fcip_port_info_t *fport);
181fcf3ce44SJohn Forte static int fcip_port_attach_handler(struct fcip *fptr);
182fcf3ce44SJohn Forte 
183fcf3ce44SJohn Forte 
184fcf3ce44SJohn Forte /*
185fcf3ce44SJohn Forte  * ulp - transport interface function prototypes
186fcf3ce44SJohn Forte  */
187fcf3ce44SJohn Forte static int fcip_port_attach(opaque_t ulp_handle, fc_ulp_port_info_t *,
188fcf3ce44SJohn Forte     fc_attach_cmd_t cmd, uint32_t sid);
189fcf3ce44SJohn Forte static int fcip_port_detach(opaque_t ulp_handle, fc_ulp_port_info_t *,
190fcf3ce44SJohn Forte     fc_detach_cmd_t cmd);
191fcf3ce44SJohn Forte static int fcip_port_ioctl(opaque_t ulp_handle,  opaque_t port_handle,
192fcf3ce44SJohn Forte     dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp, int *rval,
193fcf3ce44SJohn Forte     uint32_t claimed);
194fcf3ce44SJohn Forte static void fcip_statec_cb(opaque_t ulp_handle, opaque_t phandle,
195fcf3ce44SJohn Forte     uint32_t port_state, uint32_t port_top, fc_portmap_t changelist[],
196fcf3ce44SJohn Forte     uint32_t listlen, uint32_t sid);
197fcf3ce44SJohn Forte static int fcip_els_cb(opaque_t ulp_handle, opaque_t phandle,
198fcf3ce44SJohn Forte     fc_unsol_buf_t *buf, uint32_t claimed);
199fcf3ce44SJohn Forte static int fcip_data_cb(opaque_t ulp_handle, opaque_t phandle,
200fcf3ce44SJohn Forte     fc_unsol_buf_t *payload, uint32_t claimed);
201fcf3ce44SJohn Forte 
202fcf3ce44SJohn Forte 
203fcf3ce44SJohn Forte /* Routing table specific */
204fcf3ce44SJohn Forte static void fcip_handle_topology(struct fcip *fptr);
205fcf3ce44SJohn Forte static int fcip_init_port(struct fcip *fptr);
206fcf3ce44SJohn Forte struct fcip_routing_table *fcip_lookup_rtable(struct fcip *fptr,
207fcf3ce44SJohn Forte     la_wwn_t *pwwn, int matchflag);
208fcf3ce44SJohn Forte static void fcip_rt_update(struct fcip *fptr, fc_portmap_t *devlist,
209fcf3ce44SJohn Forte     uint32_t listlen);
210fcf3ce44SJohn Forte static void fcip_rt_flush(struct fcip *fptr);
211fcf3ce44SJohn Forte static void fcip_rte_remove_deferred(void *arg);
212fcf3ce44SJohn Forte static int fcip_do_plogi(struct fcip *fptr, struct fcip_routing_table *frp);
213fcf3ce44SJohn Forte 
214fcf3ce44SJohn Forte 
215fcf3ce44SJohn Forte /* dest table specific */
216fcf3ce44SJohn Forte static struct fcip_dest *fcip_get_dest(struct fcip *fptr,
217fcf3ce44SJohn Forte     la_wwn_t *dlphys);
218fcf3ce44SJohn Forte static struct fcip_dest *fcip_add_dest(struct fcip *fptr,
219fcf3ce44SJohn Forte     struct fcip_routing_table *frp);
220fcf3ce44SJohn Forte static int fcip_dest_add_broadcast_entry(struct fcip *fptr, int new_flag);
221fcf3ce44SJohn Forte static uint32_t fcip_get_broadcast_did(struct fcip *fptr);
222fcf3ce44SJohn Forte static void fcip_cleanup_dest(struct fcip *fptr);
223fcf3ce44SJohn Forte 
224fcf3ce44SJohn Forte 
225fcf3ce44SJohn Forte /* helper functions */
226fcf3ce44SJohn Forte static fcip_port_info_t *fcip_get_port(opaque_t phandle);
227fcf3ce44SJohn Forte static int fcip_wwn_compare(la_wwn_t *wwn1, la_wwn_t *wwn2, int flag);
228fcf3ce44SJohn Forte static void fcip_ether_to_str(struct ether_addr *e, caddr_t s);
229fcf3ce44SJohn Forte static int fcip_port_get_num_pkts(struct fcip *fptr);
230fcf3ce44SJohn Forte static int fcip_check_port_busy(struct fcip *fptr);
231fcf3ce44SJohn Forte static void fcip_check_remove_minor_node(void);
232fcf3ce44SJohn Forte static int fcip_set_wwn(la_wwn_t *pwwn);
233fcf3ce44SJohn Forte static int fcip_plogi_in_progress(struct fcip *fptr);
234fcf3ce44SJohn Forte static int fcip_check_port_exists(struct fcip *fptr);
235fcf3ce44SJohn Forte static int fcip_is_supported_fc_topology(int fc_topology);
236fcf3ce44SJohn Forte 
237fcf3ce44SJohn Forte 
238fcf3ce44SJohn Forte /* pkt specific */
239fcf3ce44SJohn Forte static fcip_pkt_t *fcip_pkt_alloc(struct fcip *fptr, mblk_t *bp,
240fcf3ce44SJohn Forte     int flags, int datalen);
241fcf3ce44SJohn Forte static void fcip_pkt_free(struct fcip_pkt *fcip_pkt, int flags);
242fcf3ce44SJohn Forte static fcip_pkt_t *fcip_ipkt_alloc(struct fcip *fptr, int cmdlen,
243fcf3ce44SJohn Forte     int resplen, opaque_t pd, int flags);
244fcf3ce44SJohn Forte static void fcip_ipkt_free(fcip_pkt_t *fcip_pkt);
245fcf3ce44SJohn Forte static void fcip_ipkt_callback(fc_packet_t *fc_pkt);
246fcf3ce44SJohn Forte static void fcip_free_pkt_dma(fcip_pkt_t *fcip_pkt);
247fcf3ce44SJohn Forte static void fcip_pkt_callback(fc_packet_t *fc_pkt);
248fcf3ce44SJohn Forte static void fcip_init_unicast_pkt(fcip_pkt_t *fcip_pkt, fc_portid_t sid,
249fcf3ce44SJohn Forte     fc_portid_t did, void (*comp) ());
250fcf3ce44SJohn Forte static int fcip_transport(fcip_pkt_t *fcip_pkt);
251fcf3ce44SJohn Forte static void fcip_pkt_timeout(void *arg);
252fcf3ce44SJohn Forte static void fcip_timeout(void *arg);
253fcf3ce44SJohn Forte static void fcip_fdestp_enqueue_pkt(struct fcip_dest *fdestp,
254fcf3ce44SJohn Forte     fcip_pkt_t *fcip_pkt);
255fcf3ce44SJohn Forte static int fcip_fdestp_dequeue_pkt(struct fcip_dest *fdestp,
256fcf3ce44SJohn Forte     fcip_pkt_t *fcip_pkt);
257fcf3ce44SJohn Forte static int fcip_sendup_constructor(void *buf, void *arg, int flags);
258fcf3ce44SJohn Forte static void fcip_sendup_thr(void *arg);
259fcf3ce44SJohn Forte static int fcip_sendup_alloc_enque(struct fcip *ftpr, mblk_t *mp,
260fcf3ce44SJohn Forte     struct fcipstr *(*f)());
261fcf3ce44SJohn Forte 
262fcf3ce44SJohn Forte /*
263fcf3ce44SJohn Forte  * zero copy inbound data handling
264fcf3ce44SJohn Forte  */
265fcf3ce44SJohn Forte #ifdef FCIP_ESBALLOC
266fcf3ce44SJohn Forte static void fcip_ubfree(char *arg);
267fcf3ce44SJohn Forte #endif /* FCIP_ESBALLOC */
268fcf3ce44SJohn Forte 
269fcf3ce44SJohn Forte #if !defined(FCIP_ESBALLOC)
270fcf3ce44SJohn Forte static void *fcip_allocb(size_t size, uint_t pri);
271fcf3ce44SJohn Forte #endif
272fcf3ce44SJohn Forte 
273fcf3ce44SJohn Forte 
274fcf3ce44SJohn Forte /* FCIP FARP support functions */
275fcf3ce44SJohn Forte static struct fcip_dest *fcip_do_farp(struct fcip *fptr, la_wwn_t *pwwn,
276fcf3ce44SJohn Forte     char *ip_addr, size_t ip_addr_len, int flags);
277fcf3ce44SJohn Forte static void fcip_init_broadcast_pkt(fcip_pkt_t *fcip_pkt, void (*comp) (),
278fcf3ce44SJohn Forte     int is_els);
279fcf3ce44SJohn Forte static int fcip_handle_farp_request(struct fcip *fptr, la_els_farp_t *fcmd);
280fcf3ce44SJohn Forte static int fcip_handle_farp_response(struct fcip *fptr, la_els_farp_t *fcmd);
281fcf3ce44SJohn Forte static void fcip_cache_arp_broadcast(struct fcip *ftpr, fc_unsol_buf_t *buf);
282fcf3ce44SJohn Forte static void fcip_port_ns(void *arg);
283fcf3ce44SJohn Forte 
284fcf3ce44SJohn Forte #ifdef DEBUG
285fcf3ce44SJohn Forte 
286fcf3ce44SJohn Forte #include <sys/debug.h>
287fcf3ce44SJohn Forte 
288fcf3ce44SJohn Forte #define	FCIP_DEBUG_DEFAULT	0x1
289fcf3ce44SJohn Forte #define	FCIP_DEBUG_ATTACH	0x2
290fcf3ce44SJohn Forte #define	FCIP_DEBUG_INIT		0x4
291fcf3ce44SJohn Forte #define	FCIP_DEBUG_DETACH	0x8
292fcf3ce44SJohn Forte #define	FCIP_DEBUG_DLPI		0x10
293fcf3ce44SJohn Forte #define	FCIP_DEBUG_ELS		0x20
294fcf3ce44SJohn Forte #define	FCIP_DEBUG_DOWNSTREAM	0x40
295fcf3ce44SJohn Forte #define	FCIP_DEBUG_UPSTREAM	0x80
296fcf3ce44SJohn Forte #define	FCIP_DEBUG_MISC		0x100
297fcf3ce44SJohn Forte 
301fcf3ce44SJohn Forte 
302fcf3ce44SJohn Forte static int fcip_debug = FCIP_DEBUG_DEFAULT;
303fcf3ce44SJohn Forte 
304fcf3ce44SJohn Forte #define	FCIP_DEBUG(level, args)	\
305fcf3ce44SJohn Forte 	if (fcip_debug & (level))	cmn_err args;
306fcf3ce44SJohn Forte 
307fcf3ce44SJohn Forte #else	/* DEBUG */
308fcf3ce44SJohn Forte 
309fcf3ce44SJohn Forte #define	FCIP_DEBUG(level, args)		/* do nothing */
310fcf3ce44SJohn Forte 
311fcf3ce44SJohn Forte #endif	/* DEBUG */
312fcf3ce44SJohn Forte 
313fcf3ce44SJohn Forte #define	KIOIP	KSTAT_INTR_PTR(fcip->fcip_intrstats)
314fcf3ce44SJohn Forte 
315fcf3ce44SJohn Forte /*
316fcf3ce44SJohn Forte  * Endian independent ethernet to WWN copy
317fcf3ce44SJohn Forte  */
318fcf3ce44SJohn Forte #define	ether_to_wwn(E, W)	\
319fcf3ce44SJohn Forte 	bzero((void *)(W), sizeof (la_wwn_t)); \
320fcf3ce44SJohn Forte 	bcopy((void *)(E), (void *)&((W)->raw_wwn[2]), ETHERADDRL); \
321fcf3ce44SJohn Forte 	(W)->raw_wwn[0] |= 0x10
322fcf3ce44SJohn Forte 
323fcf3ce44SJohn Forte /*
324fcf3ce44SJohn Forte  * wwn_to_ether : Endian independent, copies a WWN to struct ether_addr.
325fcf3ce44SJohn Forte  * The args to the macro are pointers to WWN and ether_addr structures
326fcf3ce44SJohn Forte  */
327fcf3ce44SJohn Forte #define	wwn_to_ether(W, E)	\
328fcf3ce44SJohn Forte 	bcopy((void *)&((W)->raw_wwn[2]), (void *)E, ETHERADDRL)
329fcf3ce44SJohn Forte 
330fcf3ce44SJohn Forte /*
331fcf3ce44SJohn Forte  * The module_info structure contains identification and limit values.
332fcf3ce44SJohn Forte  * All queues associated with a certain driver share the same module_info
333fcf3ce44SJohn Forte  * structures. This structure defines the characteristics of that driver/
334fcf3ce44SJohn Forte  * module's queues. The module name must be unique. The max and min packet
335fcf3ce44SJohn Forte  * sizes limit the no. of characters in M_DATA messages. The Hi and Lo
336fcf3ce44SJohn Forte  * water marks are for flow control when a module has a service procedure.
337fcf3ce44SJohn Forte  */
338fcf3ce44SJohn Forte static struct module_info	fcipminfo = {
339fcf3ce44SJohn Forte 	FCIPIDNUM,	/* mi_idnum : Module ID num */
340fcf3ce44SJohn Forte 	FCIPNAME, 	/* mi_idname: Module Name */
341fcf3ce44SJohn Forte 	FCIPMINPSZ,	/* mi_minpsz: Min packet size */
342fcf3ce44SJohn Forte 	FCIPMAXPSZ,	/* mi_maxpsz: Max packet size */
343fcf3ce44SJohn Forte 	FCIPHIWAT,	/* mi_hiwat : High water mark */
344fcf3ce44SJohn Forte 	FCIPLOWAT	/* mi_lowat : Low water mark */
345fcf3ce44SJohn Forte };
346fcf3ce44SJohn Forte 
347fcf3ce44SJohn Forte /*
348fcf3ce44SJohn Forte  * The qinit structres contain the module put, service. open and close
349fcf3ce44SJohn Forte  * procedure pointers. All modules and drivers with the same streamtab
350fcf3ce44SJohn Forte  * file (i.e same fmodsw or cdevsw entry points) point to the same
351fcf3ce44SJohn Forte  * upstream (read) and downstream (write) qinit structs.
352fcf3ce44SJohn Forte  */
353fcf3ce44SJohn Forte static struct qinit	fcip_rinit = {
354fcf3ce44SJohn Forte 	NULL,		/* qi_putp */
355fcf3ce44SJohn Forte 	NULL,		/* qi_srvp */
356fcf3ce44SJohn Forte 	fcip_open,	/* qi_qopen */
357fcf3ce44SJohn Forte 	fcip_close,	/* qi_qclose */
358fcf3ce44SJohn Forte 	NULL,		/* qi_qadmin */
359fcf3ce44SJohn Forte 	&fcipminfo,	/* qi_minfo */
360fcf3ce44SJohn Forte 	NULL		/* qi_mstat */
361fcf3ce44SJohn Forte };
362fcf3ce44SJohn Forte 
363fcf3ce44SJohn Forte static struct qinit	fcip_winit = {
364fcf3ce44SJohn Forte 	fcip_wput,	/* qi_putp */
365fcf3ce44SJohn Forte 	fcip_wsrv,	/* qi_srvp */
366fcf3ce44SJohn Forte 	NULL,		/* qi_qopen */
367fcf3ce44SJohn Forte 	NULL,		/* qi_qclose */
368fcf3ce44SJohn Forte 	NULL,		/* qi_qadmin */
369fcf3ce44SJohn Forte 	&fcipminfo,	/* qi_minfo */
370fcf3ce44SJohn Forte 	NULL		/* qi_mstat */
371fcf3ce44SJohn Forte };
372fcf3ce44SJohn Forte 
373fcf3ce44SJohn Forte /*
374fcf3ce44SJohn Forte  * streamtab contains pointers to the read and write qinit structures
375fcf3ce44SJohn Forte  */
376fcf3ce44SJohn Forte 
377fcf3ce44SJohn Forte static struct streamtab fcip_info = {
378fcf3ce44SJohn Forte 	&fcip_rinit,	/* st_rdinit */
379fcf3ce44SJohn Forte 	&fcip_winit,	/* st_wrinit */
380fcf3ce44SJohn Forte 	NULL,		/* st_muxrinit */
381fcf3ce44SJohn Forte 	NULL,		/* st_muxwrinit */
382fcf3ce44SJohn Forte };
383fcf3ce44SJohn Forte 
384fcf3ce44SJohn Forte static struct cb_ops  fcip_cb_ops = {
385fcf3ce44SJohn Forte 	nodev,				/* open */
386fcf3ce44SJohn Forte 	nodev,				/* close */
387fcf3ce44SJohn Forte 	nodev,				/* strategy */
388fcf3ce44SJohn Forte 	nodev,				/* print */
389fcf3ce44SJohn Forte 	nodev,				/* dump */
390fcf3ce44SJohn Forte 	nodev,				/* read */
391fcf3ce44SJohn Forte 	nodev,				/* write */
392fcf3ce44SJohn Forte 	nodev,				/* ioctl */
393fcf3ce44SJohn Forte 	nodev,				/* devmap */
394fcf3ce44SJohn Forte 	nodev,				/* mmap */
395fcf3ce44SJohn Forte 	nodev,				/* segmap */
396fcf3ce44SJohn Forte 	nochpoll,			/* poll */
397fcf3ce44SJohn Forte 	ddi_prop_op,			/* cb_prop_op */
398fcf3ce44SJohn Forte 	&fcip_info,			/* streamtab  */
399fcf3ce44SJohn Forte 	D_MP | D_HOTPLUG,		/* Driver compatibility flag */
400fcf3ce44SJohn Forte 	CB_REV,				/* rev */
401fcf3ce44SJohn Forte 	nodev,				/* int (*cb_aread)() */
402fcf3ce44SJohn Forte 	nodev				/* int (*cb_awrite)() */
403fcf3ce44SJohn Forte };
404fcf3ce44SJohn Forte 
405fcf3ce44SJohn Forte /*
406fcf3ce44SJohn Forte  * autoconfiguration routines.
407fcf3ce44SJohn Forte  */
408fcf3ce44SJohn Forte static struct dev_ops fcip_ops = {
409fcf3ce44SJohn Forte 	DEVO_REV,		/* devo_rev, */
410fcf3ce44SJohn Forte 	0,			/* refcnt  */
411fcf3ce44SJohn Forte 	fcip_getinfo,		/* info */
412fcf3ce44SJohn Forte 	nulldev,		/* identify */
413fcf3ce44SJohn Forte 	nulldev,		/* probe */
414fcf3ce44SJohn Forte 	fcip_attach,		/* attach */
415fcf3ce44SJohn Forte 	fcip_detach,		/* detach */
416fcf3ce44SJohn Forte 	nodev,			/* RESET */
417fcf3ce44SJohn Forte 	&fcip_cb_ops,		/* driver operations */
418fcf3ce44SJohn Forte 	NULL,			/* bus operations */
419fcf3ce44SJohn Forte 	ddi_power		/* power management */
420fcf3ce44SJohn Forte };
421fcf3ce44SJohn Forte 
422fcf3ce44SJohn Forte #define	FCIP_VERSION	"1.61"
423fcf3ce44SJohn Forte #define	FCIP_NAME	"SunFC FCIP v" FCIP_VERSION
424fcf3ce44SJohn Forte 
425fcf3ce44SJohn Forte #define	PORT_DRIVER	"fp"
426fcf3ce44SJohn Forte 
427fcf3ce44SJohn Forte #define	GETSTRUCT(struct, number)	\
428fcf3ce44SJohn Forte 	((struct *)kmem_zalloc((size_t)(sizeof (struct) * (number)), \
429fcf3ce44SJohn Forte 		KM_SLEEP))
430fcf3ce44SJohn Forte 
431fcf3ce44SJohn Forte static struct modldrv modldrv = {
432fcf3ce44SJohn Forte 	&mod_driverops,			/* Type of module - driver */
433fcf3ce44SJohn Forte 	FCIP_NAME,			/* Name of module */
434fcf3ce44SJohn Forte 	&fcip_ops,			/* driver ops */
435fcf3ce44SJohn Forte };
436fcf3ce44SJohn Forte 
437fcf3ce44SJohn Forte static struct modlinkage modlinkage = {
438fcf3ce44SJohn Forte 	MODREV_1, (void *)&modldrv, NULL
439fcf3ce44SJohn Forte };
440fcf3ce44SJohn Forte 
441fcf3ce44SJohn Forte 
442fcf3ce44SJohn Forte /*
443fcf3ce44SJohn Forte  * Now for some global statics
444fcf3ce44SJohn Forte  */
445fcf3ce44SJohn Forte static uint32_t	fcip_ub_nbufs = FCIP_UB_NBUFS;
446fcf3ce44SJohn Forte static uint32_t fcip_ub_size = FCIP_UB_SIZE;
447fcf3ce44SJohn Forte static int fcip_pkt_ttl_ticks = FCIP_PKT_TTL;
448fcf3ce44SJohn Forte static int fcip_tick_incr = 1;
449fcf3ce44SJohn Forte static int fcip_wait_cmds = FCIP_WAIT_CMDS;
450fcf3ce44SJohn Forte static int fcip_num_attaching = 0;
451fcf3ce44SJohn Forte static int fcip_port_attach_pending = 0;
452fcf3ce44SJohn Forte static int fcip_create_nodes_on_demand = 1;	/* keep it similar to fcp */
453fcf3ce44SJohn Forte static int fcip_cache_on_arp_broadcast = 0;
454fcf3ce44SJohn Forte static int fcip_farp_supported = 0;
455fcf3ce44SJohn Forte static int fcip_minor_node_created = 0;
456fcf3ce44SJohn Forte 
457fcf3ce44SJohn Forte /*
458fcf3ce44SJohn Forte  * Supported FCAs
459fcf3ce44SJohn Forte  */
460fcf3ce44SJohn Forte #define	QLC_PORT_1_ID_BITS		0x100
461fcf3ce44SJohn Forte #define	QLC_PORT_2_ID_BITS		0x101
462fcf3ce44SJohn Forte #define	QLC_PORT_NAA			0x2
463fcf3ce44SJohn Forte #define	QLC_MODULE_NAME			"qlc"
464fcf3ce44SJohn Forte #define	IS_QLC_PORT(port_dip)		\
465fcf3ce44SJohn Forte 			(strcmp(ddi_driver_name(ddi_get_parent((port_dip))),\
466fcf3ce44SJohn Forte 			QLC_MODULE_NAME) == 0)
467fcf3ce44SJohn Forte 
468fcf3ce44SJohn Forte 
469fcf3ce44SJohn Forte /*
470fcf3ce44SJohn Forte  * fcip softstate structures head.
471fcf3ce44SJohn Forte  */
472fcf3ce44SJohn Forte 
473fcf3ce44SJohn Forte static void *fcip_softp = NULL;
474fcf3ce44SJohn Forte 
475fcf3ce44SJohn Forte /*
476fcf3ce44SJohn Forte  * linked list of active (inuse) driver streams
477fcf3ce44SJohn Forte  */
478fcf3ce44SJohn Forte 
479fcf3ce44SJohn Forte static int fcip_num_instances = 0;
480fcf3ce44SJohn Forte static dev_info_t *fcip_module_dip = (dev_info_t *)0;
481fcf3ce44SJohn Forte 
482fcf3ce44SJohn Forte 
483fcf3ce44SJohn Forte /*
484fcf3ce44SJohn Forte  * Ethernet broadcast address: Broadcast addressing in IP over fibre
485fcf3ce44SJohn Forte  * channel should be the IEEE ULA (also the low 6 bytes of the Port WWN).
486fcf3ce44SJohn Forte  *
487fcf3ce44SJohn Forte  * The broadcast addressing varies for differing topologies a node may be in:
488fcf3ce44SJohn Forte  *	- On a private loop the ARP broadcast is a class 3 sequence sent
489fcf3ce44SJohn Forte  *	  using OPNfr (Open Broadcast Replicate primitive) followed by
490fcf3ce44SJohn Forte  *	  the ARP frame to D_ID 0xFFFFFF
491fcf3ce44SJohn Forte  *
492fcf3ce44SJohn Forte  *	- On a public Loop the broadcast sequence is sent to AL_PA 0x00
493fcf3ce44SJohn Forte  *	  (no OPNfr primitive).
494fcf3ce44SJohn Forte  *
495fcf3ce44SJohn Forte  *	- For direct attach and point to point topologies we just send
496fcf3ce44SJohn Forte  *	  the frame to D_ID 0xFFFFFF
497fcf3ce44SJohn Forte  *
498fcf3ce44SJohn Forte  * For public loop the handling would probably be different - for now
499fcf3ce44SJohn Forte  * I'll just declare this struct - It can be deleted if not necessary.
500fcf3ce44SJohn Forte  *
501fcf3ce44SJohn Forte  */
502fcf3ce44SJohn Forte 
503fcf3ce44SJohn Forte 
504fcf3ce44SJohn Forte /*
505fcf3ce44SJohn Forte  * DL_INFO_ACK template for the fcip module. The dl_info_ack_t structure is
506fcf3ce44SJohn Forte  * returned as a part of an  DL_INFO_ACK message which is a M_PCPROTO message
507fcf3ce44SJohn Forte  * returned in response to a DL_INFO_REQ message sent to us from a DLS user
508fcf3ce44SJohn Forte  * Let us fake an ether header as much as possible.
509fcf3ce44SJohn Forte  *
510fcf3ce44SJohn Forte  * dl_addr_length is the Provider's DLSAP addr which is SAP addr +
511fcf3ce44SJohn Forte  *                Physical addr of the provider. We set this to
512fcf3ce44SJohn Forte  *                ushort_t + sizeof (la_wwn_t) for Fibre Channel ports.
513fcf3ce44SJohn Forte  * dl_mac_type    Lets just use DL_ETHER - we can try using DL_IPFC, a new
514fcf3ce44SJohn Forte  *		  dlpi.h define later.
515fcf3ce44SJohn Forte  * dl_sap_length  -2 indicating the SAP address follows the Physical addr
516fcf3ce44SJohn Forte  *		  component in the DLSAP addr.
517fcf3ce44SJohn Forte  * dl_service_mode: DLCLDS - connectionless data link service.
518fcf3ce44SJohn Forte  *
519fcf3ce44SJohn Forte  */
520fcf3ce44SJohn Forte 
521fcf3ce44SJohn Forte static dl_info_ack_t fcip_infoack = {
522fcf3ce44SJohn Forte 	DL_INFO_ACK,				/* dl_primitive */
523fcf3ce44SJohn Forte 	FCIPMTU,				/* dl_max_sdu */
524fcf3ce44SJohn Forte 	0,					/* dl_min_sdu */
525fcf3ce44SJohn Forte 	FCIPADDRL,				/* dl_addr_length */
526fcf3ce44SJohn Forte 	DL_ETHER,				/* dl_mac_type */
527fcf3ce44SJohn Forte 	0,					/* dl_reserved */
528fcf3ce44SJohn Forte 	0,					/* dl_current_state */
529fcf3ce44SJohn Forte 	-2,					/* dl_sap_length */
530fcf3ce44SJohn Forte 	DL_CLDLS,				/* dl_service_mode */
531fcf3ce44SJohn Forte 	0,					/* dl_qos_length */
532fcf3ce44SJohn Forte 	0,					/* dl_qos_offset */
533fcf3ce44SJohn Forte 	0,					/* dl_range_length */
534fcf3ce44SJohn Forte 	0,					/* dl_range_offset */
535fcf3ce44SJohn Forte 	DL_STYLE2,				/* dl_provider_style */
536fcf3ce44SJohn Forte 	sizeof (dl_info_ack_t),			/* dl_addr_offset */
537fcf3ce44SJohn Forte 	DL_VERSION_2,				/* dl_version */
538fcf3ce44SJohn Forte 	ETHERADDRL,				/* dl_brdcst_addr_length */
539fcf3ce44SJohn Forte 	sizeof (dl_info_ack_t) + FCIPADDRL,	/* dl_brdcst_addr_offset */
540fcf3ce44SJohn Forte 	0					/* dl_growth */
541fcf3ce44SJohn Forte };
542fcf3ce44SJohn Forte 
543fcf3ce44SJohn Forte /*
544fcf3ce44SJohn Forte  * FCIP broadcast address definition.
545fcf3ce44SJohn Forte  */
546fcf3ce44SJohn Forte static	struct ether_addr	fcipnhbroadcastaddr = {
547fcf3ce44SJohn Forte 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff
548fcf3ce44SJohn Forte };
549fcf3ce44SJohn Forte 
550fcf3ce44SJohn Forte /*
551fcf3ce44SJohn Forte  * RFC2625 requires the broadcast ARP address in the ARP data payload to
552fcf3ce44SJohn Forte  * be set to 0x00 00 00 00 00 00 for ARP broadcast packets
553fcf3ce44SJohn Forte  */
554fcf3ce44SJohn Forte static	struct ether_addr	fcip_arpbroadcast_addr = {
555fcf3ce44SJohn Forte 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00
556fcf3ce44SJohn Forte };
557fcf3ce44SJohn Forte 
558fcf3ce44SJohn Forte 
559fcf3ce44SJohn Forte #define	ether_bcopy(src, dest)	bcopy((src), (dest), ETHERADDRL);
560fcf3ce44SJohn Forte 
561fcf3ce44SJohn Forte /*
562fcf3ce44SJohn Forte  * global kernel locks
563fcf3ce44SJohn Forte  */
564fcf3ce44SJohn Forte static kcondvar_t	fcip_global_cv;
565fcf3ce44SJohn Forte static kmutex_t		fcip_global_mutex;
566fcf3ce44SJohn Forte 
567fcf3ce44SJohn Forte /*
568fcf3ce44SJohn Forte  * fctl external defines
569fcf3ce44SJohn Forte  */
570fcf3ce44SJohn Forte extern int fc_ulp_add(fc_ulp_modinfo_t *);
571fcf3ce44SJohn Forte 
572fcf3ce44SJohn Forte /*
573fcf3ce44SJohn Forte  * fctl data structures
574fcf3ce44SJohn Forte  */
575fcf3ce44SJohn Forte 
576fcf3ce44SJohn Forte #define	FCIP_REV	0x07
577fcf3ce44SJohn Forte 
578fcf3ce44SJohn Forte /* linked list of port info structures */
579fcf3ce44SJohn Forte static fcip_port_info_t *fcip_port_head = NULL;
580fcf3ce44SJohn Forte 
581fcf3ce44SJohn Forte /* linked list of fcip structures */
582fcf3ce44SJohn Forte static struct fcipstr	*fcipstrup = NULL;
583fcf3ce44SJohn Forte static krwlock_t	fcipstruplock;
584fcf3ce44SJohn Forte 
585fcf3ce44SJohn Forte 
586fcf3ce44SJohn Forte /*
587fcf3ce44SJohn Forte  * Module information structure. This structure gives the FC Transport modules
588fcf3ce44SJohn Forte  * information about an ULP that registers with it.
589fcf3ce44SJohn Forte  */
590fcf3ce44SJohn Forte static fc_ulp_modinfo_t	fcip_modinfo = {
591fcf3ce44SJohn Forte 	0,			/* for xref checks? */
592fcf3ce44SJohn Forte 	FCTL_ULP_MODREV_4,	/* FCIP revision */
593fcf3ce44SJohn Forte 	FC_TYPE_IS8802_SNAP,	/* type 5 for SNAP encapsulated datagrams */
594fcf3ce44SJohn Forte 	FCIP_NAME,		/* module name as in the modldrv struct */
595fcf3ce44SJohn Forte 	0x0,			/* get all statec callbacks for now */
596fcf3ce44SJohn Forte 	fcip_port_attach,	/* port attach callback */
597fcf3ce44SJohn Forte 	fcip_port_detach,	/* port detach callback */
598fcf3ce44SJohn Forte 	fcip_port_ioctl,	/* port ioctl callback */
599fcf3ce44SJohn Forte 	fcip_els_cb,		/* els callback */
600fcf3ce44SJohn Forte 	fcip_data_cb,		/* data callback */
601fcf3ce44SJohn Forte 	fcip_statec_cb		/* state change callback */
602fcf3ce44SJohn Forte };
603fcf3ce44SJohn Forte 
604fcf3ce44SJohn Forte 
605fcf3ce44SJohn Forte /*
606fcf3ce44SJohn Forte  * Solaris 9 and up, the /kernel/drv/fp.conf file will have the following entry
607fcf3ce44SJohn Forte  *
608fcf3ce44SJohn Forte  * ddi-forceattach=1;
609fcf3ce44SJohn Forte  *
610fcf3ce44SJohn Forte  * This will ensure that fp is loaded at bootup. No additional checks are needed
611fcf3ce44SJohn Forte  */
612fcf3ce44SJohn Forte int
_init(void)613fcf3ce44SJohn Forte _init(void)
614fcf3ce44SJohn Forte {
615fcf3ce44SJohn Forte 	int	rval;
616fcf3ce44SJohn Forte 
617fcf3ce44SJohn Forte 	FCIP_TNF_LOAD();
618fcf3ce44SJohn Forte 
619fcf3ce44SJohn Forte 	/*
620fcf3ce44SJohn Forte 	 * Initialize the mutexs used by port attach and other callbacks.
621fcf3ce44SJohn Forte 	 * The transport can call back into our port_attach_callback
622fcf3ce44SJohn Forte 	 * routine even before _init() completes and bad things can happen.
623fcf3ce44SJohn Forte 	 */
624fcf3ce44SJohn Forte 	mutex_init(&fcip_global_mutex, NULL, MUTEX_DRIVER, NULL);
625fcf3ce44SJohn Forte 	cv_init(&fcip_global_cv, NULL, CV_DRIVER, NULL);
626fcf3ce44SJohn Forte 	rw_init(&fcipstruplock, NULL, RW_DRIVER, NULL);
627fcf3ce44SJohn Forte 
628fcf3ce44SJohn Forte 	mutex_enter(&fcip_global_mutex);
629fcf3ce44SJohn Forte 	fcip_port_attach_pending = 1;
630fcf3ce44SJohn Forte 	mutex_exit(&fcip_global_mutex);
631fcf3ce44SJohn Forte 
632fcf3ce44SJohn Forte 	/*
633fcf3ce44SJohn Forte 	 * Now attempt to register fcip with the transport.
634fcf3ce44SJohn Forte 	 * If fc_ulp_add fails, fcip module will not be loaded.
635fcf3ce44SJohn Forte 	 */
636fcf3ce44SJohn Forte 	rval = fc_ulp_add(&fcip_modinfo);
637fcf3ce44SJohn Forte 	if (rval != FC_SUCCESS) {
638fcf3ce44SJohn Forte 		mutex_destroy(&fcip_global_mutex);
639fcf3ce44SJohn Forte 		cv_destroy(&fcip_global_cv);
640fcf3ce44SJohn Forte 		rw_destroy(&fcipstruplock);
641fcf3ce44SJohn Forte 		switch (rval) {
642fcf3ce44SJohn Forte 		case FC_ULP_SAMEMODULE:
644fcf3ce44SJohn Forte 			    "!fcip: module is already registered with"
645fcf3ce44SJohn Forte 			    " transport"));
646fcf3ce44SJohn Forte 			rval = EEXIST;
647fcf3ce44SJohn Forte 			break;
648fcf3ce44SJohn Forte 		case FC_ULP_SAMETYPE:
650fcf3ce44SJohn Forte 			    "!fcip: Another module of the same ULP type 0x%x"
651fcf3ce44SJohn Forte 			    " is already registered with the transport",
652fcf3ce44SJohn Forte 			    fcip_modinfo.ulp_type));
653fcf3ce44SJohn Forte 			rval = EEXIST;
654fcf3ce44SJohn Forte 			break;
655fcf3ce44SJohn Forte 		case FC_BADULP:
657fcf3ce44SJohn Forte 			    "!fcip: Current fcip version 0x%x does not match"
658fcf3ce44SJohn Forte 			    " fctl version",
659fcf3ce44SJohn Forte 			    fcip_modinfo.ulp_rev));
660fcf3ce44SJohn Forte 			rval = ENODEV;
661fcf3ce44SJohn Forte 			break;
662fcf3ce44SJohn Forte 		default:
664fcf3ce44SJohn Forte 			    "!fcip: fc_ulp_add failed with status 0x%x", rval));
665fcf3ce44SJohn Forte 			rval = ENODEV;
666fcf3ce44SJohn Forte 			break;
667fcf3ce44SJohn Forte 		}
668fcf3ce44SJohn Forte 		FCIP_TNF_UNLOAD(&modlinkage);
669fcf3ce44SJohn Forte 		return (rval);
670fcf3ce44SJohn Forte 	}
671fcf3ce44SJohn Forte 
672fcf3ce44SJohn Forte 	if ((rval = ddi_soft_state_init(&fcip_softp, sizeof (struct fcip),
673fcf3ce44SJohn Forte 			FCIP_NUM_INSTANCES)) != 0) {
674fcf3ce44SJohn Forte 		mutex_destroy(&fcip_global_mutex);
675fcf3ce44SJohn Forte 		cv_destroy(&fcip_global_cv);
676fcf3ce44SJohn Forte 		rw_destroy(&fcipstruplock);
677fcf3ce44SJohn Forte 		(void) fc_ulp_remove(&fcip_modinfo);
678fcf3ce44SJohn Forte 		FCIP_TNF_UNLOAD(&modlinkage);
679fcf3ce44SJohn Forte 		return (rval);
680fcf3ce44SJohn Forte 	}
681fcf3ce44SJohn Forte 
682fcf3ce44SJohn Forte 	if ((rval = mod_install(&modlinkage)) != 0) {
683fcf3ce44SJohn Forte 		FCIP_TNF_UNLOAD(&modlinkage);
684fcf3ce44SJohn Forte 		(void) fc_ulp_remove(&fcip_modinfo);
685fcf3ce44SJohn Forte 		mutex_destroy(&fcip_global_mutex);
686fcf3ce44SJohn Forte 		cv_destroy(&fcip_global_cv);
687fcf3ce44SJohn Forte 		rw_destroy(&fcipstruplock);
688fcf3ce44SJohn Forte 		ddi_soft_state_fini(&fcip_softp);
689fcf3ce44SJohn Forte 	}
690fcf3ce44SJohn Forte 	return (rval);
691fcf3ce44SJohn Forte }
692fcf3ce44SJohn Forte 
693fcf3ce44SJohn Forte /*
694fcf3ce44SJohn Forte  * Unload the port driver if this was the only ULP loaded and then
695fcf3ce44SJohn Forte  * deregister with the transport.
696fcf3ce44SJohn Forte  */
697fcf3ce44SJohn Forte int
_fini(void)698fcf3ce44SJohn Forte _fini(void)
699fcf3ce44SJohn Forte {
700fcf3ce44SJohn Forte 	int	rval;
701fcf3ce44SJohn Forte 	int	rval1;
702fcf3ce44SJohn Forte 
703fcf3ce44SJohn Forte 	/*
704fcf3ce44SJohn Forte 	 * Do not permit the module to be unloaded before a port
705fcf3ce44SJohn Forte 	 * attach callback has happened.
706fcf3ce44SJohn Forte 	 */
707fcf3ce44SJohn Forte 	mutex_enter(&fcip_global_mutex);
708fcf3ce44SJohn Forte 	if (fcip_num_attaching || fcip_port_attach_pending) {
709fcf3ce44SJohn Forte 		mutex_exit(&fcip_global_mutex);
710fcf3ce44SJohn Forte 		return (EBUSY);
711fcf3ce44SJohn Forte 	}
712fcf3ce44SJohn Forte 	mutex_exit(&fcip_global_mutex);
713fcf3ce44SJohn Forte 
714fcf3ce44SJohn Forte 	if ((rval = mod_remove(&modlinkage)) != 0) {
715fcf3ce44SJohn Forte 		return (rval);
716fcf3ce44SJohn Forte 	}
717fcf3ce44SJohn Forte 
718fcf3ce44SJohn Forte 	/*
719fcf3ce44SJohn Forte 	 * unregister with the transport layer
720fcf3ce44SJohn Forte 	 */
721fcf3ce44SJohn Forte 	rval1 = fc_ulp_remove(&fcip_modinfo);
722fcf3ce44SJohn Forte 
723fcf3ce44SJohn Forte 	/*
724fcf3ce44SJohn Forte 	 * If the ULP was not registered with the transport, init should
725fcf3ce44SJohn Forte 	 * have failed. If transport has no knowledge of our existence
726fcf3ce44SJohn Forte 	 * we should simply bail out and succeed
727fcf3ce44SJohn Forte 	 */
728fcf3ce44SJohn Forte #ifdef DEBUG
729fcf3ce44SJohn Forte 	if (rval1 == FC_BADULP) {
731fcf3ce44SJohn Forte 		"fcip: ULP was never registered with the transport"));
732fcf3ce44SJohn Forte 		rval = ENODEV;
733fcf3ce44SJohn Forte 	} else if (rval1 == FC_BADTYPE) {
735fcf3ce44SJohn Forte 			"fcip: No ULP of this type 0x%x was registered with "
736fcf3ce44SJohn Forte 			"transport", fcip_modinfo.ulp_type));
737fcf3ce44SJohn Forte 		rval = ENODEV;
738fcf3ce44SJohn Forte 	}
739fcf3ce44SJohn Forte #endif /* DEBUG */
740fcf3ce44SJohn Forte 
741fcf3ce44SJohn Forte 	mutex_destroy(&fcip_global_mutex);
742fcf3ce44SJohn Forte 	rw_destroy(&fcipstruplock);
743fcf3ce44SJohn Forte 	cv_destroy(&fcip_global_cv);
744fcf3ce44SJohn Forte 	ddi_soft_state_fini(&fcip_softp);
745fcf3ce44SJohn Forte 
746fcf3ce44SJohn Forte 	FCIP_TNF_UNLOAD(&modlinkage);
747fcf3ce44SJohn Forte 
748fcf3ce44SJohn Forte 	return (rval);
749fcf3ce44SJohn Forte }
750fcf3ce44SJohn Forte 
751fcf3ce44SJohn Forte /*
752fcf3ce44SJohn Forte  * Info about this loadable module
753fcf3ce44SJohn Forte  */
754fcf3ce44SJohn Forte int
_info(struct modinfo * modinfop)755fcf3ce44SJohn Forte _info(struct modinfo *modinfop)
756fcf3ce44SJohn Forte {
757fcf3ce44SJohn Forte 	return (mod_info(&modlinkage, modinfop));
758fcf3ce44SJohn Forte }
759fcf3ce44SJohn Forte 
760fcf3ce44SJohn Forte /*
761fcf3ce44SJohn Forte  * The port attach callback is invoked by the port driver when a FCA
762fcf3ce44SJohn Forte  * port comes online and binds with the transport layer. The transport
763fcf3ce44SJohn Forte  * then callsback into all ULP modules registered with it. The Port attach
764fcf3ce44SJohn Forte  * call back will also provide the ULP module with the Port's WWN and S_ID
765fcf3ce44SJohn Forte  */
766fcf3ce44SJohn Forte /* ARGSUSED */
767fcf3ce44SJohn Forte static int
fcip_port_attach(opaque_t ulp_handle,fc_ulp_port_info_t * port_info,fc_attach_cmd_t cmd,uint32_t sid)768fcf3ce44SJohn Forte fcip_port_attach(opaque_t ulp_handle, fc_ulp_port_info_t *port_info,
769fcf3ce44SJohn Forte     fc_attach_cmd_t cmd, uint32_t sid)
770fcf3ce44SJohn Forte {
771fcf3ce44SJohn Forte 	int 			rval = FC_FAILURE;
772fcf3ce44SJohn Forte 	int 			instance;
773fcf3ce44SJohn Forte 	struct fcip		*fptr;
774fcf3ce44SJohn Forte 	fcip_port_info_t	*fport = NULL;
775fcf3ce44SJohn Forte 	fcip_port_info_t	*cur_fport;
776fcf3ce44SJohn Forte 	fc_portid_t		src_id;
777fcf3ce44SJohn Forte 
778fcf3ce44SJohn Forte 	switch (cmd) {
779fcf3ce44SJohn Forte 	case FC_CMD_ATTACH: {
780fcf3ce44SJohn Forte 		la_wwn_t	*ww_pn = NULL;
781fcf3ce44SJohn Forte 		/*
782fcf3ce44SJohn Forte 		 * It was determined that, as per spec, the lower 48 bits of
783fcf3ce44SJohn Forte 		 * the port-WWN will always be unique. This will make the MAC
784fcf3ce44SJohn Forte 		 * address (i.e the lower 48 bits of the WWN), that IP/ARP
785fcf3ce44SJohn Forte 		 * depend on, unique too. Hence we should be able to remove the
786fcf3ce44SJohn Forte 		 * restriction of attaching to only one of the ports of
787fcf3ce44SJohn Forte 		 * multi port FCAs.
788fcf3ce44SJohn Forte 		 *
789fcf3ce44SJohn Forte 		 * Earlier, fcip used to attach only to qlc module and fail
790fcf3ce44SJohn Forte 		 * silently for attach failures resulting from unknown FCAs or
791fcf3ce44SJohn Forte 		 * unsupported FCA ports. Now, we'll do no such checks.
792fcf3ce44SJohn Forte 		 */
793fcf3ce44SJohn Forte 		ww_pn = &port_info->port_pwwn;
794fcf3ce44SJohn Forte 
795fcf3ce44SJohn Forte 		FCIP_TNF_PROBE_2((fcip_port_attach, "fcip io", /* CSTYLED */,
796fcf3ce44SJohn Forte 			tnf_string, msg, "port id bits",
797fcf3ce44SJohn Forte 			tnf_opaque, nport_id, ww_pn->w.nport_id));
799fcf3ce44SJohn Forte 		    "port id bits: 0x%x", ww_pn->w.nport_id));
800fcf3ce44SJohn Forte 		/*
801fcf3ce44SJohn Forte 		 * A port has come online
802fcf3ce44SJohn Forte 		 */
803fcf3ce44SJohn Forte 		mutex_enter(&fcip_global_mutex);
804fcf3ce44SJohn Forte 		fcip_num_instances++;
805fcf3ce44SJohn Forte 		fcip_num_attaching++;
806fcf3ce44SJohn Forte 
807fcf3ce44SJohn Forte 		if (fcip_port_head == NULL) {
808fcf3ce44SJohn Forte 			/* OK to sleep here ? */
809fcf3ce44SJohn Forte 			fport = kmem_zalloc(sizeof (fcip_port_info_t),
810fcf3ce44SJohn Forte 						KM_NOSLEEP);
811fcf3ce44SJohn Forte 			if (fport == NULL) {
812fcf3ce44SJohn Forte 				fcip_num_instances--;
813fcf3ce44SJohn Forte 				fcip_num_attaching--;
814fcf3ce44SJohn Forte 				ASSERT(fcip_num_attaching >= 0);
815fcf3ce44SJohn Forte 				mutex_exit(&fcip_global_mutex);
816fcf3ce44SJohn Forte 				rval = FC_FAILURE;
817fcf3ce44SJohn Forte 				cmn_err(CE_WARN, "!fcip(%d): port attach "
818fcf3ce44SJohn Forte 				    "failed: alloc failed",
819fcf3ce44SJohn Forte 				    ddi_get_instance(port_info->port_dip));
820fcf3ce44SJohn Forte 				goto done;
821fcf3ce44SJohn Forte 			}
822fcf3ce44SJohn Forte 			fcip_port_head = fport;
823fcf3ce44SJohn Forte 		} else {
824fcf3ce44SJohn Forte 			/*
825fcf3ce44SJohn Forte 			 * traverse the port list and also check for
826fcf3ce44SJohn Forte 			 * duplicate port attaches - Nothing wrong in being
827fcf3ce44SJohn Forte 			 * paranoid Heh Heh.
828fcf3ce44SJohn Forte 			 */
829fcf3ce44SJohn Forte 			cur_fport = fcip_port_head;
830fcf3ce44SJohn Forte 			while (cur_fport != NULL) {
831fcf3ce44SJohn Forte 				if (cur_fport->fcipp_handle ==
832fcf3ce44SJohn Forte 				    port_info->port_handle) {
833fcf3ce44SJohn Forte 					fcip_num_instances--;
834fcf3ce44SJohn Forte 					fcip_num_attaching--;
835fcf3ce44SJohn Forte 					ASSERT(fcip_num_attaching >= 0);
836fcf3ce44SJohn Forte 					mutex_exit(&fcip_global_mutex);
837fcf3ce44SJohn Forte 					FCIP_DEBUG(FCIP_DEBUG_ATTACH, (CE_WARN,
838fcf3ce44SJohn Forte 					    "!fcip(%d): port already "
839fcf3ce44SJohn Forte 					    "attached!!", ddi_get_instance(
840fcf3ce44SJohn Forte 					    port_info->port_dip)));
841fcf3ce44SJohn Forte 					rval = FC_FAILURE;
842fcf3ce44SJohn Forte 					goto done;
843fcf3ce44SJohn Forte 				}
844fcf3ce44SJohn Forte 				cur_fport = cur_fport->fcipp_next;
845fcf3ce44SJohn Forte 			}
846fcf3ce44SJohn Forte 			fport = kmem_zalloc(sizeof (fcip_port_info_t),
847fcf3ce44SJohn Forte 						KM_NOSLEEP);
848fcf3ce44SJohn Forte 			if (fport == NULL) {
849fcf3ce44SJohn Forte 				rval = FC_FAILURE;
850fcf3ce44SJohn Forte 				fcip_num_instances--;
851fcf3ce44SJohn Forte 				fcip_num_attaching--;
852fcf3ce44SJohn Forte 				ASSERT(fcip_num_attaching >= 0);
853fcf3ce44SJohn Forte 				mutex_exit(&fcip_global_mutex);
854fcf3ce44SJohn Forte 				cmn_err(CE_WARN, "!fcip(%d): port attach "
855fcf3ce44SJohn Forte 				    "failed: alloc failed",
856fcf3ce44SJohn Forte 				    ddi_get_instance(port_info->port_dip));
857fcf3ce44SJohn Forte 				goto done;
858fcf3ce44SJohn Forte 			}
859fcf3ce44SJohn Forte 			fport->fcipp_next = fcip_port_head;
860fcf3ce44SJohn Forte 			fcip_port_head = fport;
861fcf3ce44SJohn Forte 		}
862fcf3ce44SJohn Forte 
863fcf3ce44SJohn Forte 		mutex_exit(&fcip_global_mutex);
864fcf3ce44SJohn Forte 
865fcf3ce44SJohn Forte 		/*
866fcf3ce44SJohn Forte 		 * now fill in the details about the port itself
867fcf3ce44SJohn Forte 		 */
868fcf3ce44SJohn Forte 		fport->fcipp_linkage = *port_info->port_linkage;
869fcf3ce44SJohn Forte 		fport->fcipp_handle = port_info->port_handle;
870fcf3ce44SJohn Forte 		fport->fcipp_dip = port_info->port_dip;
871fcf3ce44SJohn Forte 		fport->fcipp_topology = port_info->port_flags;
872fcf3ce44SJohn Forte 		fport->fcipp_pstate = port_info->port_state;
873fcf3ce44SJohn Forte 		fport->fcipp_naa = port_info->port_pwwn.w.naa_id;
874fcf3ce44SJohn Forte 		bcopy(&port_info->port_pwwn, &fport->fcipp_pwwn,
875fcf3ce44SJohn Forte 		    sizeof (la_wwn_t));
876fcf3ce44SJohn Forte 		bcopy(&port_info->port_nwwn, &fport->fcipp_nwwn,
877fcf3ce44SJohn Forte 		    sizeof (la_wwn_t));
878fcf3ce44SJohn Forte 		fport->fcipp_fca_pkt_size = port_info->port_fca_pkt_size;
879fcf3ce44SJohn Forte 		fport->fcipp_cmd_dma_attr = *port_info->port_cmd_dma_attr;
880fcf3ce44SJohn Forte 		fport->fcipp_resp_dma_attr = *port_info->port_resp_dma_attr;
881fcf3ce44SJohn Forte 		fport->fcipp_fca_acc_attr = *port_info->port_acc_attr;
882fcf3ce44SJohn Forte 		src_id.port_id = sid;
883fcf3ce44SJohn Forte 		src_id.priv_lilp_posit = 0;
884fcf3ce44SJohn Forte 		fport->fcipp_sid = src_id;
885fcf3ce44SJohn Forte 
886fcf3ce44SJohn Forte 		/*
887fcf3ce44SJohn Forte 		 * allocate soft state for this instance
888fcf3ce44SJohn Forte 		 */
889fcf3ce44SJohn Forte 		instance = ddi_get_instance(fport->fcipp_dip);
890fcf3ce44SJohn Forte 		if (ddi_soft_state_zalloc(fcip_softp,
891fcf3ce44SJohn Forte 		    instance) != DDI_SUCCESS) {
892fcf3ce44SJohn Forte 			rval = FC_FAILURE;
893fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "!fcip(%d): port attach failed: "
894fcf3ce44SJohn Forte 			    "soft state alloc failed", instance);
895fcf3ce44SJohn Forte 			goto failure;
896fcf3ce44SJohn Forte 		}
897fcf3ce44SJohn Forte 
898fcf3ce44SJohn Forte 		fptr = ddi_get_soft_state(fcip_softp, instance);
899fcf3ce44SJohn Forte 
900fcf3ce44SJohn Forte 		if (fptr == NULL) {
901fcf3ce44SJohn Forte 			rval = FC_FAILURE;
902fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "!fcip(%d): port attach failed: "
903fcf3ce44SJohn Forte 			    "failure to get soft state", instance);
904fcf3ce44SJohn Forte 			goto failure;
905fcf3ce44SJohn Forte 		}
906fcf3ce44SJohn Forte 
907fcf3ce44SJohn Forte 		/*
908fcf3ce44SJohn Forte 		 * initialize all mutexes and locks required for this module
909fcf3ce44SJohn Forte 		 */
910fcf3ce44SJohn Forte 		mutex_init(&fptr->fcip_mutex, NULL, MUTEX_DRIVER, NULL);
911fcf3ce44SJohn Forte 		mutex_init(&fptr->fcip_ub_mutex, NULL, MUTEX_DRIVER, NULL);
912fcf3ce44SJohn Forte 		mutex_init(&fptr->fcip_rt_mutex, NULL, MUTEX_DRIVER, NULL);
913fcf3ce44SJohn Forte 		mutex_init(&fptr->fcip_dest_mutex, NULL, MUTEX_DRIVER, NULL);
914fcf3ce44SJohn Forte 		mutex_init(&fptr->fcip_sendup_mutex, NULL, MUTEX_DRIVER, NULL);
915fcf3ce44SJohn Forte 		cv_init(&fptr->fcip_farp_cv, NULL, CV_DRIVER, NULL);
916fcf3ce44SJohn Forte 		cv_init(&fptr->fcip_sendup_cv, NULL, CV_DRIVER, NULL);
917fcf3ce44SJohn Forte 		cv_init(&fptr->fcip_ub_cv, NULL, CV_DRIVER, NULL);
918fcf3ce44SJohn Forte 
919fcf3ce44SJohn Forte 		mutex_enter(&fptr->fcip_mutex);
920fcf3ce44SJohn Forte 
921fcf3ce44SJohn Forte 		fptr->fcip_dip = fport->fcipp_dip;	/* parent's dip */
922fcf3ce44SJohn Forte 		fptr->fcip_instance = instance;
923fcf3ce44SJohn Forte 		fptr->fcip_ub_upstream = 0;
924fcf3ce44SJohn Forte 
925fcf3ce44SJohn Forte 		if (FC_PORT_STATE_MASK(port_info->port_state) ==
926fcf3ce44SJohn Forte 		    FC_STATE_ONLINE) {
927fcf3ce44SJohn Forte 			fptr->fcip_port_state = FCIP_PORT_ONLINE;
928fcf3ce44SJohn Forte 			if (fptr->fcip_flags & FCIP_LINK_DOWN) {
929fcf3ce44SJohn Forte 				fptr->fcip_flags &= ~FCIP_LINK_DOWN;
930fcf3ce44SJohn Forte 			}
931fcf3ce44SJohn Forte 		} else {
932fcf3ce44SJohn Forte 			fptr->fcip_port_state = FCIP_PORT_OFFLINE;
933fcf3ce44SJohn Forte 		}
934fcf3ce44SJohn Forte 
935fcf3ce44SJohn Forte 		fptr->fcip_flags |= FCIP_ATTACHING;
936fcf3ce44SJohn Forte 		fptr->fcip_port_info = fport;
937fcf3ce44SJohn Forte 
938fcf3ce44SJohn Forte 		/*
939fcf3ce44SJohn Forte 		 * Extract our MAC addr from our port's WWN. The lower 48
940fcf3ce44SJohn Forte 		 * bits will be our MAC address
941fcf3ce44SJohn Forte 		 */
942fcf3ce44SJohn Forte 		wwn_to_ether(&fport->fcipp_nwwn, &fptr->fcip_macaddr);
943fcf3ce44SJohn Forte 
944fcf3ce44SJohn Forte 		fport->fcipp_fcip = fptr;
945fcf3ce44SJohn Forte 
946fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_ATTACH,
947fcf3ce44SJohn Forte 		    (CE_NOTE, "fcipdest : 0x%lx, rtable : 0x%lx",
948fcf3ce44SJohn Forte 		    (long)(sizeof (fptr->fcip_dest)),
949fcf3ce44SJohn Forte 		    (long)(sizeof (fptr->fcip_rtable))));
950fcf3ce44SJohn Forte 
951fcf3ce44SJohn Forte 		bzero(fptr->fcip_dest, sizeof (fptr->fcip_dest));
952fcf3ce44SJohn Forte 		bzero(fptr->fcip_rtable, sizeof (fptr->fcip_rtable));
953fcf3ce44SJohn Forte 
954fcf3ce44SJohn Forte 		/*
955fcf3ce44SJohn Forte 		 * create a taskq to handle sundry jobs for the driver
956fcf3ce44SJohn Forte 		 * This way we can have jobs run in parallel
957fcf3ce44SJohn Forte 		 */
958fcf3ce44SJohn Forte 		fptr->fcip_tq = taskq_create("fcip_tasks",
960fcf3ce44SJohn Forte 		    FCIP_MAX_TASKS, TASKQ_PREPOPULATE);
961fcf3ce44SJohn Forte 
962fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_mutex);
963fcf3ce44SJohn Forte 
964fcf3ce44SJohn Forte 		/*
965fcf3ce44SJohn Forte 		 * create a separate thread to handle all unsolicited
966fcf3ce44SJohn Forte 		 * callback handling. This is because unsolicited_callback
967fcf3ce44SJohn Forte 		 * can happen from an interrupt context and the upstream
968fcf3ce44SJohn Forte 		 * modules can put new messages right back in the same
969fcf3ce44SJohn Forte 		 * thread context. This usually works fine, but sometimes
970fcf3ce44SJohn Forte 		 * we may have to block to obtain the dest struct entries
971fcf3ce44SJohn Forte 		 * for some remote ports.
972fcf3ce44SJohn Forte 		 */
973fcf3ce44SJohn Forte 		mutex_enter(&fptr->fcip_sendup_mutex);
974fcf3ce44SJohn Forte 		if (thread_create(NULL, DEFAULTSTKSZ,
975fcf3ce44SJohn Forte 		    (void (*)())fcip_sendup_thr, (caddr_t)fptr, 0, &p0,
976fcf3ce44SJohn Forte 		    TS_RUN, minclsyspri) == NULL) {
977fcf3ce44SJohn Forte 			mutex_exit(&fptr->fcip_sendup_mutex);
978fcf3ce44SJohn Forte 			cmn_err(CE_WARN,
979fcf3ce44SJohn Forte 			    "!unable to create fcip sendup thread for "
980fcf3ce44SJohn Forte 			    " instance: 0x%x", instance);
981fcf3ce44SJohn Forte 			rval = FC_FAILURE;
982fcf3ce44SJohn Forte 			goto done;
983fcf3ce44SJohn Forte 		}
984fcf3ce44SJohn Forte 		fptr->fcip_sendup_thr_initted = 1;
985fcf3ce44SJohn Forte 		fptr->fcip_sendup_head = fptr->fcip_sendup_tail = NULL;
986fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_sendup_mutex);
987fcf3ce44SJohn Forte 
988fcf3ce44SJohn Forte 
989fcf3ce44SJohn Forte 		/* Let the attach handler do the rest */
990fcf3ce44SJohn Forte 		if (fcip_port_attach_handler(fptr) != FC_SUCCESS) {
991fcf3ce44SJohn Forte 			/*
992fcf3ce44SJohn Forte 			 * We have already cleaned up so return
993fcf3ce44SJohn Forte 			 */
994fcf3ce44SJohn Forte 			rval = FC_FAILURE;
995fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "!fcip(%d): port attach failed",
996fcf3ce44SJohn Forte 			    instance);
997fcf3ce44SJohn Forte 			goto done;
998fcf3ce44SJohn Forte 		}
999fcf3ce44SJohn Forte 
1001fcf3ce44SJohn Forte 		    "!fcip attach for port instance (0x%x) successful",
1002fcf3ce44SJohn Forte 		    instance));
1003fcf3ce44SJohn Forte 
1004fcf3ce44SJohn Forte 		rval = FC_SUCCESS;
1005fcf3ce44SJohn Forte 		goto done;
1006fcf3ce44SJohn Forte 	}
1007fcf3ce44SJohn Forte 	case FC_CMD_POWER_UP:
1008fcf3ce44SJohn Forte 	/* FALLTHROUGH */
1009fcf3ce44SJohn Forte 	case FC_CMD_RESUME:
1010fcf3ce44SJohn Forte 		mutex_enter(&fcip_global_mutex);
1011fcf3ce44SJohn Forte 		fport = fcip_port_head;
1012fcf3ce44SJohn Forte 		while (fport != NULL) {
1013fcf3ce44SJohn Forte 			if (fport->fcipp_handle == port_info->port_handle) {
1014fcf3ce44SJohn Forte 				break;
1015fcf3ce44SJohn Forte 			}
1016fcf3ce44SJohn Forte 			fport = fport->fcipp_next;
1017fcf3ce44SJohn Forte 		}
1018fcf3ce44SJohn Forte 		if (fport == NULL) {
1019fcf3ce44SJohn Forte 			rval = FC_SUCCESS;
1020fcf3ce44SJohn Forte 			mutex_exit(&fcip_global_mutex);
1021fcf3ce44SJohn Forte 			goto done;
1022fcf3ce44SJohn Forte 		}
1023fcf3ce44SJohn Forte 		rval = fcip_handle_resume(fport, port_info, cmd);
1024fcf3ce44SJohn Forte 		mutex_exit(&fcip_global_mutex);
1025fcf3ce44SJohn Forte 		goto done;
1026fcf3ce44SJohn Forte 
1027fcf3ce44SJohn Forte 	default:
1028fcf3ce44SJohn Forte 		FCIP_TNF_PROBE_2((fcip_port_attach, "fcip io", /* CSTYLED */,
1029fcf3ce44SJohn Forte 			tnf_string, msg, "unknown command type",
1030fcf3ce44SJohn Forte 			tnf_uint, cmd, cmd));
1032fcf3ce44SJohn Forte 		    "unknown cmd type 0x%x in port_attach", cmd));
1033fcf3ce44SJohn Forte 		rval = FC_FAILURE;
1034fcf3ce44SJohn Forte 		goto done;
1035fcf3ce44SJohn Forte 	}
1036fcf3ce44SJohn Forte 
1037fcf3ce44SJohn Forte failure:
1038fcf3ce44SJohn Forte 	if (fport) {
1039fcf3ce44SJohn Forte 		mutex_enter(&fcip_global_mutex);
1040fcf3ce44SJohn Forte 		fcip_num_attaching--;
1041fcf3ce44SJohn Forte 		ASSERT(fcip_num_attaching >= 0);
1042fcf3ce44SJohn Forte 		(void) fcip_softstate_free(fport);
1043fcf3ce44SJohn Forte 		fcip_port_attach_pending = 0;
1044fcf3ce44SJohn Forte 		mutex_exit(&fcip_global_mutex);
1045fcf3ce44SJohn Forte 	}
1046fcf3ce44SJohn Forte 	return (rval);
1047fcf3ce44SJohn Forte 
1048fcf3ce44SJohn Forte done:
1049fcf3ce44SJohn Forte 	mutex_enter(&fcip_global_mutex);
1050fcf3ce44SJohn Forte 	fcip_port_attach_pending = 0;
1051fcf3ce44SJohn Forte 	mutex_exit(&fcip_global_mutex);
1052fcf3ce44SJohn Forte 	return (rval);
1053fcf3ce44SJohn Forte }
1054fcf3ce44SJohn Forte 
1055fcf3ce44SJohn Forte /*
1056fcf3ce44SJohn Forte  * fcip_port_attach_handler : Completes the port attach operation after
1057fcf3ce44SJohn Forte  * the ulp_port_attach routine has completed its ground work. The job
1058fcf3ce44SJohn Forte  * of this function among other things is to obtain and handle topology
1059fcf3ce44SJohn Forte  * specifics, initialize a port, setup broadcast address entries in
1060fcf3ce44SJohn Forte  * the fcip tables etc. This routine cleans up behind itself on failures.
1061fcf3ce44SJohn Forte  * Returns FC_SUCCESS or FC_FAILURE.
1062fcf3ce44SJohn Forte  */
1063fcf3ce44SJohn Forte static int
fcip_port_attach_handler(struct fcip * fptr)1064fcf3ce44SJohn Forte fcip_port_attach_handler(struct fcip *fptr)
1065fcf3ce44SJohn Forte {
1066fcf3ce44SJohn Forte 	fcip_port_info_t		*fport = fptr->fcip_port_info;
1067fcf3ce44SJohn Forte 	int				rval = FC_FAILURE;
1068fcf3ce44SJohn Forte 
1069fcf3ce44SJohn Forte 	ASSERT(fport != NULL);
1070fcf3ce44SJohn Forte 
1071fcf3ce44SJohn Forte 	mutex_enter(&fcip_global_mutex);
1072fcf3ce44SJohn Forte 
1074fcf3ce44SJohn Forte 	    "fcip module dip: %p instance: %d",
1075fcf3ce44SJohn Forte 	    (void *)fcip_module_dip, ddi_get_instance(fptr->fcip_dip)));
1076fcf3ce44SJohn Forte 
1077fcf3ce44SJohn Forte 	if (fcip_module_dip == NULL) {
1078fcf3ce44SJohn Forte 		clock_t		fcip_lbolt;
1079fcf3ce44SJohn Forte 
1080fcf3ce44SJohn Forte 		fcip_lbolt = ddi_get_lbolt();
1081fcf3ce44SJohn Forte 		/*
1082fcf3ce44SJohn Forte 		 * we need to use the fcip devinfo for creating
1083fcf3ce44SJohn Forte 		 * the clone device node, but the fcip attach
1084fcf3ce44SJohn Forte 		 * (from its conf file entry claiming to be a
1085fcf3ce44SJohn Forte 		 * child of pseudo) may not have happened yet.
1086fcf3ce44SJohn Forte 		 * wait here for 10 seconds and fail port attach
1087fcf3ce44SJohn Forte 		 * if the fcip devinfo is not attached yet
1088fcf3ce44SJohn Forte 		 */
1089fcf3ce44SJohn Forte 		fcip_lbolt += drv_usectohz(FCIP_INIT_DELAY);
1090fcf3ce44SJohn Forte 
1091fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_ATTACH,
1092fcf3ce44SJohn Forte 		    (CE_WARN, "cv_timedwait lbolt %lx", fcip_lbolt));
1093fcf3ce44SJohn Forte 
1094fcf3ce44SJohn Forte 		(void) cv_timedwait(&fcip_global_cv, &fcip_global_mutex,
1095fcf3ce44SJohn Forte 		    fcip_lbolt);
1096fcf3ce44SJohn Forte 
1097fcf3ce44SJohn Forte 		if (fcip_module_dip == NULL) {
1098fcf3ce44SJohn Forte 			mutex_exit(&fcip_global_mutex);
1099fcf3ce44SJohn Forte 
1100fcf3ce44SJohn Forte 			FCIP_DEBUG(FCIP_DEBUG_ATTACH, (CE_WARN,
1101fcf3ce44SJohn Forte 				"fcip attach did not happen"));
1102fcf3ce44SJohn Forte 			goto port_attach_cleanup;
1103fcf3ce44SJohn Forte 		}
1104fcf3ce44SJohn Forte 	}
1105fcf3ce44SJohn Forte 
1106fcf3ce44SJohn Forte 	if ((!fcip_minor_node_created) &&
1107fcf3ce44SJohn Forte 	    fcip_is_supported_fc_topology(fport->fcipp_topology)) {
1108fcf3ce44SJohn Forte 		/*
1109fcf3ce44SJohn Forte 		 * Checking for same topologies which are considered valid
1110fcf3ce44SJohn Forte 		 * by fcip_handle_topology(). Dont create a minor node if
1111fcf3ce44SJohn Forte 		 * nothing is hanging off the FC port.
1112fcf3ce44SJohn Forte 		 */
1113fcf3ce44SJohn Forte 		if (ddi_create_minor_node(fcip_module_dip, "fcip", S_IFCHR,