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 
298fcf3ce44SJohn Forte #define	FCIP_DEBUG_STARTUP	(FCIP_DEBUG_ATTACH|FCIP_DEBUG_INIT)
299fcf3ce44SJohn Forte #define	FCIP_DEBUG_DATAOUT	(FCIP_DEBUG_DLPI|FCIP_DEBUG_DOWNSTREAM)
300fcf3ce44SJohn Forte #define	FCIP_DEBUG_DATAIN	(FCIP_DEBUG_ELS|FCIP_DEBUG_UPSTREAM)
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
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:
643fcf3ce44SJohn Forte 			FCIP_DEBUG(FCIP_DEBUG_DEFAULT, (CE_WARN,
644fcf3ce44SJohn Forte 			    "!fcip: module is already registered with"
645fcf3ce44SJohn Forte 			    " transport"));
646fcf3ce44SJohn Forte 			rval = EEXIST;
647fcf3ce44SJohn Forte 			break;
648fcf3ce44SJohn Forte 		case FC_ULP_SAMETYPE:
649fcf3ce44SJohn Forte 			FCIP_DEBUG(FCIP_DEBUG_DEFAULT, (CE_WARN,
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:
656fcf3ce44SJohn Forte 			FCIP_DEBUG(FCIP_DEBUG_DEFAULT, (CE_WARN,
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:
663fcf3ce44SJohn Forte 			FCIP_DEBUG(FCIP_DEBUG_DEFAULT, (CE_WARN,
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
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) {
730fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DEFAULT, (CE_WARN,
731fcf3ce44SJohn Forte 		"fcip: ULP was never registered with the transport"));
732fcf3ce44SJohn Forte 		rval = ENODEV;
733fcf3ce44SJohn Forte 	} else if (rval1 == FC_BADTYPE) {
734fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DEFAULT, (CE_WARN,
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
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
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));
798fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_ATTACH, (CE_NOTE,
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",
959fcf3ce44SJohn Forte 		    FCIP_NUM_THREADS, MINCLSYSPRI, FCIP_MIN_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 
1000fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_ATTACH, (CE_CONT,
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));
1031fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_ATTACH, (CE_WARN,
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
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 
1073fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_ATTACH, (CE_NOTE,
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,
1114fcf3ce44SJohn Forte 		    ddi_get_instance(fptr->fcip_dip), DDI_PSEUDO,
1115fcf3ce44SJohn Forte 		    CLONE_DEV) == DDI_FAILURE) {
1116fcf3ce44SJohn Forte 			mutex_exit(&fcip_global_mutex);
1117fcf3ce44SJohn Forte 			FCIP_DEBUG(FCIP_DEBUG_ATTACH, (CE_WARN,
1118fcf3ce44SJohn Forte 			    "failed to create minor node for fcip(%d)",
1119fcf3ce44SJohn Forte 			    ddi_get_instance(fptr->fcip_dip)));
1120fcf3ce44SJohn Forte 			goto port_attach_cleanup;
1121fcf3ce44SJohn Forte 		}
1122fcf3ce44SJohn Forte 		fcip_minor_node_created++;
1123fcf3ce44SJohn Forte 	}
1124fcf3ce44SJohn Forte 	mutex_exit(&fcip_global_mutex);
1125fcf3ce44SJohn Forte 
1126fcf3ce44SJohn Forte 	/*
1127fcf3ce44SJohn Forte 	 * initialize port for traffic
1128fcf3ce44SJohn Forte 	 */
1129fcf3ce44SJohn Forte 	if (fcip_init_port(fptr) != FC_SUCCESS) {
1130fcf3ce44SJohn Forte 		/* fcip_init_port has already cleaned up its stuff */
1131fcf3ce44SJohn Forte 
1132fcf3ce44SJohn Forte 		mutex_enter(&fcip_global_mutex);
1133fcf3ce44SJohn Forte 
1134fcf3ce44SJohn Forte 		if ((fcip_num_instances == 1) &&
1135fcf3ce44SJohn Forte 		    (fcip_minor_node_created == 1)) {
1136fcf3ce44SJohn Forte 			/* Remove minor node iff this is the last instance */
1137fcf3ce44SJohn Forte 			ddi_remove_minor_node(fcip_module_dip, NULL);
1138fcf3ce44SJohn Forte 		}
1139fcf3ce44SJohn Forte 
1140fcf3ce44SJohn Forte 		mutex_exit(&fcip_global_mutex);
1141fcf3ce44SJohn Forte 
1142fcf3ce44SJohn Forte 		goto port_attach_cleanup;
1143fcf3ce44SJohn Forte 	}
1144fcf3ce44SJohn Forte 
1145fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_mutex);
1146fcf3ce44SJohn Forte 	fptr->fcip_flags &= ~FCIP_ATTACHING;
1147fcf3ce44SJohn Forte 	fptr->fcip_flags |= FCIP_INITED;
1148fcf3ce44SJohn Forte 	fptr->fcip_timeout_ticks = 0;
1149fcf3ce44SJohn Forte 
1150fcf3ce44SJohn Forte 	/*
1151fcf3ce44SJohn Forte 	 * start the timeout threads
1152fcf3ce44SJohn Forte 	 */
1153fcf3ce44SJohn Forte 	fptr->fcip_timeout_id = timeout(fcip_timeout, fptr,
1154fcf3ce44SJohn Forte 	    drv_usectohz(1000000));
1155fcf3ce44SJohn Forte 
1156fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_mutex);
1157fcf3ce44SJohn Forte 	mutex_enter(&fcip_global_mutex);
1158fcf3ce44SJohn Forte 	fcip_num_attaching--;
1159fcf3ce44SJohn Forte 	ASSERT(fcip_num_attaching >= 0);
1160fcf3ce44SJohn Forte 	mutex_exit(&fcip_global_mutex);
1161fcf3ce44SJohn Forte 	rval = FC_SUCCESS;
1162fcf3ce44SJohn Forte 	return (rval);
1163fcf3ce44SJohn Forte 
1164fcf3ce44SJohn Forte port_attach_cleanup:
1165fcf3ce44SJohn Forte 	mutex_enter(&fcip_global_mutex);
1166fcf3ce44SJohn Forte 	(void) fcip_softstate_free(fport);
1167fcf3ce44SJohn Forte 	fcip_num_attaching--;
1168fcf3ce44SJohn Forte 	ASSERT(fcip_num_attaching >= 0);
1169fcf3ce44SJohn Forte 	mutex_exit(&fcip_global_mutex);
1170fcf3ce44SJohn Forte 	rval = FC_FAILURE;
1171fcf3ce44SJohn Forte 	return (rval);
1172fcf3ce44SJohn Forte }
1173fcf3ce44SJohn Forte 
1174fcf3ce44SJohn Forte 
1175fcf3ce44SJohn Forte /*
1176fcf3ce44SJohn Forte  * Handler for DDI_RESUME operations. Port must be ready to restart IP
1177fcf3ce44SJohn Forte  * traffic on resume
1178fcf3ce44SJohn Forte  */
1179fcf3ce44SJohn Forte static int
1180fcf3ce44SJohn Forte fcip_handle_resume(fcip_port_info_t *fport, fc_ulp_port_info_t *port_info,
1181fcf3ce44SJohn Forte     fc_attach_cmd_t cmd)
1182fcf3ce44SJohn Forte {
1183fcf3ce44SJohn Forte 	int 		rval = FC_SUCCESS;
1184fcf3ce44SJohn Forte 	struct fcip	*fptr = fport->fcipp_fcip;
1185fcf3ce44SJohn Forte 	struct fcipstr	*tslp;
1186fcf3ce44SJohn Forte 	int		index;
1187fcf3ce44SJohn Forte 
1188fcf3ce44SJohn Forte 
1189fcf3ce44SJohn Forte 	ASSERT(fptr != NULL);
1190fcf3ce44SJohn Forte 
1191fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_mutex);
1192fcf3ce44SJohn Forte 
1193fcf3ce44SJohn Forte 	if (cmd == FC_CMD_POWER_UP) {
1194fcf3ce44SJohn Forte 		fptr->fcip_flags &= ~(FCIP_POWER_DOWN);
1195fcf3ce44SJohn Forte 		if (fptr->fcip_flags & FCIP_SUSPENDED) {
1196fcf3ce44SJohn Forte 			mutex_exit(&fptr->fcip_mutex);
1197fcf3ce44SJohn Forte 			return (FC_SUCCESS);
1198fcf3ce44SJohn Forte 		}
1199fcf3ce44SJohn Forte 	} else if (cmd == FC_CMD_RESUME) {
1200fcf3ce44SJohn Forte 		fptr->fcip_flags &= ~(FCIP_SUSPENDED);
1201fcf3ce44SJohn Forte 	} else {
1202fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_mutex);
1203fcf3ce44SJohn Forte 		return (FC_FAILURE);
1204fcf3ce44SJohn Forte 	}
1205fcf3ce44SJohn Forte 
1206fcf3ce44SJohn Forte 	/*
1207fcf3ce44SJohn Forte 	 * set the current port state and topology
1208fcf3ce44SJohn Forte 	 */
1209fcf3ce44SJohn Forte 	fport->fcipp_topology = port_info->port_flags;
1210fcf3ce44SJohn Forte 	fport->fcipp_pstate = port_info->port_state;
1211fcf3ce44SJohn Forte 
1212fcf3ce44SJohn Forte 	rw_enter(&fcipstruplock, RW_READER);
1213fcf3ce44SJohn Forte 	for (tslp = fcipstrup; tslp; tslp = tslp->sl_nextp) {
1214fcf3ce44SJohn Forte 		if (tslp->sl_fcip == fptr) {
1215fcf3ce44SJohn Forte 			break;
1216fcf3ce44SJohn Forte 		}
1217fcf3ce44SJohn Forte 	}
1218fcf3ce44SJohn Forte 	rw_exit(&fcipstruplock);
1219fcf3ce44SJohn Forte 
1220fcf3ce44SJohn Forte 	/*
1221fcf3ce44SJohn Forte 	 * No active streams on this port
1222fcf3ce44SJohn Forte 	 */
1223fcf3ce44SJohn Forte 	if (tslp == NULL) {
1224fcf3ce44SJohn Forte 		rval = FC_SUCCESS;
1225fcf3ce44SJohn Forte 		goto done;
1226fcf3ce44SJohn Forte 	}
1227fcf3ce44SJohn Forte 
1228fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_rt_mutex);
1229fcf3ce44SJohn Forte 	for (index = 0; index < FCIP_RT_HASH_ELEMS; index++) {
1230fcf3ce44SJohn Forte 		struct fcip_routing_table 	*frp;
1231fcf3ce44SJohn Forte 
1232fcf3ce44SJohn Forte 		frp = fptr->fcip_rtable[index];
1233fcf3ce44SJohn Forte 		while (frp) {
1234fcf3ce44SJohn Forte 			uint32_t		did;
1235fcf3ce44SJohn Forte 			/*
1236fcf3ce44SJohn Forte 			 * Mark the broadcast RTE available again. It
1237fcf3ce44SJohn Forte 			 * was marked SUSPENDED during SUSPEND.
1238fcf3ce44SJohn Forte 			 */
1239fcf3ce44SJohn Forte 			did = fcip_get_broadcast_did(fptr);
1240fcf3ce44SJohn Forte 			if (frp->fcipr_d_id.port_id == did) {
1241fcf3ce44SJohn Forte 				frp->fcipr_state = 0;
1242fcf3ce44SJohn Forte 				index = FCIP_RT_HASH_ELEMS;
1243fcf3ce44SJohn Forte 				break;
1244fcf3ce44SJohn Forte 			}
1245fcf3ce44SJohn Forte 			frp = frp->fcipr_next;
1246fcf3ce44SJohn Forte 		}
1247fcf3ce44SJohn Forte 	}
1248fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_rt_mutex);
1249fcf3ce44SJohn Forte 
1250fcf3ce44SJohn Forte 	/*
1251fcf3ce44SJohn Forte 	 * fcip_handle_topology will update the port entries in the
1252fcf3ce44SJohn Forte 	 * routing table.
1253fcf3ce44SJohn Forte 	 * fcip_handle_topology also takes care of resetting the
1254fcf3ce44SJohn Forte 	 * fcipr_state field in the routing table structure. The entries
1255fcf3ce44SJohn Forte 	 * were set to RT_INVALID during suspend.
1256fcf3ce44SJohn Forte 	 */
1257fcf3ce44SJohn Forte 	fcip_handle_topology(fptr);
1258fcf3ce44SJohn Forte 
1259fcf3ce44SJohn Forte done:
1260fcf3ce44SJohn Forte 	/*
1261fcf3ce44SJohn Forte 	 * Restart the timeout thread
1262fcf3ce44SJohn Forte 	 */
1263fcf3ce44SJohn Forte 	fptr->fcip_timeout_id = timeout(fcip_timeout, fptr,
1264fcf3ce44SJohn Forte 	    drv_usectohz(1000000));
1265fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_mutex);
1266fcf3ce44SJohn Forte 	return (rval);
1267fcf3ce44SJohn Forte }
1268fcf3ce44SJohn Forte 
1269fcf3ce44SJohn Forte 
1270fcf3ce44SJohn Forte /*
1271fcf3ce44SJohn Forte  * Insert a destination port entry into the routing table for
1272fcf3ce44SJohn Forte  * this port
1273fcf3ce44SJohn Forte  */
1274fcf3ce44SJohn Forte static void
1275fcf3ce44SJohn Forte fcip_rt_update(struct fcip *fptr, fc_portmap_t *devlist, uint32_t listlen)
1276fcf3ce44SJohn Forte {
1277fcf3ce44SJohn Forte 	struct fcip_routing_table	*frp;
1278fcf3ce44SJohn Forte 	fcip_port_info_t		*fport = fptr->fcip_port_info;
1279fcf3ce44SJohn Forte 	int				hash_bucket, i;
1280fcf3ce44SJohn Forte 	fc_portmap_t			*pmap;
1281fcf3ce44SJohn Forte 	char				wwn_buf[20];
1282fcf3ce44SJohn Forte 
1283fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_2((fcip_rt_update, "fcip io", /* CSTYLED */,
1284fcf3ce44SJohn Forte 		tnf_string, msg, "enter",
1285fcf3ce44SJohn Forte 		tnf_int, listlen, listlen));
1286fcf3ce44SJohn Forte 
1287fcf3ce44SJohn Forte 	ASSERT(!mutex_owned(&fptr->fcip_mutex));
1288fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_rt_mutex);
1289fcf3ce44SJohn Forte 
1290fcf3ce44SJohn Forte 	for (i = 0; i < listlen; i++) {
1291fcf3ce44SJohn Forte 		pmap = &(devlist[i]);
1292fcf3ce44SJohn Forte 
1293fcf3ce44SJohn Forte 		frp = fcip_lookup_rtable(fptr, &(pmap->map_pwwn),
1294fcf3ce44SJohn Forte 		    FCIP_COMPARE_PWWN);
1295fcf3ce44SJohn Forte 		/*
1296fcf3ce44SJohn Forte 		 * If an entry for a port in the devlist exists in the
1297fcf3ce44SJohn Forte 		 * in the per port routing table, make sure the data
1298fcf3ce44SJohn Forte 		 * is current. We need to do this irrespective of the
1299fcf3ce44SJohn Forte 		 * underlying port topology.
1300fcf3ce44SJohn Forte 		 */
1301fcf3ce44SJohn Forte 		switch (pmap->map_type) {
1302fcf3ce44SJohn Forte 		/* FALLTHROUGH */
1303fcf3ce44SJohn Forte 		case PORT_DEVICE_NOCHANGE:
1304fcf3ce44SJohn Forte 		/* FALLTHROUGH */
1305fcf3ce44SJohn Forte 		case PORT_DEVICE_USER_LOGIN:
1306fcf3ce44SJohn Forte 		/* FALLTHROUGH */
1307fcf3ce44SJohn Forte 		case PORT_DEVICE_CHANGED:
1308fcf3ce44SJohn Forte 		/* FALLTHROUGH */
1309fcf3ce44SJohn Forte 		case PORT_DEVICE_NEW:
1310fcf3ce44SJohn Forte 			if (frp == NULL) {
1311fcf3ce44SJohn Forte 				goto add_new_entry;
1312fcf3ce44SJohn Forte 			} else if (frp) {
1313fcf3ce44SJohn Forte 				goto update_entry;
1314fcf3ce44SJohn Forte 			} else {
1315fcf3ce44SJohn Forte 				continue;
1316fcf3ce44SJohn Forte 			}
1317fcf3ce44SJohn Forte 
1318fcf3ce44SJohn Forte 		case PORT_DEVICE_OLD:
1319fcf3ce44SJohn Forte 		/* FALLTHROUGH */
1320fcf3ce44SJohn Forte 		case PORT_DEVICE_USER_LOGOUT:
1321fcf3ce44SJohn Forte 			/*
1322fcf3ce44SJohn Forte 			 * Mark entry for removal from Routing Table if
1323fcf3ce44SJohn Forte 			 * one exists. Let the timeout thread actually
1324fcf3ce44SJohn Forte 			 * remove the entry after we've given up hopes
1325fcf3ce44SJohn Forte 			 * of the port ever showing up.
1326fcf3ce44SJohn Forte 			 */
1327fcf3ce44SJohn Forte 			if (frp) {
1328fcf3ce44SJohn Forte 				uint32_t		did;
1329fcf3ce44SJohn Forte 
1330fcf3ce44SJohn Forte 				/*
1331fcf3ce44SJohn Forte 				 * Mark the routing table as invalid to bail
1332fcf3ce44SJohn Forte 				 * the packets early that are in transit
1333fcf3ce44SJohn Forte 				 */
1334fcf3ce44SJohn Forte 				did = fptr->fcip_broadcast_did;
1335fcf3ce44SJohn Forte 				if (frp->fcipr_d_id.port_id != did) {
1336fcf3ce44SJohn Forte 					frp->fcipr_pd = NULL;
1337fcf3ce44SJohn Forte 					frp->fcipr_state = FCIP_RT_INVALID;
1338fcf3ce44SJohn Forte 					frp->fcipr_invalid_timeout =
1339fcf3ce44SJohn Forte 					    fptr->fcip_timeout_ticks +
1340fcf3ce44SJohn Forte 					    FCIP_RTE_TIMEOUT;
1341fcf3ce44SJohn Forte 				}
1342fcf3ce44SJohn Forte 			}
1343fcf3ce44SJohn Forte 			continue;
1344fcf3ce44SJohn Forte 
1345fcf3ce44SJohn Forte 		default:
1346fcf3ce44SJohn Forte 			FCIP_DEBUG(FCIP_DEBUG_INIT, (CE_WARN,
1347fcf3ce44SJohn Forte 			    "unknown map flags in rt_update"));
1348fcf3ce44SJohn Forte 			continue;
1349fcf3ce44SJohn Forte 		}
1350fcf3ce44SJohn Forte add_new_entry:
1351fcf3ce44SJohn Forte 		ASSERT(frp == NULL);
1352fcf3ce44SJohn Forte 		hash_bucket = FCIP_RT_HASH(pmap->map_pwwn.raw_wwn);
1353fcf3ce44SJohn Forte 
1354fcf3ce44SJohn Forte 		ASSERT(hash_bucket < FCIP_RT_HASH_ELEMS);
1355fcf3ce44SJohn Forte 
1356fcf3ce44SJohn Forte 		FCIP_TNF_PROBE_2((fcip_rt_update, "cfip io", /* CSTYLED */,
1357fcf3ce44SJohn Forte 			tnf_string, msg,
1358fcf3ce44SJohn Forte 			"add new entry",
1359fcf3ce44SJohn Forte 			tnf_int, hashbucket, hash_bucket));
1360fcf3ce44SJohn Forte 
1361fcf3ce44SJohn Forte 		frp = (struct fcip_routing_table *)
1362fcf3ce44SJohn Forte 		    kmem_zalloc(sizeof (struct fcip_routing_table), KM_SLEEP);
1363fcf3ce44SJohn Forte 		/* insert at beginning of hash bucket */
1364fcf3ce44SJohn Forte 		frp->fcipr_next = fptr->fcip_rtable[hash_bucket];
1365fcf3ce44SJohn Forte 		fptr->fcip_rtable[hash_bucket] = frp;
1366fcf3ce44SJohn Forte 		fc_wwn_to_str(&pmap->map_pwwn, wwn_buf);
1367fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_ATTACH, (CE_NOTE,
1368fcf3ce44SJohn Forte 		    "added entry for pwwn %s and d_id 0x%x",
1369fcf3ce44SJohn Forte 		    wwn_buf, pmap->map_did.port_id));
1370fcf3ce44SJohn Forte update_entry:
1371fcf3ce44SJohn Forte 		bcopy((void *)&pmap->map_pwwn,
1372fcf3ce44SJohn Forte 		    (void *)&frp->fcipr_pwwn, sizeof (la_wwn_t));
1373fcf3ce44SJohn Forte 		bcopy((void *)&pmap->map_nwwn, (void *)&frp->fcipr_nwwn,
1374fcf3ce44SJohn Forte 		    sizeof (la_wwn_t));
1375fcf3ce44SJohn Forte 		frp->fcipr_d_id = pmap->map_did;
1376fcf3ce44SJohn Forte 		frp->fcipr_state = pmap->map_state;
1377fcf3ce44SJohn Forte 		frp->fcipr_pd = pmap->map_pd;
1378fcf3ce44SJohn Forte 
1379fcf3ce44SJohn Forte 		/*
1380fcf3ce44SJohn Forte 		 * If there is no pd for a destination port that is not
1381fcf3ce44SJohn Forte 		 * a broadcast entry, the port is pretty much unusable - so
1382fcf3ce44SJohn Forte 		 * mark the port for removal so we can try adding back the
1383fcf3ce44SJohn Forte 		 * entry again.
1384fcf3ce44SJohn Forte 		 */
1385fcf3ce44SJohn Forte 		if ((frp->fcipr_pd == NULL) &&
1386fcf3ce44SJohn Forte 		    (frp->fcipr_d_id.port_id != fptr->fcip_broadcast_did)) {
1387fcf3ce44SJohn Forte 			frp->fcipr_state = PORT_DEVICE_INVALID;
1388fcf3ce44SJohn Forte 			frp->fcipr_invalid_timeout = fptr->fcip_timeout_ticks +
1389fcf3ce44SJohn Forte 			    (FCIP_RTE_TIMEOUT / 2);
1390fcf3ce44SJohn Forte 		}
1391fcf3ce44SJohn Forte 		frp->fcipr_fca_dev =
1392fcf3ce44SJohn Forte 		    fc_ulp_get_fca_device(fport->fcipp_handle, pmap->map_did);
1393fcf3ce44SJohn Forte 
1394fcf3ce44SJohn Forte 		/*
1395fcf3ce44SJohn Forte 		 * login to the remote port. Don't worry about
1396fcf3ce44SJohn Forte 		 * plogi failures for now
1397fcf3ce44SJohn Forte 		 */
1398fcf3ce44SJohn Forte 		if (pmap->map_pd != NULL) {
1399fcf3ce44SJohn Forte 			(void) fcip_do_plogi(fptr, frp);
1400fcf3ce44SJohn Forte 		} else if (FC_TOP_EXTERNAL(fport->fcipp_topology)) {
1401fcf3ce44SJohn Forte 			fc_wwn_to_str(&frp->fcipr_pwwn, wwn_buf);
1402fcf3ce44SJohn Forte 			FCIP_DEBUG(FCIP_DEBUG_MISC, (CE_NOTE,
1403fcf3ce44SJohn Forte 			    "logging into pwwn %s, d_id 0x%x",
1404fcf3ce44SJohn Forte 			    wwn_buf, frp->fcipr_d_id.port_id));
1405fcf3ce44SJohn Forte 			(void) fcip_do_plogi(fptr, frp);
1406fcf3ce44SJohn Forte 		}
1407fcf3ce44SJohn Forte 
1408fcf3ce44SJohn Forte 		FCIP_TNF_BYTE_ARRAY(fcip_rt_update, "fcip io", "detail",
1409fcf3ce44SJohn Forte 			"new wwn in rt", pwwn,
1410fcf3ce44SJohn Forte 			&frp->fcipr_pwwn, sizeof (la_wwn_t));
1411fcf3ce44SJohn Forte 	}
1412fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_rt_mutex);
1413fcf3ce44SJohn Forte }
1414fcf3ce44SJohn Forte 
1415fcf3ce44SJohn Forte 
1416fcf3ce44SJohn Forte /*
1417fcf3ce44SJohn Forte  * return a matching routing table entry for a given fcip instance
1418fcf3ce44SJohn Forte  */
1419fcf3ce44SJohn Forte struct fcip_routing_table *
1420fcf3ce44SJohn Forte fcip_lookup_rtable(struct fcip *fptr, la_wwn_t *wwn, int matchflag)
1421fcf3ce44SJohn Forte {
1422fcf3ce44SJohn Forte 	struct fcip_routing_table	*frp = NULL;
1423fcf3ce44SJohn Forte 	int				hash_bucket;
1424fcf3ce44SJohn Forte 
1425fcf3ce44SJohn Forte 
1426fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_1((fcip_lookup_rtable, "fcip io", /* CSTYLED */,
1427fcf3ce44SJohn Forte 		tnf_string, msg, "enter"));
1428fcf3ce44SJohn Forte 	FCIP_TNF_BYTE_ARRAY(fcip_lookup_rtable, "fcip io", "detail",
1429fcf3ce44SJohn Forte 		"rtable lookup for", wwn,
1430fcf3ce44SJohn Forte 		&wwn->raw_wwn, sizeof (la_wwn_t));
1431fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_2((fcip_lookup_rtable, "fcip io", /* CSTYLED */,
1432fcf3ce44SJohn Forte 		tnf_string, msg, "match by",
1433fcf3ce44SJohn Forte 		tnf_int, matchflag, matchflag));
1434fcf3ce44SJohn Forte 
1435fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&fptr->fcip_rt_mutex));
1436fcf3ce44SJohn Forte 
1437fcf3ce44SJohn Forte 	hash_bucket = FCIP_RT_HASH(wwn->raw_wwn);
1438fcf3ce44SJohn Forte 	frp = fptr->fcip_rtable[hash_bucket];
1439fcf3ce44SJohn Forte 	while (frp != NULL) {
1440fcf3ce44SJohn Forte 
1441fcf3ce44SJohn Forte 		FCIP_TNF_BYTE_ARRAY(fcip_lookup_rtable, "fcip io", "detail",
1442fcf3ce44SJohn Forte 			"rtable entry", nwwn,
1443fcf3ce44SJohn Forte 			&(frp->fcipr_nwwn.raw_wwn), sizeof (la_wwn_t));
1444fcf3ce44SJohn Forte 
1445fcf3ce44SJohn Forte 		if (fcip_wwn_compare(&frp->fcipr_pwwn, wwn, matchflag) == 0) {
1446fcf3ce44SJohn Forte 			break;
1447fcf3ce44SJohn Forte 		}
1448fcf3ce44SJohn Forte 
1449fcf3ce44SJohn Forte 		frp = frp->fcipr_next;
1450fcf3ce44SJohn Forte 	}
1451fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_2((fcip_lookup_rtable, "fcip io", /* CSTYLED */,
1452fcf3ce44SJohn Forte 		tnf_string, msg, "lookup result",
1453fcf3ce44SJohn Forte 		tnf_opaque, frp, frp));
1454fcf3ce44SJohn Forte 	return (frp);
1455fcf3ce44SJohn Forte }
1456fcf3ce44SJohn Forte 
1457fcf3ce44SJohn Forte /*
1458fcf3ce44SJohn Forte  * Attach of fcip under pseudo. The actual setup of the interface
1459fcf3ce44SJohn Forte  * actually happens in fcip_port_attach on a callback from the
1460fcf3ce44SJohn Forte  * transport. The port_attach callback however can proceed only
1461fcf3ce44SJohn Forte  * after the devinfo for fcip has been created under pseudo
1462fcf3ce44SJohn Forte  */
1463fcf3ce44SJohn Forte static int
1464fcf3ce44SJohn Forte fcip_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1465fcf3ce44SJohn Forte {
1466fcf3ce44SJohn Forte 	switch ((int)cmd) {
1467fcf3ce44SJohn Forte 
1468fcf3ce44SJohn Forte 	case DDI_ATTACH: {
1469fcf3ce44SJohn Forte 		ASSERT(fcip_module_dip == NULL);
1470fcf3ce44SJohn Forte 		fcip_module_dip = dip;
1471fcf3ce44SJohn Forte 
1472fcf3ce44SJohn Forte 		/*
1473fcf3ce44SJohn Forte 		 * this call originates as a result of fcip's conf
1474fcf3ce44SJohn Forte 		 * file entry and will result in a fcip instance being
1475fcf3ce44SJohn Forte 		 * a child of pseudo. We should ensure here that the port
1476fcf3ce44SJohn Forte 		 * driver (fp) has been loaded and initted since we would
1477fcf3ce44SJohn Forte 		 * never get a port attach callback without fp being loaded.
1478fcf3ce44SJohn Forte 		 * If we are unable to succesfully load and initalize fp -
1479fcf3ce44SJohn Forte 		 * just fail this attach.
1480fcf3ce44SJohn Forte 		 */
1481fcf3ce44SJohn Forte 		mutex_enter(&fcip_global_mutex);
1482fcf3ce44SJohn Forte 
1483fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_ATTACH,
1484fcf3ce44SJohn Forte 		    (CE_WARN, "global cv - signaling"));
1485fcf3ce44SJohn Forte 
1486fcf3ce44SJohn Forte 		cv_signal(&fcip_global_cv);
1487fcf3ce44SJohn Forte 
1488fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_ATTACH,
1489fcf3ce44SJohn Forte 		    (CE_WARN, "global cv - signaled"));
1490fcf3ce44SJohn Forte 		mutex_exit(&fcip_global_mutex);
1491fcf3ce44SJohn Forte 		return (DDI_SUCCESS);
1492fcf3ce44SJohn Forte 	}
1493fcf3ce44SJohn Forte 	case DDI_RESUME:
1494fcf3ce44SJohn Forte 		/*
1495fcf3ce44SJohn Forte 		 * Resume appears trickier
1496fcf3ce44SJohn Forte 		 */
1497fcf3ce44SJohn Forte 		return (DDI_SUCCESS);
1498fcf3ce44SJohn Forte 	default:
1499fcf3ce44SJohn Forte 		return (DDI_FAILURE);
1500fcf3ce44SJohn Forte 	}
1501fcf3ce44SJohn Forte }
1502fcf3ce44SJohn Forte 
1503fcf3ce44SJohn Forte 
1504fcf3ce44SJohn Forte /*
1505fcf3ce44SJohn Forte  * The detach entry point to permit unloading fcip. We make sure
1506fcf3ce44SJohn Forte  * there are no active streams before we proceed with the detach
1507fcf3ce44SJohn Forte  */
1508fcf3ce44SJohn Forte /* ARGSUSED */
1509fcf3ce44SJohn Forte static int
1510fcf3ce44SJohn Forte fcip_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1511fcf3ce44SJohn Forte {
1512fcf3ce44SJohn Forte 	struct fcip		*fptr;
1513fcf3ce44SJohn Forte 	fcip_port_info_t	*fport;
1514fcf3ce44SJohn Forte 	int			detached;
1515fcf3ce44SJohn Forte 
1516fcf3ce44SJohn Forte 	switch (cmd) {
1517fcf3ce44SJohn Forte 	case DDI_DETACH: {
1518fcf3ce44SJohn Forte 		/*
1519fcf3ce44SJohn Forte 		 * If we got here, any active streams should have been
1520fcf3ce44SJohn Forte 		 * unplumbed but check anyway
1521fcf3ce44SJohn Forte 		 */
1522fcf3ce44SJohn Forte 		mutex_enter(&fcip_global_mutex);
1523fcf3ce44SJohn Forte 		if (fcipstrup != NULL) {
1524fcf3ce44SJohn Forte 			mutex_exit(&fcip_global_mutex);
1525fcf3ce44SJohn Forte 			return (DDI_FAILURE);
1526fcf3ce44SJohn Forte 		}
1527fcf3ce44SJohn Forte 
1528fcf3ce44SJohn Forte 		if (fcip_port_head != NULL) {
1529fcf3ce44SJohn Forte 			/*
1530fcf3ce44SJohn Forte 			 * Check to see if we have unattached/unbound
1531fcf3ce44SJohn Forte 			 * ports. If all the ports are unattached/unbound go
1532fcf3ce44SJohn Forte 			 * ahead and unregister with the transport
1533fcf3ce44SJohn Forte 			 */
1534fcf3ce44SJohn Forte 			fport = fcip_port_head;
1535fcf3ce44SJohn Forte 			while (fport != NULL) {
1536fcf3ce44SJohn Forte 				fptr = fport->fcipp_fcip;
1537fcf3ce44SJohn Forte 				if (fptr == NULL) {
1538fcf3ce44SJohn Forte 					continue;
1539fcf3ce44SJohn Forte 				}
1540fcf3ce44SJohn Forte 				mutex_enter(&fptr->fcip_mutex);
1541fcf3ce44SJohn Forte 				fptr->fcip_flags |= FCIP_DETACHING;
1542fcf3ce44SJohn Forte 				if (fptr->fcip_ipq ||
1543fcf3ce44SJohn Forte 				    fptr->fcip_flags & (FCIP_IN_TIMEOUT |
1544fcf3ce44SJohn Forte 				    FCIP_IN_CALLBACK | FCIP_ATTACHING |
1545fcf3ce44SJohn Forte 				    FCIP_SUSPENDED | FCIP_POWER_DOWN |
1546fcf3ce44SJohn Forte 				    FCIP_REG_INPROGRESS)) {
1547fcf3ce44SJohn Forte 					FCIP_TNF_PROBE_1((fcip_detach,
1548fcf3ce44SJohn Forte 					    "fcip io", /* CSTYLED */,
1549fcf3ce44SJohn Forte 					    tnf_string, msg,
1550fcf3ce44SJohn Forte 					    "fcip instance busy"));
1551fcf3ce44SJohn Forte 
1552fcf3ce44SJohn Forte 					mutex_exit(&fptr->fcip_mutex);
1553fcf3ce44SJohn Forte 					FCIP_DEBUG(FCIP_DEBUG_DETACH, (CE_WARN,
1554fcf3ce44SJohn Forte 					    "fcip instance busy"));
1555fcf3ce44SJohn Forte 					break;
1556fcf3ce44SJohn Forte 				}
1557fcf3ce44SJohn Forte 				/*
1558fcf3ce44SJohn Forte 				 * Check for any outstanding pkts. If yes
1559fcf3ce44SJohn Forte 				 * fail the detach
1560fcf3ce44SJohn Forte 				 */
1561fcf3ce44SJohn Forte 				mutex_enter(&fptr->fcip_dest_mutex);
1562fcf3ce44SJohn Forte 				if (fcip_port_get_num_pkts(fptr) > 0) {
1563fcf3ce44SJohn Forte 					mutex_exit(&fptr->fcip_dest_mutex);
1564fcf3ce44SJohn Forte 					mutex_exit(&fptr->fcip_mutex);
1565fcf3ce44SJohn Forte 					FCIP_DEBUG(FCIP_DEBUG_DETACH, (CE_WARN,
1566fcf3ce44SJohn Forte 					    "fcip instance busy - pkts "
1567fcf3ce44SJohn Forte 					    "pending"));
1568fcf3ce44SJohn Forte 					break;
1569fcf3ce44SJohn Forte 				}
1570fcf3ce44SJohn Forte 				mutex_exit(&fptr->fcip_dest_mutex);
1571fcf3ce44SJohn Forte 
1572fcf3ce44SJohn Forte 				mutex_enter(&fptr->fcip_rt_mutex);
1573fcf3ce44SJohn Forte 				if (fcip_plogi_in_progress(fptr)) {
1574fcf3ce44SJohn Forte 					mutex_exit(&fptr->fcip_rt_mutex);
1575fcf3ce44SJohn Forte 					mutex_exit(&fptr->fcip_mutex);
1576fcf3ce44SJohn Forte 					FCIP_DEBUG(FCIP_DEBUG_DETACH, (CE_WARN,
1577fcf3ce44SJohn Forte 					    "fcip instance busy - plogi in "
1578fcf3ce44SJohn Forte 					    "progress"));
1579fcf3ce44SJohn Forte 					break;
1580fcf3ce44SJohn Forte 				}
1581fcf3ce44SJohn Forte 				mutex_exit(&fptr->fcip_rt_mutex);
1582fcf3ce44SJohn Forte 
1583fcf3ce44SJohn Forte 				mutex_exit(&fptr->fcip_mutex);
1584fcf3ce44SJohn Forte 				fport = fport->fcipp_next;
1585fcf3ce44SJohn Forte 			}
1586fcf3ce44SJohn Forte 			/*
1587fcf3ce44SJohn Forte 			 * if fport is non NULL - we have active ports
1588fcf3ce44SJohn Forte 			 */
1589fcf3ce44SJohn Forte 			if (fport != NULL) {
1590fcf3ce44SJohn Forte 				/*
1591fcf3ce44SJohn Forte 				 * Remove the DETACHING flags on the ports
1592fcf3ce44SJohn Forte 				 */
1593fcf3ce44SJohn Forte 				fport = fcip_port_head;
1594fcf3ce44SJohn Forte 				while (fport != NULL) {
1595fcf3ce44SJohn Forte 					fptr = fport->fcipp_fcip;
1596fcf3ce44SJohn Forte 					mutex_enter(&fptr->fcip_mutex);
1597fcf3ce44SJohn Forte 					fptr->fcip_flags &= ~(FCIP_DETACHING);
1598fcf3ce44SJohn Forte 					mutex_exit(&fptr->fcip_mutex);
1599fcf3ce44SJohn Forte 					fport = fport->fcipp_next;
1600fcf3ce44SJohn Forte 				}
1601fcf3ce44SJohn Forte 				mutex_exit(&fcip_global_mutex);
1602fcf3ce44SJohn Forte 				return (DDI_FAILURE);
1603fcf3ce44SJohn Forte 			}
1604fcf3ce44SJohn Forte 		}
1605fcf3ce44SJohn Forte 
1606fcf3ce44SJohn Forte 		/*
1607fcf3ce44SJohn Forte 		 * free up all softstate structures
1608fcf3ce44SJohn Forte 		 */
1609fcf3ce44SJohn Forte 		fport = fcip_port_head;
1610fcf3ce44SJohn Forte 		while (fport != NULL) {
1611fcf3ce44SJohn Forte 			detached = 1;
1612fcf3ce44SJohn Forte 
1613fcf3ce44SJohn Forte 			fptr = fport->fcipp_fcip;
1614fcf3ce44SJohn Forte 			if (fptr) {
1615fcf3ce44SJohn Forte 				mutex_enter(&fptr->fcip_mutex);
1616fcf3ce44SJohn Forte 				/*
1617fcf3ce44SJohn Forte 				 * Check to see if somebody beat us to the
1618fcf3ce44SJohn Forte 				 * punch
1619fcf3ce44SJohn Forte 				 */
1620fcf3ce44SJohn Forte 				detached = fptr->fcip_flags & FCIP_DETACHED;
1621fcf3ce44SJohn Forte 				fptr->fcip_flags &= ~(FCIP_DETACHING);
1622fcf3ce44SJohn Forte 				fptr->fcip_flags |= FCIP_DETACHED;
1623fcf3ce44SJohn Forte 				mutex_exit(&fptr->fcip_mutex);
1624fcf3ce44SJohn Forte 			}
1625fcf3ce44SJohn Forte 
1626fcf3ce44SJohn Forte 			if (!detached) {
1627fcf3ce44SJohn Forte 				fport = fcip_softstate_free(fport);
1628fcf3ce44SJohn Forte 			} else {
1629fcf3ce44SJohn Forte 				/*
1630fcf3ce44SJohn Forte 				 * If the port was marked as detached
1631fcf3ce44SJohn Forte 				 * but it was still in the list, that
1632fcf3ce44SJohn Forte 				 * means another thread has marked it
1633fcf3ce44SJohn Forte 				 * but we got in while it released the
1634fcf3ce44SJohn Forte 				 * fcip_global_mutex in softstate_free.
1635fcf3ce44SJohn Forte 				 * Given that, we're still safe to use
1636fcf3ce44SJohn Forte 				 * fport->fcipp_next to find out what
1637fcf3ce44SJohn Forte 				 * the next port on the list is.
1638fcf3ce44SJohn Forte 				 */
1639fcf3ce44SJohn Forte 				fport = fport->fcipp_next;
1640fcf3ce44SJohn Forte 			}
1641fcf3ce44SJohn Forte 
1642fcf3ce44SJohn Forte 			FCIP_DEBUG(FCIP_DEBUG_DETACH,
1643fcf3ce44SJohn Forte 			    (CE_NOTE, "detaching port"));
1644fcf3ce44SJohn Forte 
1645fcf3ce44SJohn Forte 			FCIP_TNF_PROBE_1((fcip_detach,
1646fcf3ce44SJohn Forte 				"fcip io", /* CSTYLED */, tnf_string,
1647fcf3ce44SJohn Forte 				msg, "detaching port"));
1648fcf3ce44SJohn Forte 		}
1649fcf3ce44SJohn Forte 
1650fcf3ce44SJohn Forte 		/*
1651fcf3ce44SJohn Forte 		 * If we haven't removed all the port structures, we
1652fcf3ce44SJohn Forte 		 * aren't yet ready to be detached.
1653fcf3ce44SJohn Forte 		 */
1654fcf3ce44SJohn Forte 		if (fcip_port_head != NULL) {
1655fcf3ce44SJohn Forte 			mutex_exit(&fcip_global_mutex);
1656fcf3ce44SJohn Forte 			return (DDI_FAILURE);
1657fcf3ce44SJohn Forte 		}
1658fcf3ce44SJohn Forte 
1659fcf3ce44SJohn Forte 		fcip_num_instances = 0;
1660fcf3ce44SJohn Forte 		mutex_exit(&fcip_global_mutex);
1661fcf3ce44SJohn Forte 		fcip_module_dip = NULL;
1662fcf3ce44SJohn Forte 		return (DDI_SUCCESS);
1663fcf3ce44SJohn Forte 	}
1664fcf3ce44SJohn Forte 	case DDI_SUSPEND:
1665fcf3ce44SJohn Forte 		return (DDI_SUCCESS);
1666fcf3ce44SJohn Forte 	default:
1667fcf3ce44SJohn Forte 		return (DDI_FAILURE);
1668fcf3ce44SJohn Forte 	}
1669fcf3ce44SJohn Forte }
1670fcf3ce44SJohn Forte 
1671fcf3ce44SJohn Forte /*
1672fcf3ce44SJohn Forte  * The port_detach callback is called from the transport when a
1673fcf3ce44SJohn Forte  * FC port is being removed from the transport's control. This routine
1674fcf3ce44SJohn Forte  * provides fcip with an opportunity to cleanup all activities and
1675fcf3ce44SJohn Forte  * structures on the port marked for removal.
1676fcf3ce44SJohn Forte  */
1677fcf3ce44SJohn Forte /* ARGSUSED */
1678fcf3ce44SJohn Forte static int
1679fcf3ce44SJohn Forte fcip_port_detach(opaque_t ulp_handle, fc_ulp_port_info_t *port_info,
1680fcf3ce44SJohn Forte     fc_detach_cmd_t cmd)
1681fcf3ce44SJohn Forte {
1682fcf3ce44SJohn Forte 	int 			rval = FC_FAILURE;
1683fcf3ce44SJohn Forte 	fcip_port_info_t	*fport;
1684fcf3ce44SJohn Forte 	struct fcip		*fptr;
1685fcf3ce44SJohn Forte 	struct fcipstr		*strp;
1686fcf3ce44SJohn Forte 
1687fcf3ce44SJohn Forte 	switch (cmd) {
1688fcf3ce44SJohn Forte 	case FC_CMD_DETACH: {
1689fcf3ce44SJohn Forte 		mutex_enter(&fcip_global_mutex);
1690fcf3ce44SJohn Forte 
1691fcf3ce44SJohn Forte 		if (fcip_port_head == NULL) {
1692fcf3ce44SJohn Forte 			/*
1693fcf3ce44SJohn Forte 			 * we are all done but our fini has not been
1694fcf3ce44SJohn Forte 			 * called yet!! Let's hope we have no active
1695fcf3ce44SJohn Forte 			 * fcip instances here. - strange secnario but
1696fcf3ce44SJohn Forte 			 * no harm in having this return a success.
1697fcf3ce44SJohn Forte 			 */
1698fcf3ce44SJohn Forte 			fcip_check_remove_minor_node();
1699fcf3ce44SJohn Forte 
1700fcf3ce44SJohn Forte 			mutex_exit(&fcip_global_mutex);
1701fcf3ce44SJohn Forte 			return (FC_SUCCESS);
1702fcf3ce44SJohn Forte 		} else {
1703fcf3ce44SJohn Forte 			/*
1704fcf3ce44SJohn Forte 			 * traverse the port list
1705fcf3ce44SJohn Forte 			 */
1706fcf3ce44SJohn Forte 			fport = fcip_port_head;
1707fcf3ce44SJohn Forte 			while (fport != NULL) {
1708fcf3ce44SJohn Forte 				if (fport->fcipp_handle ==
1709fcf3ce44SJohn Forte 				    port_info->port_handle) {
1710fcf3ce44SJohn Forte 					fptr = fport->fcipp_fcip;
1711fcf3ce44SJohn Forte 
1712fcf3ce44SJohn Forte 					/*
1713fcf3ce44SJohn Forte 					 * Fail the port detach if there is
1714fcf3ce44SJohn Forte 					 * still an attached, bound stream on
1715fcf3ce44SJohn Forte 					 * this interface.
1716fcf3ce44SJohn Forte 					 */
1717fcf3ce44SJohn Forte 
1718fcf3ce44SJohn Forte 					rw_enter(&fcipstruplock, RW_READER);
1719fcf3ce44SJohn Forte 
1720fcf3ce44SJohn Forte 					for (strp = fcipstrup; strp != NULL;
1721fcf3ce44SJohn Forte 					    strp = strp->sl_nextp) {
1722fcf3ce44SJohn Forte 						if (strp->sl_fcip == fptr) {
1723fcf3ce44SJohn Forte 							rw_exit(&fcipstruplock);
1724fcf3ce44SJohn Forte 							mutex_exit(
1725fcf3ce44SJohn Forte 							    &fcip_global_mutex);
1726fcf3ce44SJohn Forte 							return (FC_FAILURE);
1727fcf3ce44SJohn Forte 						}
1728fcf3ce44SJohn Forte 					}
1729fcf3ce44SJohn Forte 
1730fcf3ce44SJohn Forte 					rw_exit(&fcipstruplock);
1731fcf3ce44SJohn Forte 
1732fcf3ce44SJohn Forte 					/*
1733fcf3ce44SJohn Forte 					 * fail port detach if we are in
1734fcf3ce44SJohn Forte 					 * the middle of a deferred port attach
1735fcf3ce44SJohn Forte 					 * or if the port has outstanding pkts
1736fcf3ce44SJohn Forte 					 */
1737fcf3ce44SJohn Forte 					if (fptr != NULL) {
1738fcf3ce44SJohn Forte 						mutex_enter(&fptr->fcip_mutex);
1739fcf3ce44SJohn Forte 						if (fcip_check_port_busy
1740fcf3ce44SJohn Forte 						    (fptr) ||
1741fcf3ce44SJohn Forte 						    (fptr->fcip_flags &
1742fcf3ce44SJohn Forte 						    FCIP_DETACHED)) {
1743fcf3ce44SJohn Forte 							mutex_exit(
1744fcf3ce44SJohn Forte 							    &fptr->fcip_mutex);
1745fcf3ce44SJohn Forte 							mutex_exit(
1746fcf3ce44SJohn Forte 							    &fcip_global_mutex);
1747fcf3ce44SJohn Forte 							return (FC_FAILURE);
1748fcf3ce44SJohn Forte 						}
1749fcf3ce44SJohn Forte 
1750fcf3ce44SJohn Forte 						fptr->fcip_flags |=
1751fcf3ce44SJohn Forte 						    FCIP_DETACHED;
1752fcf3ce44SJohn Forte 						mutex_exit(&fptr->fcip_mutex);
1753fcf3ce44SJohn Forte 					}
1754fcf3ce44SJohn Forte 					(void) fcip_softstate_free(fport);
1755fcf3ce44SJohn Forte 
1756fcf3ce44SJohn Forte 					fcip_check_remove_minor_node();
1757fcf3ce44SJohn Forte 					mutex_exit(&fcip_global_mutex);
1758fcf3ce44SJohn Forte 					return (FC_SUCCESS);
1759fcf3ce44SJohn Forte 				}
1760fcf3ce44SJohn Forte 				fport = fport->fcipp_next;
1761fcf3ce44SJohn Forte 			}
1762fcf3ce44SJohn Forte 			ASSERT(fport == NULL);
1763fcf3ce44SJohn Forte 		}
1764fcf3ce44SJohn Forte 		mutex_exit(&fcip_global_mutex);
1765fcf3ce44SJohn Forte 		break;
1766fcf3ce44SJohn Forte 	}
1767fcf3ce44SJohn Forte 	case FC_CMD_POWER_DOWN:
1768fcf3ce44SJohn Forte 	/* FALLTHROUGH */
1769fcf3ce44SJohn Forte 	case FC_CMD_SUSPEND:
1770fcf3ce44SJohn Forte 		mutex_enter(&fcip_global_mutex);
1771fcf3ce44SJohn Forte 		fport = fcip_port_head;
1772fcf3ce44SJohn Forte 		while (fport != NULL) {
1773fcf3ce44SJohn Forte 			if (fport->fcipp_handle == port_info->port_handle) {
1774fcf3ce44SJohn Forte 				break;
1775fcf3ce44SJohn Forte 			}
1776fcf3ce44SJohn Forte 			fport = fport->fcipp_next;
1777fcf3ce44SJohn Forte 		}
1778fcf3ce44SJohn Forte 		if (fport == NULL) {
1779fcf3ce44SJohn Forte 			mutex_exit(&fcip_global_mutex);
1780fcf3ce44SJohn Forte 			break;
1781fcf3ce44SJohn Forte 		}
1782fcf3ce44SJohn Forte 		rval = fcip_handle_suspend(fport, cmd);
1783fcf3ce44SJohn Forte 		mutex_exit(&fcip_global_mutex);
1784fcf3ce44SJohn Forte 		break;
1785fcf3ce44SJohn Forte 	default:
1786fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DETACH,
1787fcf3ce44SJohn Forte 		    (CE_WARN, "unknown port detach command!!"));
1788fcf3ce44SJohn Forte 		break;
1789fcf3ce44SJohn Forte 	}
1790fcf3ce44SJohn Forte 	return (rval);
1791fcf3ce44SJohn Forte }
1792fcf3ce44SJohn Forte 
1793fcf3ce44SJohn Forte 
1794fcf3ce44SJohn Forte /*
1795fcf3ce44SJohn Forte  * Returns 0 if the port is not busy, else returns non zero.
1796fcf3ce44SJohn Forte  */
1797fcf3ce44SJohn Forte static int
1798fcf3ce44SJohn Forte fcip_check_port_busy(struct fcip *fptr)
1799fcf3ce44SJohn Forte {
1800fcf3ce44SJohn Forte 	int rval = 0, num_pkts = 0;
1801fcf3ce44SJohn Forte 
1802fcf3ce44SJohn Forte 	ASSERT(fptr != NULL);
1803fcf3ce44SJohn Forte 	ASSERT(MUTEX_HELD(&fptr->fcip_mutex));
1804fcf3ce44SJohn Forte 
1805fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_dest_mutex);
1806fcf3ce44SJohn Forte 
1807fcf3ce44SJohn Forte 	if (fptr->fcip_flags & FCIP_PORT_BUSY ||
1808fcf3ce44SJohn Forte 	    ((num_pkts = fcip_port_get_num_pkts(fptr)) > 0) ||
1809fcf3ce44SJohn Forte 	    fptr->fcip_num_ipkts_pending) {
1810fcf3ce44SJohn Forte 		rval = 1;
1811fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DETACH,
1812fcf3ce44SJohn Forte 		    (CE_NOTE, "!fcip_check_port_busy: port is busy "
1813fcf3ce44SJohn Forte 		    "fcip_flags: 0x%x, num_pkts: 0x%x, ipkts_pending: 0x%lx!",
1814fcf3ce44SJohn Forte 		    fptr->fcip_flags, num_pkts, fptr->fcip_num_ipkts_pending));
1815fcf3ce44SJohn Forte 	}
1816fcf3ce44SJohn Forte 
1817fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_dest_mutex);
1818fcf3ce44SJohn Forte 	return (rval);
1819fcf3ce44SJohn Forte }
1820fcf3ce44SJohn Forte 
1821fcf3ce44SJohn Forte /*
1822fcf3ce44SJohn Forte  * Helper routine to remove fcip's minor node
1823fcf3ce44SJohn Forte  * There is one minor node per system and it should be removed if there are no
1824fcf3ce44SJohn Forte  * other fcip instances (which has a 1:1 mapping for fp instances) present
1825fcf3ce44SJohn Forte  */
1826fcf3ce44SJohn Forte static void
1827fcf3ce44SJohn Forte fcip_check_remove_minor_node(void)
1828fcf3ce44SJohn Forte {
1829fcf3ce44SJohn Forte 	ASSERT(MUTEX_HELD(&fcip_global_mutex));
1830fcf3ce44SJohn Forte 
1831fcf3ce44SJohn Forte 	/*
1832fcf3ce44SJohn Forte 	 * If there are no more fcip (fp) instances, remove the
1833fcf3ce44SJohn Forte 	 * minor node for fcip.
1834fcf3ce44SJohn Forte 	 * Reset fcip_minor_node_created to invalidate it.
1835fcf3ce44SJohn Forte 	 */
1836fcf3ce44SJohn Forte 	if (fcip_num_instances == 0 && (fcip_module_dip != NULL)) {
1837fcf3ce44SJohn Forte 		ddi_remove_minor_node(fcip_module_dip, NULL);
1838fcf3ce44SJohn Forte 		fcip_minor_node_created = 0;
1839fcf3ce44SJohn Forte 	}
1840fcf3ce44SJohn Forte }
1841fcf3ce44SJohn Forte 
1842fcf3ce44SJohn Forte /*
1843fcf3ce44SJohn Forte  * This routine permits the suspend operation during a CPR/System
1844fcf3ce44SJohn Forte  * power management operation. The routine basically quiesces I/Os
1845fcf3ce44SJohn Forte  * on all active interfaces
1846fcf3ce44SJohn Forte  */
1847fcf3ce44SJohn Forte static int
1848fcf3ce44SJohn Forte fcip_handle_suspend(fcip_port_info_t *fport, fc_detach_cmd_t cmd)
1849fcf3ce44SJohn Forte {
1850fcf3ce44SJohn Forte 	struct fcip	*fptr = fport->fcipp_fcip;
1851fcf3ce44SJohn Forte 	timeout_id_t	tid;
1852fcf3ce44SJohn Forte 	int 		index;
1853fcf3ce44SJohn Forte 	int		tryagain = 0;
1854fcf3ce44SJohn Forte 	int		count;
1855fcf3ce44SJohn Forte 	struct fcipstr	*tslp;
1856fcf3ce44SJohn Forte 
1857fcf3ce44SJohn Forte 
1858fcf3ce44SJohn Forte 	ASSERT(fptr != NULL);
1859fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_mutex);
1860fcf3ce44SJohn Forte 
1861fcf3ce44SJohn Forte 	/*
1862fcf3ce44SJohn Forte 	 * Fail if we are in the middle of a callback. Don't use delay during
1863fcf3ce44SJohn Forte 	 * suspend since clock intrs are not available so busy wait
1864fcf3ce44SJohn Forte 	 */
1865fcf3ce44SJohn Forte 	count = 0;
1866fcf3ce44SJohn Forte 	while (count++ < 15 &&
1867fcf3ce44SJohn Forte 	    ((fptr->fcip_flags & FCIP_IN_CALLBACK) ||
1868fcf3ce44SJohn Forte 	    (fptr->fcip_flags & FCIP_IN_TIMEOUT))) {
1869fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_mutex);
1870fcf3ce44SJohn Forte 		drv_usecwait(1000000);
1871fcf3ce44SJohn Forte 		mutex_enter(&fptr->fcip_mutex);
1872fcf3ce44SJohn Forte 	}
1873fcf3ce44SJohn Forte 
1874fcf3ce44SJohn Forte 	if (fptr->fcip_flags & FCIP_IN_CALLBACK ||
1875fcf3ce44SJohn Forte 	    fptr->fcip_flags & FCIP_IN_TIMEOUT) {
1876fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_mutex);
1877fcf3ce44SJohn Forte 		return (FC_FAILURE);
1878fcf3ce44SJohn Forte 	}
1879fcf3ce44SJohn Forte 
1880fcf3ce44SJohn Forte 	if (cmd == FC_CMD_POWER_DOWN) {
1881fcf3ce44SJohn Forte 		if (fptr->fcip_flags & FCIP_SUSPENDED) {
1882fcf3ce44SJohn Forte 			fptr->fcip_flags |= FCIP_POWER_DOWN;
1883fcf3ce44SJohn Forte 			mutex_exit(&fptr->fcip_mutex);
1884fcf3ce44SJohn Forte 			goto success;
1885fcf3ce44SJohn Forte 		} else {
1886fcf3ce44SJohn Forte 			fptr->fcip_flags |= FCIP_POWER_DOWN;
1887fcf3ce44SJohn Forte 		}
1888fcf3ce44SJohn Forte 	} else if (cmd == FC_CMD_SUSPEND) {
1889fcf3ce44SJohn Forte 		fptr->fcip_flags |= FCIP_SUSPENDED;
1890fcf3ce44SJohn Forte 	} else {
1891fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_mutex);
1892fcf3ce44SJohn Forte 		return (FC_FAILURE);
1893fcf3ce44SJohn Forte 	}
1894fcf3ce44SJohn Forte 
1895fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_mutex);
1896fcf3ce44SJohn Forte 	/*
1897fcf3ce44SJohn Forte 	 * If no streams are plumbed - its the easiest case - Just
1898fcf3ce44SJohn Forte 	 * bail out without having to do much
1899fcf3ce44SJohn Forte 	 */
1900fcf3ce44SJohn Forte 
1901fcf3ce44SJohn Forte 	rw_enter(&fcipstruplock, RW_READER);
1902fcf3ce44SJohn Forte 	for (tslp = fcipstrup; tslp; tslp = tslp->sl_nextp) {
1903fcf3ce44SJohn Forte 		if (tslp->sl_fcip == fptr) {
1904fcf3ce44SJohn Forte 			break;
1905fcf3ce44SJohn Forte 		}
1906fcf3ce44SJohn Forte 	}
1907fcf3ce44SJohn Forte 	rw_exit(&fcipstruplock);
1908fcf3ce44SJohn Forte 
1909fcf3ce44SJohn Forte 	/*
1910fcf3ce44SJohn Forte 	 * No active streams on this port
1911fcf3ce44SJohn Forte 	 */
1912fcf3ce44SJohn Forte 	if (tslp == NULL) {
1913fcf3ce44SJohn Forte 		goto success;
1914fcf3ce44SJohn Forte 	}
1915fcf3ce44SJohn Forte 
1916fcf3ce44SJohn Forte 	/*
1917fcf3ce44SJohn Forte 	 * Walk through each Routing table structure and check if
1918fcf3ce44SJohn Forte 	 * the destination table has any outstanding commands. If yes
1919fcf3ce44SJohn Forte 	 * wait for the commands to drain. Since we go through each
1920fcf3ce44SJohn Forte 	 * routing table entry in succession, it may be wise to wait
1921fcf3ce44SJohn Forte 	 * only a few seconds for each entry.
1922fcf3ce44SJohn Forte 	 */
1923fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_rt_mutex);
1924fcf3ce44SJohn Forte 	while (!tryagain) {
1925fcf3ce44SJohn Forte 
1926fcf3ce44SJohn Forte 		tryagain = 0;
1927fcf3ce44SJohn Forte 		for (index = 0; index < FCIP_RT_HASH_ELEMS; index++) {
1928fcf3ce44SJohn Forte 			struct fcip_routing_table 	*frp;
1929fcf3ce44SJohn Forte 			struct fcip_dest 		*fdestp;
1930fcf3ce44SJohn Forte 			la_wwn_t			*pwwn;
1931fcf3ce44SJohn Forte 			int				hash_bucket;
1932fcf3ce44SJohn Forte 
1933fcf3ce44SJohn Forte 			frp = fptr->fcip_rtable[index];
1934fcf3ce44SJohn Forte 			while (frp) {
1935fcf3ce44SJohn Forte 				/*
1936fcf3ce44SJohn Forte 				 * Mark the routing table as SUSPENDED. Even
1937fcf3ce44SJohn Forte 				 * mark the broadcast entry SUSPENDED to
1938fcf3ce44SJohn Forte 				 * prevent any ARP or other broadcasts. We
1939fcf3ce44SJohn Forte 				 * can reset the state of the broadcast
1940fcf3ce44SJohn Forte 				 * RTE when we resume.
1941fcf3ce44SJohn Forte 				 */
1942fcf3ce44SJohn Forte 				frp->fcipr_state = FCIP_RT_SUSPENDED;
1943fcf3ce44SJohn Forte 				pwwn = &frp->fcipr_pwwn;
1944fcf3ce44SJohn Forte 
1945fcf3ce44SJohn Forte 				/*
1946fcf3ce44SJohn Forte 				 * Get hold of destination pointer
1947fcf3ce44SJohn Forte 				 */
1948fcf3ce44SJohn Forte 				mutex_enter(&fptr->fcip_dest_mutex);
1949fcf3ce44SJohn Forte 
1950fcf3ce44SJohn Forte 				hash_bucket = FCIP_DEST_HASH(pwwn->raw_wwn);
1951fcf3ce44SJohn Forte 				ASSERT(hash_bucket < FCIP_DEST_HASH_ELEMS);
1952fcf3ce44SJohn Forte 
1953fcf3ce44SJohn Forte 				fdestp = fptr->fcip_dest[hash_bucket];
1954fcf3ce44SJohn Forte 				while (fdestp != NULL) {
1955fcf3ce44SJohn Forte 					mutex_enter(&fdestp->fcipd_mutex);
1956fcf3ce44SJohn Forte 					if (fdestp->fcipd_rtable) {
1957fcf3ce44SJohn Forte 						if (fcip_wwn_compare(pwwn,
1958fcf3ce44SJohn Forte 						    &fdestp->fcipd_pwwn,
1959fcf3ce44SJohn Forte 						    FCIP_COMPARE_PWWN) == 0) {
1960fcf3ce44SJohn Forte 							mutex_exit(
1961fcf3ce44SJohn Forte 							&fdestp->fcipd_mutex);
1962fcf3ce44SJohn Forte 							break;
1963fcf3ce44SJohn Forte 						}
1964fcf3ce44SJohn Forte 					}
1965fcf3ce44SJohn Forte 					mutex_exit(&fdestp->fcipd_mutex);
1966fcf3ce44SJohn Forte 					fdestp = fdestp->fcipd_next;
1967fcf3ce44SJohn Forte 				}
1968fcf3ce44SJohn Forte 
1969fcf3ce44SJohn Forte 				mutex_exit(&fptr->fcip_dest_mutex);
1970fcf3ce44SJohn Forte 				if (fdestp == NULL) {
1971fcf3ce44SJohn Forte 					frp = frp->fcipr_next;
1972fcf3ce44SJohn Forte 					continue;
1973fcf3ce44SJohn Forte 				}
1974fcf3ce44SJohn Forte 
1975fcf3ce44SJohn Forte 				/*
1976fcf3ce44SJohn Forte 				 * Wait for fcip_wait_cmds seconds for
1977fcf3ce44SJohn Forte 				 * the commands to drain.
1978fcf3ce44SJohn Forte 				 */
1979fcf3ce44SJohn Forte 				count = 0;
1980fcf3ce44SJohn Forte 				mutex_enter(&fdestp->fcipd_mutex);
1981fcf3ce44SJohn Forte 				while (fdestp->fcipd_ncmds &&
1982fcf3ce44SJohn Forte 				    count < fcip_wait_cmds) {
1983fcf3ce44SJohn Forte 					mutex_exit(&fdestp->fcipd_mutex);
1984fcf3ce44SJohn Forte 					mutex_exit(&fptr->fcip_rt_mutex);
1985fcf3ce44SJohn Forte 					drv_usecwait(1000000);
1986fcf3ce44SJohn Forte 					mutex_enter(&fptr->fcip_rt_mutex);
1987fcf3ce44SJohn Forte 					mutex_enter(&fdestp->fcipd_mutex);
1988fcf3ce44SJohn Forte 					count++;
1989fcf3ce44SJohn Forte 				}
1990fcf3ce44SJohn Forte 				/*
1991fcf3ce44SJohn Forte 				 * Check if we were able to drain all cmds
1992fcf3ce44SJohn Forte 				 * successfully. Else continue with other
1993fcf3ce44SJohn Forte 				 * ports and try during the second pass
1994fcf3ce44SJohn Forte 				 */
1995fcf3ce44SJohn Forte 				if (fdestp->fcipd_ncmds) {
1996fcf3ce44SJohn Forte 					tryagain++;
1997fcf3ce44SJohn Forte 				}
1998fcf3ce44SJohn Forte 				mutex_exit(&fdestp->fcipd_mutex);
1999fcf3ce44SJohn Forte 
2000fcf3ce44SJohn Forte 				frp = frp->fcipr_next;
2001fcf3ce44SJohn Forte 			}
2002fcf3ce44SJohn Forte 		}
2003fcf3ce44SJohn Forte 		if (tryagain == 0) {
2004fcf3ce44SJohn Forte 			break;
2005fcf3ce44SJohn Forte 		}
2006fcf3ce44SJohn Forte 	}
2007fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_rt_mutex);
2008fcf3ce44SJohn Forte 
2009fcf3ce44SJohn Forte 	if (tryagain) {
2010fcf3ce44SJohn Forte 		mutex_enter(&fptr->fcip_mutex);
2011fcf3ce44SJohn Forte 		fptr->fcip_flags &= ~(FCIP_SUSPENDED | FCIP_POWER_DOWN);
2012fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_mutex);
2013fcf3ce44SJohn Forte 		return (FC_FAILURE);
2014fcf3ce44SJohn Forte 	}
2015fcf3ce44SJohn Forte 
2016fcf3ce44SJohn Forte success:
2017fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_mutex);
2018fcf3ce44SJohn Forte 	tid = fptr->fcip_timeout_id;
2019fcf3ce44SJohn Forte 	fptr->fcip_timeout_id = NULL;
2020fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_mutex);
2021fcf3ce44SJohn Forte 
2022fcf3ce44SJohn Forte 	(void) untimeout(tid);
2023fcf3ce44SJohn Forte 
2024fcf3ce44SJohn Forte 	return (FC_SUCCESS);
2025fcf3ce44SJohn Forte }
2026fcf3ce44SJohn Forte 
2027fcf3ce44SJohn Forte /*
2028fcf3ce44SJohn Forte  * the getinfo(9E) entry point
2029fcf3ce44SJohn Forte  */
2030fcf3ce44SJohn Forte /* ARGSUSED */
2031fcf3ce44SJohn Forte static int
2032fcf3ce44SJohn Forte fcip_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
2033fcf3ce44SJohn Forte {
2034fcf3ce44SJohn Forte 	int rval = DDI_FAILURE;
2035fcf3ce44SJohn Forte 
2036fcf3ce44SJohn Forte 	switch (cmd) {
2037fcf3ce44SJohn Forte 	case DDI_INFO_DEVT2DEVINFO:
2038fcf3ce44SJohn Forte 		*result = fcip_module_dip;
2039fcf3ce44SJohn Forte 		if (*result)
2040fcf3ce44SJohn Forte 			rval = DDI_SUCCESS;
2041fcf3ce44SJohn Forte 		break;
2042fcf3ce44SJohn Forte 
2043fcf3ce44SJohn Forte 	case DDI_INFO_DEVT2INSTANCE:
2044fcf3ce44SJohn Forte 		*result = (void *)0;
2045fcf3ce44SJohn Forte 		rval = DDI_SUCCESS;
2046fcf3ce44SJohn Forte 		break;
2047fcf3ce44SJohn Forte 	default:
2048fcf3ce44SJohn Forte 		break;
2049fcf3ce44SJohn Forte 	}
2050fcf3ce44SJohn Forte 
2051fcf3ce44SJohn Forte 	return (rval);
2052fcf3ce44SJohn Forte }
2053fcf3ce44SJohn Forte 
2054fcf3ce44SJohn Forte /*
2055fcf3ce44SJohn Forte  * called from fcip_attach to initialize kstats for the link
2056fcf3ce44SJohn Forte  */
2057fcf3ce44SJohn Forte /* ARGSUSED */
2058fcf3ce44SJohn Forte static void
2059fcf3ce44SJohn Forte fcip_kstat_init(struct fcip *fptr)
2060fcf3ce44SJohn Forte {
2061fcf3ce44SJohn Forte 	int instance;
2062fcf3ce44SJohn Forte 	char buf[16];
2063fcf3ce44SJohn Forte 	struct fcipstat	*fcipstatp;
2064fcf3ce44SJohn Forte 
2065fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&fptr->fcip_mutex));
2066fcf3ce44SJohn Forte 
2067fcf3ce44SJohn Forte 	instance = ddi_get_instance(fptr->fcip_dip);
2068fcf3ce44SJohn Forte 	(void) sprintf(buf, "fcip%d", instance);
2069fcf3ce44SJohn Forte 
2070fcf3ce44SJohn Forte #ifdef	kstat
2071fcf3ce44SJohn Forte 	fptr->fcip_kstatp = kstat_create("fcip", instance, buf, "net",
2072fcf3ce44SJohn Forte 	    KSTAT_TYPE_NAMED,
2073fcf3ce44SJohn Forte 	    (sizeof (struct fcipstat)/ sizeof (kstat_named_t)),
2074fcf3ce44SJohn Forte 	    KSTAT_FLAG_PERSISTENT);
2075fcf3ce44SJohn Forte #else
2076fcf3ce44SJohn Forte 	fptr->fcip_kstatp = kstat_create("fcip", instance, buf, "net",
2077fcf3ce44SJohn Forte 	    KSTAT_TYPE_NAMED,
2078fcf3ce44SJohn Forte 	    (sizeof (struct fcipstat)/ sizeof (kstat_named_t)), 0);
2079fcf3ce44SJohn Forte #endif
2080fcf3ce44SJohn Forte 	if (fptr->fcip_kstatp == NULL) {
2081fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_INIT, (CE_WARN, "kstat created failed"));
2082fcf3ce44SJohn Forte 		return;
2083fcf3ce44SJohn Forte 	}
2084fcf3ce44SJohn Forte 
2085fcf3ce44SJohn Forte 	fcipstatp = (struct  fcipstat *)fptr->fcip_kstatp->ks_data;
2086fcf3ce44SJohn Forte 	kstat_named_init(&fcipstatp->fcips_ipackets,	"ipackets",
2087fcf3ce44SJohn Forte 		KSTAT_DATA_ULONG);
2088fcf3ce44SJohn Forte 	kstat_named_init(&fcipstatp->fcips_ierrors,	"ierrors",
2089fcf3ce44SJohn Forte 		KSTAT_DATA_ULONG);
2090fcf3ce44SJohn Forte 	kstat_named_init(&fcipstatp->fcips_opackets,	"opackets",
2091fcf3ce44SJohn Forte 		KSTAT_DATA_ULONG);
2092fcf3ce44SJohn Forte 	kstat_named_init(&fcipstatp->fcips_oerrors,	"oerrors",
2093fcf3ce44SJohn Forte 		KSTAT_DATA_ULONG);
2094fcf3ce44SJohn Forte 	kstat_named_init(&fcipstatp->fcips_collisions,	"collisions",
2095fcf3ce44SJohn Forte 		KSTAT_DATA_ULONG);
2096fcf3ce44SJohn Forte 	kstat_named_init(&fcipstatp->fcips_nocanput,	"nocanput",
2097fcf3ce44SJohn Forte 		KSTAT_DATA_ULONG);
2098fcf3ce44SJohn Forte 	kstat_named_init(&fcipstatp->fcips_allocbfail,	"allocbfail",
2099fcf3ce44SJohn Forte 		KSTAT_DATA_ULONG);
2100fcf3ce44SJohn Forte 
2101fcf3ce44SJohn Forte 	kstat_named_init(&fcipstatp->fcips_defer, "defer",
2102fcf3ce44SJohn Forte 		KSTAT_DATA_ULONG);
2103fcf3ce44SJohn Forte 	kstat_named_init(&fcipstatp->fcips_fram, "fram",
2104fcf3ce44SJohn Forte 		KSTAT_DATA_ULONG);
2105fcf3ce44SJohn Forte 	kstat_named_init(&fcipstatp->fcips_crc, "crc",
2106fcf3ce44SJohn Forte 		KSTAT_DATA_ULONG);
2107fcf3ce44SJohn Forte 	kstat_named_init(&fcipstatp->fcips_oflo, "oflo",
2108fcf3ce44SJohn Forte 		KSTAT_DATA_ULONG);
2109fcf3ce44SJohn Forte 	kstat_named_init(&fcipstatp->fcips_uflo, "uflo",
2110fcf3ce44SJohn Forte 		KSTAT_DATA_ULONG);
2111fcf3ce44SJohn Forte 	kstat_named_init(&fcipstatp->fcips_missed, "missed",
2112fcf3ce44SJohn Forte 		KSTAT_DATA_ULONG);
2113fcf3ce44SJohn Forte 	kstat_named_init(&fcipstatp->fcips_tlcol, "tlcol",
2114fcf3ce44SJohn Forte 		KSTAT_DATA_ULONG);
2115fcf3ce44SJohn Forte 	kstat_named_init(&fcipstatp->fcips_trtry, "trtry",
2116fcf3ce44SJohn Forte 		KSTAT_DATA_ULONG);
2117fcf3ce44SJohn Forte 	kstat_named_init(&fcipstatp->fcips_tnocar, "tnocar",
2118fcf3ce44SJohn Forte 		KSTAT_DATA_ULONG);
2119fcf3ce44SJohn Forte 	kstat_named_init(&fcipstatp->fcips_inits, "inits",
2120fcf3ce44SJohn Forte 		KSTAT_DATA_ULONG);
2121fcf3ce44SJohn Forte 	kstat_named_init(&fcipstatp->fcips_notbufs, "notbufs",
2122fcf3ce44SJohn Forte 		KSTAT_DATA_ULONG);
2123fcf3ce44SJohn Forte 	kstat_named_init(&fcipstatp->fcips_norbufs, "norbufs",
2124fcf3ce44SJohn Forte 		KSTAT_DATA_ULONG);
2125fcf3ce44SJohn Forte 	kstat_named_init(&fcipstatp->fcips_allocbfail, "allocbfail",
2126fcf3ce44SJohn Forte 		KSTAT_DATA_ULONG);
2127fcf3ce44SJohn Forte 
2128fcf3ce44SJohn Forte 	/*
2129fcf3ce44SJohn Forte 	 * required by kstat for MIB II objects(RFC 1213)
2130fcf3ce44SJohn Forte 	 */
2131fcf3ce44SJohn Forte 	kstat_named_init(&fcipstatp->fcips_rcvbytes, "fcips_rcvbytes",
2132fcf3ce44SJohn Forte 		KSTAT_DATA_ULONG);	/* # octets received */
2133fcf3ce44SJohn Forte 					/* MIB - ifInOctets */
2134fcf3ce44SJohn Forte 	kstat_named_init(&fcipstatp->fcips_xmtbytes, "fcips_xmtbytes",
2135fcf3ce44SJohn Forte 		KSTAT_DATA_ULONG);	/* # octets xmitted */
2136fcf3ce44SJohn Forte 					/* MIB - ifOutOctets */
2137fcf3ce44SJohn Forte 	kstat_named_init(&fcipstatp->fcips_multircv,	"fcips_multircv",
2138fcf3ce44SJohn Forte 		KSTAT_DATA_ULONG);	/* # multicast packets */
2139fcf3ce44SJohn Forte 					/* delivered to upper layer */
2140fcf3ce44SJohn Forte 					/* MIB - ifInNUcastPkts */
2141fcf3ce44SJohn Forte 	kstat_named_init(&fcipstatp->fcips_multixmt,	"fcips_multixmt",
2142fcf3ce44SJohn Forte 		KSTAT_DATA_ULONG);	/* # multicast packets */
2143fcf3ce44SJohn Forte 					/* requested to be sent */
2144fcf3ce44SJohn Forte 					/* MIB - ifOutNUcastPkts */
2145fcf3ce44SJohn Forte 	kstat_named_init(&fcipstatp->fcips_brdcstrcv, "fcips_brdcstrcv",
2146fcf3ce44SJohn Forte 		KSTAT_DATA_ULONG); /* # broadcast packets */
2147fcf3ce44SJohn Forte 					/* delivered to upper layer */
2148fcf3ce44SJohn Forte 					/* MIB - ifInNUcastPkts */
2149fcf3ce44SJohn Forte 	kstat_named_init(&fcipstatp->fcips_brdcstxmt, "fcips_brdcstxmt",
2150fcf3ce44SJohn Forte 		KSTAT_DATA_ULONG);	/* # broadcast packets */
2151fcf3ce44SJohn Forte 					/* requested to be sent */
2152fcf3ce44SJohn Forte 					/* MIB - ifOutNUcastPkts */
2153fcf3ce44SJohn Forte 	kstat_named_init(&fcipstatp->fcips_norcvbuf,	"fcips_norcvbuf",
2154fcf3ce44SJohn Forte 		KSTAT_DATA_ULONG);	/* # rcv packets discarded */
2155fcf3ce44SJohn Forte 					/* MIB - ifInDiscards */
2156fcf3ce44SJohn Forte 	kstat_named_init(&fcipstatp->fcips_noxmtbuf,	"fcips_noxmtbuf",
2157fcf3ce44SJohn Forte 		KSTAT_DATA_ULONG);	/* # xmt packets discarded */
2158fcf3ce44SJohn Forte 
2159fcf3ce44SJohn Forte 	fptr->fcip_kstatp->ks_update = fcip_stat_update;
2160fcf3ce44SJohn Forte 	fptr->fcip_kstatp->ks_private = (void *) fptr;
2161fcf3ce44SJohn Forte 	kstat_install(fptr->fcip_kstatp);
2162fcf3ce44SJohn Forte }
2163fcf3ce44SJohn Forte 
2164fcf3ce44SJohn Forte /*
2165fcf3ce44SJohn Forte  * Update the defined kstats for netstat et al to use
2166fcf3ce44SJohn Forte  */
2167fcf3ce44SJohn Forte /* ARGSUSED */
2168fcf3ce44SJohn Forte static int
2169fcf3ce44SJohn Forte fcip_stat_update(kstat_t *fcip_statp, int val)
2170fcf3ce44SJohn Forte {
2171fcf3ce44SJohn Forte 	struct fcipstat	*fcipstatp;
2172fcf3ce44SJohn Forte 	struct fcip	*fptr;
2173fcf3ce44SJohn Forte 
2174fcf3ce44SJohn Forte 	fptr = (struct fcip *)fcip_statp->ks_private;
2175fcf3ce44SJohn Forte 	fcipstatp = (struct fcipstat *)fcip_statp->ks_data;
2176fcf3ce44SJohn Forte 
2177fcf3ce44SJohn Forte 	if (val == KSTAT_WRITE) {
2178fcf3ce44SJohn Forte 		fptr->fcip_ipackets	= fcipstatp->fcips_ipackets.value.ul;
2179fcf3ce44SJohn Forte 		fptr->fcip_ierrors	= fcipstatp->fcips_ierrors.value.ul;
2180fcf3ce44SJohn Forte 		fptr->fcip_opackets	= fcipstatp->fcips_opackets.value.ul;
2181fcf3ce44SJohn Forte 		fptr->fcip_oerrors	= fcipstatp->fcips_oerrors.value.ul;
2182fcf3ce44SJohn Forte 		fptr->fcip_collisions	= fcipstatp->fcips_collisions.value.ul;
2183fcf3ce44SJohn Forte 		fptr->fcip_defer	= fcipstatp->fcips_defer.value.ul;
2184fcf3ce44SJohn Forte 		fptr->fcip_fram	= fcipstatp->fcips_fram.value.ul;
2185fcf3ce44SJohn Forte 		fptr->fcip_crc	= fcipstatp->fcips_crc.value.ul;
2186fcf3ce44SJohn Forte 		fptr->fcip_oflo	= fcipstatp->fcips_oflo.value.ul;
2187fcf3ce44SJohn Forte 		fptr->fcip_uflo	= fcipstatp->fcips_uflo.value.ul;
2188fcf3ce44SJohn Forte 		fptr->fcip_missed	= fcipstatp->fcips_missed.value.ul;
2189fcf3ce44SJohn Forte 		fptr->fcip_tlcol	= fcipstatp->fcips_tlcol.value.ul;
2190fcf3ce44SJohn Forte 		fptr->fcip_trtry	= fcipstatp->fcips_trtry.value.ul;
2191fcf3ce44SJohn Forte 		fptr->fcip_tnocar	= fcipstatp->fcips_tnocar.value.ul;
2192fcf3ce44SJohn Forte 		fptr->fcip_inits	= fcipstatp->fcips_inits.value.ul;
2193fcf3ce44SJohn Forte 		fptr->fcip_notbufs	= fcipstatp->fcips_notbufs.value.ul;
2194fcf3ce44SJohn Forte 		fptr->fcip_norbufs	= fcipstatp->fcips_norbufs.value.ul;
2195fcf3ce44SJohn Forte 		fptr->fcip_nocanput	= fcipstatp->fcips_nocanput.value.ul;
2196fcf3ce44SJohn Forte 		fptr->fcip_allocbfail	= fcipstatp->fcips_allocbfail.value.ul;
2197fcf3ce44SJohn Forte 		fptr->fcip_rcvbytes	= fcipstatp->fcips_rcvbytes.value.ul;
2198fcf3ce44SJohn Forte 		fptr->fcip_xmtbytes	= fcipstatp->fcips_xmtbytes.value.ul;
2199fcf3ce44SJohn Forte 		fptr->fcip_multircv	= fcipstatp->fcips_multircv.value.ul;
2200fcf3ce44SJohn Forte 		fptr->fcip_multixmt	= fcipstatp->fcips_multixmt.value.ul;
2201fcf3ce44SJohn Forte 		fptr->fcip_brdcstrcv	= fcipstatp->fcips_brdcstrcv.value.ul;
2202fcf3ce44SJohn Forte 		fptr->fcip_norcvbuf	= fcipstatp->fcips_norcvbuf.value.ul;
2203fcf3ce44SJohn Forte 		fptr->fcip_noxmtbuf	= fcipstatp->fcips_noxmtbuf.value.ul;
2204fcf3ce44SJohn Forte 		fptr->fcip_allocbfail	= fcipstatp->fcips_allocbfail.value.ul;
2205fcf3ce44SJohn Forte 		fptr->fcip_allocbfail	= fcipstatp->fcips_allocbfail.value.ul;
2206fcf3ce44SJohn Forte 		fptr->fcip_allocbfail	= fcipstatp->fcips_allocbfail.value.ul;
2207fcf3ce44SJohn Forte 		fptr->fcip_allocbfail	= fcipstatp->fcips_allocbfail.value.ul;
2208fcf3ce44SJohn Forte 		fptr->fcip_allocbfail	= fcipstatp->fcips_allocbfail.value.ul;
2209fcf3ce44SJohn Forte 		fptr->fcip_allocbfail	= fcipstatp->fcips_allocbfail.value.ul;
2210fcf3ce44SJohn Forte 		fptr->fcip_allocbfail	= fcipstatp->fcips_allocbfail.value.ul;
2211fcf3ce44SJohn Forte 		fptr->fcip_allocbfail	= fcipstatp->fcips_allocbfail.value.ul;
2212fcf3ce44SJohn Forte 
2213fcf3ce44SJohn Forte 	} else {
2214fcf3ce44SJohn Forte 		fcipstatp->fcips_ipackets.value.ul	= fptr->fcip_ipackets;
2215fcf3ce44SJohn Forte 		fcipstatp->fcips_ierrors.value.ul	= fptr->fcip_ierrors;
2216fcf3ce44SJohn Forte 		fcipstatp->fcips_opackets.value.ul	= fptr->fcip_opackets;
2217fcf3ce44SJohn Forte 		fcipstatp->fcips_oerrors.value.ul	= fptr->fcip_oerrors;
2218fcf3ce44SJohn Forte 		fcipstatp->fcips_collisions.value.ul	= fptr->fcip_collisions;
2219fcf3ce44SJohn Forte 		fcipstatp->fcips_nocanput.value.ul	= fptr->fcip_nocanput;
2220fcf3ce44SJohn Forte 		fcipstatp->fcips_allocbfail.value.ul	= fptr->fcip_allocbfail;
2221fcf3ce44SJohn Forte 		fcipstatp->fcips_defer.value.ul	= fptr->fcip_defer;
2222fcf3ce44SJohn Forte 		fcipstatp->fcips_fram.value.ul	= fptr->fcip_fram;
2223fcf3ce44SJohn Forte 		fcipstatp->fcips_crc.value.ul	= fptr->fcip_crc;
2224fcf3ce44SJohn Forte 		fcipstatp->fcips_oflo.value.ul	= fptr->fcip_oflo;
2225fcf3ce44SJohn Forte 		fcipstatp->fcips_uflo.value.ul	= fptr->fcip_uflo;
2226fcf3ce44SJohn Forte 		fcipstatp->fcips_missed.value.ul	= fptr->fcip_missed;
2227fcf3ce44SJohn Forte 		fcipstatp->fcips_tlcol.value.ul	= fptr->fcip_tlcol;
2228fcf3ce44SJohn Forte 		fcipstatp->fcips_trtry.value.ul	= fptr->fcip_trtry;
2229fcf3ce44SJohn Forte 		fcipstatp->fcips_tnocar.value.ul	= fptr->fcip_tnocar;
2230fcf3ce44SJohn Forte 		fcipstatp->fcips_inits.value.ul	= fptr->fcip_inits;
2231fcf3ce44SJohn Forte 		fcipstatp->fcips_norbufs.value.ul	= fptr->fcip_norbufs;
2232fcf3ce44SJohn Forte 		fcipstatp->fcips_notbufs.value.ul	= fptr->fcip_notbufs;
2233fcf3ce44SJohn Forte 		fcipstatp->fcips_rcvbytes.value.ul	= fptr->fcip_rcvbytes;
2234fcf3ce44SJohn Forte 		fcipstatp->fcips_xmtbytes.value.ul	= fptr->fcip_xmtbytes;
2235fcf3ce44SJohn Forte 		fcipstatp->fcips_multircv.value.ul	= fptr->fcip_multircv;
2236fcf3ce44SJohn Forte 		fcipstatp->fcips_multixmt.value.ul	= fptr->fcip_multixmt;
2237fcf3ce44SJohn Forte 		fcipstatp->fcips_brdcstrcv.value.ul	= fptr->fcip_brdcstrcv;
2238fcf3ce44SJohn Forte 		fcipstatp->fcips_brdcstxmt.value.ul	= fptr->fcip_brdcstxmt;
2239fcf3ce44SJohn Forte 		fcipstatp->fcips_norcvbuf.value.ul	= fptr->fcip_norcvbuf;
2240fcf3ce44SJohn Forte 		fcipstatp->fcips_noxmtbuf.value.ul	= fptr->fcip_noxmtbuf;
2241fcf3ce44SJohn Forte 
2242fcf3ce44SJohn Forte 	}
2243fcf3ce44SJohn Forte 	return (0);
2244fcf3ce44SJohn Forte }
2245fcf3ce44SJohn Forte 
2246fcf3ce44SJohn Forte 
2247fcf3ce44SJohn Forte /*
2248fcf3ce44SJohn Forte  * fcip_statec_cb: handles all required state change callback notifications
2249fcf3ce44SJohn Forte  * it receives from the transport
2250fcf3ce44SJohn Forte  */
2251fcf3ce44SJohn Forte /* ARGSUSED */
2252fcf3ce44SJohn Forte static void
2253fcf3ce44SJohn Forte fcip_statec_cb(opaque_t ulp_handle, opaque_t phandle,
2254fcf3ce44SJohn Forte     uint32_t port_state, uint32_t port_top, fc_portmap_t changelist[],
2255fcf3ce44SJohn Forte     uint32_t listlen, uint32_t sid)
2256fcf3ce44SJohn Forte {
2257fcf3ce44SJohn Forte 	fcip_port_info_t	*fport;
2258fcf3ce44SJohn Forte 	struct fcip 		*fptr;
2259fcf3ce44SJohn Forte 	struct fcipstr		*slp;
2260fcf3ce44SJohn Forte 	queue_t			*wrq;
2261fcf3ce44SJohn Forte 	int			instance;
2262fcf3ce44SJohn Forte 	int 			index;
2263fcf3ce44SJohn Forte 	struct fcip_routing_table 	*frtp;
2264fcf3ce44SJohn Forte 
2265fcf3ce44SJohn Forte 	fport = fcip_get_port(phandle);
2266fcf3ce44SJohn Forte 
2267fcf3ce44SJohn Forte 	if (fport == NULL) {
2268fcf3ce44SJohn Forte 		return;
2269fcf3ce44SJohn Forte 	}
2270fcf3ce44SJohn Forte 
2271fcf3ce44SJohn Forte 	fptr = fport->fcipp_fcip;
2272fcf3ce44SJohn Forte 	ASSERT(fptr != NULL);
2273fcf3ce44SJohn Forte 
2274fcf3ce44SJohn Forte 	if (fptr == NULL) {
2275fcf3ce44SJohn Forte 		return;
2276fcf3ce44SJohn Forte 	}
2277fcf3ce44SJohn Forte 
2278fcf3ce44SJohn Forte 	instance = ddi_get_instance(fport->fcipp_dip);
2279fcf3ce44SJohn Forte 
2280fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_4((fcip_statec_cb, "fcip io", /* CSTYLED */,
2281fcf3ce44SJohn Forte 		tnf_string, msg, "state change callback",
2282fcf3ce44SJohn Forte 		tnf_uint, instance, instance,
2283fcf3ce44SJohn Forte 		tnf_uint, S_ID, sid,
2284fcf3ce44SJohn Forte 		tnf_int, count, listlen));
2285fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_ELS,
2286fcf3ce44SJohn Forte 	    (CE_NOTE, "fcip%d, state change callback: state:0x%x, "
2287fcf3ce44SJohn Forte 	    "S_ID:0x%x, count:0x%x", instance, port_state, sid, listlen));
2288fcf3ce44SJohn Forte 
2289fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_mutex);
2290fcf3ce44SJohn Forte 
2291fcf3ce44SJohn Forte 	if ((fptr->fcip_flags & (FCIP_DETACHING | FCIP_DETACHED)) ||
2292fcf3ce44SJohn Forte 	    (fptr->fcip_flags & (FCIP_SUSPENDED | FCIP_POWER_DOWN))) {
2293fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_mutex);
2294fcf3ce44SJohn Forte 		return;
2295fcf3ce44SJohn Forte 	}
2296fcf3ce44SJohn Forte 
2297fcf3ce44SJohn Forte 	/*
2298fcf3ce44SJohn Forte 	 * set fcip flags to indicate we are in the middle of a
2299fcf3ce44SJohn Forte 	 * state change callback so we can wait till the statechange
2300fcf3ce44SJohn Forte 	 * is handled before succeeding/failing the SUSPEND/POWER DOWN.
2301fcf3ce44SJohn Forte 	 */
2302fcf3ce44SJohn Forte 	fptr->fcip_flags |= FCIP_IN_SC_CB;
2303fcf3ce44SJohn Forte 
2304fcf3ce44SJohn Forte 	fport->fcipp_pstate = port_state;
2305fcf3ce44SJohn Forte 
2306fcf3ce44SJohn Forte 	/*
2307fcf3ce44SJohn Forte 	 * Check if topology changed. If Yes - Modify the broadcast
2308fcf3ce44SJohn Forte 	 * RTE entries to understand the new broadcast D_IDs
2309fcf3ce44SJohn Forte 	 */
2310fcf3ce44SJohn Forte 	if (fport->fcipp_topology != port_top &&
2311fcf3ce44SJohn Forte 	    (port_top != FC_TOP_UNKNOWN)) {
2312fcf3ce44SJohn Forte 		/* REMOVE later */
2313fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_ELS, (CE_NOTE,
2314fcf3ce44SJohn Forte 		    "topology changed: Old topology: 0x%x New topology 0x%x",
2315fcf3ce44SJohn Forte 		    fport->fcipp_topology, port_top));
2316fcf3ce44SJohn Forte 		/*
2317fcf3ce44SJohn Forte 		 * If topology changed - attempt a rediscovery of
2318fcf3ce44SJohn Forte 		 * devices. Helps specially in Fabric/Public loops
2319fcf3ce44SJohn Forte 		 * and if on_demand_node_creation is disabled
2320fcf3ce44SJohn Forte 		 */
2321fcf3ce44SJohn Forte 		fport->fcipp_topology = port_top;
2322fcf3ce44SJohn Forte 		fcip_handle_topology(fptr);
2323fcf3ce44SJohn Forte 	}
2324fcf3ce44SJohn Forte 
2325fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_mutex);
2326fcf3ce44SJohn Forte 
2327fcf3ce44SJohn Forte 	switch (FC_PORT_STATE_MASK(port_state)) {
2328fcf3ce44SJohn Forte 	case FC_STATE_ONLINE:
2329fcf3ce44SJohn Forte 	/* FALLTHROUGH */
2330fcf3ce44SJohn Forte 	case FC_STATE_LIP:
2331fcf3ce44SJohn Forte 	/* FALLTHROUGH */
2332fcf3ce44SJohn Forte 	case FC_STATE_LIP_LBIT_SET:
2333fcf3ce44SJohn Forte 
2334fcf3ce44SJohn Forte 		/*
2335fcf3ce44SJohn Forte 		 * nothing to do here actually other than if we
2336fcf3ce44SJohn Forte 		 * were actually logged onto a port in the devlist
2337fcf3ce44SJohn Forte 		 * (which indicates active communication between
2338fcf3ce44SJohn Forte 		 * the host port and the port in the changelist).
2339fcf3ce44SJohn Forte 		 * If however we are in a private loop or point to
2340fcf3ce44SJohn Forte 		 * point mode, we need to check for any IP capable
2341fcf3ce44SJohn Forte 		 * ports and update our routing table.
2342fcf3ce44SJohn Forte 		 */
2343fcf3ce44SJohn Forte 		switch (port_top) {
2344fcf3ce44SJohn Forte 		case FC_TOP_FABRIC:
2345fcf3ce44SJohn Forte 			/*
2346fcf3ce44SJohn Forte 			 * This indicates a fabric port with a NameServer.
2347fcf3ce44SJohn Forte 			 * Check the devlist to see if we are in active
2348fcf3ce44SJohn Forte 			 * communication with a port on the devlist.
2349fcf3ce44SJohn Forte 			 */
2350fcf3ce44SJohn Forte 			FCIP_DEBUG(FCIP_DEBUG_ELS, (CE_NOTE,
2351fcf3ce44SJohn Forte 			    "Statec_cb: fabric topology"));
2352fcf3ce44SJohn Forte 			fcip_rt_update(fptr, changelist, listlen);
2353fcf3ce44SJohn Forte 			break;
2354fcf3ce44SJohn Forte 		case FC_TOP_NO_NS:
2355fcf3ce44SJohn Forte 			/*
2356fcf3ce44SJohn Forte 			 * No nameserver - so treat it like a Private loop
2357fcf3ce44SJohn Forte 			 * or point to point topology and get a map of
2358fcf3ce44SJohn Forte 			 * devices on the link and get IP capable ports to
2359fcf3ce44SJohn Forte 			 * to update the routing table.
2360fcf3ce44SJohn Forte 			 */
2361fcf3ce44SJohn Forte 			FCIP_DEBUG(FCIP_DEBUG_ELS,
2362fcf3ce44SJohn Forte 			    (CE_NOTE, "Statec_cb: NO_NS topology"));
2363fcf3ce44SJohn Forte 		/* FALLTHROUGH */
2364fcf3ce44SJohn Forte 		case FC_TOP_PRIVATE_LOOP:
2365fcf3ce44SJohn Forte 			FCIP_DEBUG(FCIP_DEBUG_ELS, (CE_NOTE,
2366fcf3ce44SJohn Forte 			    "Statec_cb: Pvt_Loop topology"));
2367fcf3ce44SJohn Forte 		/* FALLTHROUGH */
2368fcf3ce44SJohn Forte 		case FC_TOP_PT_PT:
2369fcf3ce44SJohn Forte 			/*
2370fcf3ce44SJohn Forte 			 * call get_port_map() and update routing table
2371fcf3ce44SJohn Forte 			 */
2372fcf3ce44SJohn Forte 			fcip_rt_update(fptr, changelist, listlen);
2373fcf3ce44SJohn Forte 			break;
2374fcf3ce44SJohn Forte 		default:
2375fcf3ce44SJohn Forte 			FCIP_DEBUG(FCIP_DEBUG_ELS,
2376fcf3ce44SJohn Forte 			    (CE_NOTE, "Statec_cb: Unknown topology"));
2377fcf3ce44SJohn Forte 		}
2378fcf3ce44SJohn Forte 
2379fcf3ce44SJohn Forte 		/*
2380fcf3ce44SJohn Forte 		 * We should now enable the Queues and permit I/Os
2381fcf3ce44SJohn Forte 		 * to flow through downstream. The update of routing
2382fcf3ce44SJohn Forte 		 * table should have flushed out any port entries that
2383fcf3ce44SJohn Forte 		 * don't exist or are not available after the state change
2384fcf3ce44SJohn Forte 		 */
2385fcf3ce44SJohn Forte 		mutex_enter(&fptr->fcip_mutex);
2386fcf3ce44SJohn Forte 		fptr->fcip_port_state = FCIP_PORT_ONLINE;
2387fcf3ce44SJohn Forte 		if (fptr->fcip_flags & FCIP_LINK_DOWN) {
2388fcf3ce44SJohn Forte 			fptr->fcip_flags &= ~FCIP_LINK_DOWN;
2389fcf3ce44SJohn Forte 		}
2390fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_mutex);
2391fcf3ce44SJohn Forte 
2392fcf3ce44SJohn Forte 		/*
2393fcf3ce44SJohn Forte 		 * Enable write queues
2394fcf3ce44SJohn Forte 		 */
2395fcf3ce44SJohn Forte 		rw_enter(&fcipstruplock, RW_READER);
2396fcf3ce44SJohn Forte 		for (slp = fcipstrup; slp != NULL; slp = slp->sl_nextp) {
2397fcf3ce44SJohn Forte 			if (slp && slp->sl_fcip == fptr) {
2398fcf3ce44SJohn Forte 				wrq = WR(slp->sl_rq);
2399fcf3ce44SJohn Forte 				if (wrq->q_flag & QFULL) {
2400fcf3ce44SJohn Forte 					qenable(wrq);
2401fcf3ce44SJohn Forte 				}
2402fcf3ce44SJohn Forte 			}
2403fcf3ce44SJohn Forte 		}
2404fcf3ce44SJohn Forte 		rw_exit(&fcipstruplock);
2405fcf3ce44SJohn Forte 		break;
2406fcf3ce44SJohn Forte 	case FC_STATE_OFFLINE:
2407fcf3ce44SJohn Forte 		/*
2408fcf3ce44SJohn Forte 		 * mark the port_state OFFLINE and wait for it to
2409fcf3ce44SJohn Forte 		 * become online. Any new messages in this state will
2410fcf3ce44SJohn Forte 		 * simply be queued back up. If the port does not
2411fcf3ce44SJohn Forte 		 * come online in a short while, we can begin failing
2412fcf3ce44SJohn Forte 		 * messages and flush the routing table
2413fcf3ce44SJohn Forte 		 */
2414fcf3ce44SJohn Forte 		mutex_enter(&fptr->fcip_mutex);
2415fcf3ce44SJohn Forte 		fptr->fcip_mark_offline = fptr->fcip_timeout_ticks +
2416fcf3ce44SJohn Forte 		    FCIP_OFFLINE_TIMEOUT;
2417fcf3ce44SJohn Forte 		fptr->fcip_port_state = FCIP_PORT_OFFLINE;
2418fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_mutex);
2419fcf3ce44SJohn Forte 
2420fcf3ce44SJohn Forte 		/*
2421fcf3ce44SJohn Forte 		 * Mark all Routing table entries as invalid to prevent
2422fcf3ce44SJohn Forte 		 * any commands from trickling through to ports that
2423fcf3ce44SJohn Forte 		 * have disappeared from under us
2424fcf3ce44SJohn Forte 		 */
2425fcf3ce44SJohn Forte 		mutex_enter(&fptr->fcip_rt_mutex);
2426fcf3ce44SJohn Forte 		for (index = 0; index < FCIP_RT_HASH_ELEMS; index++) {
2427fcf3ce44SJohn Forte 			frtp = fptr->fcip_rtable[index];
2428fcf3ce44SJohn Forte 			while (frtp) {
2429fcf3ce44SJohn Forte 				frtp->fcipr_state = PORT_DEVICE_INVALID;
2430fcf3ce44SJohn Forte 				frtp = frtp->fcipr_next;
2431fcf3ce44SJohn Forte 			}
2432fcf3ce44SJohn Forte 		}
2433fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_rt_mutex);
2434fcf3ce44SJohn Forte 
2435fcf3ce44SJohn Forte 		break;
2436fcf3ce44SJohn Forte 
2437fcf3ce44SJohn Forte 	case FC_STATE_RESET_REQUESTED:
2438fcf3ce44SJohn Forte 		/*
2439fcf3ce44SJohn Forte 		 * Release all Unsolicited buffers back to transport/FCA.
2440fcf3ce44SJohn Forte 		 * This also means the port state is marked offline - so
2441fcf3ce44SJohn Forte 		 * we may have to do what OFFLINE state requires us to do.
2442fcf3ce44SJohn Forte 		 * Care must be taken to wait for any active unsolicited
2443fcf3ce44SJohn Forte 		 * buffer with the other Streams modules - so wait for
2444fcf3ce44SJohn Forte 		 * a freeb if the unsolicited buffer is passed back all
2445fcf3ce44SJohn Forte 		 * the way upstream.
2446fcf3ce44SJohn Forte 		 */
2447fcf3ce44SJohn Forte 		mutex_enter(&fptr->fcip_mutex);
2448fcf3ce44SJohn Forte 
2449fcf3ce44SJohn Forte #ifdef FCIP_ESBALLOC
2450fcf3ce44SJohn Forte 		while (fptr->fcip_ub_upstream) {
2451fcf3ce44SJohn Forte 			cv_wait(&fptr->fcip_ub_cv, &fptr->fcip_mutex);
2452fcf3ce44SJohn Forte 		}
2453fcf3ce44SJohn Forte #endif	/* FCIP_ESBALLOC */
2454fcf3ce44SJohn Forte 
2455fcf3ce44SJohn Forte 		fptr->fcip_mark_offline = fptr->fcip_timeout_ticks +
2456fcf3ce44SJohn Forte 		    FCIP_OFFLINE_TIMEOUT;
2457fcf3ce44SJohn Forte 		fptr->fcip_port_state = FCIP_PORT_OFFLINE;
2458fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_mutex);
2459fcf3ce44SJohn Forte 		break;
2460fcf3ce44SJohn Forte 
2461fcf3ce44SJohn Forte 	case FC_STATE_DEVICE_CHANGE:
2462fcf3ce44SJohn Forte 		if (listlen) {
2463fcf3ce44SJohn Forte 			fcip_rt_update(fptr, changelist, listlen);
2464fcf3ce44SJohn Forte 		}
2465fcf3ce44SJohn Forte 		break;
2466fcf3ce44SJohn Forte 	case FC_STATE_RESET:
2467fcf3ce44SJohn Forte 		/*
2468fcf3ce44SJohn Forte 		 * Not much to do I guess - wait for port to become
2469fcf3ce44SJohn Forte 		 * ONLINE. If the port doesn't become online in a short
2470fcf3ce44SJohn Forte 		 * while, the upper layers abort any request themselves.
2471fcf3ce44SJohn Forte 		 * We can just putback the messages in the streams queues
2472fcf3ce44SJohn Forte 		 * if the link is offline
2473fcf3ce44SJohn Forte 		 */
2474fcf3ce44SJohn Forte 		break;
2475fcf3ce44SJohn Forte 	}
2476fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_mutex);
2477fcf3ce44SJohn Forte 	fptr->fcip_flags &= ~(FCIP_IN_SC_CB);
2478fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_mutex);
2479fcf3ce44SJohn Forte }
2480fcf3ce44SJohn Forte 
2481fcf3ce44SJohn Forte /*
2482fcf3ce44SJohn Forte  * Given a port handle, return the fcip_port_info structure corresponding
2483fcf3ce44SJohn Forte  * to that port handle. The transport allocates and communicates with
2484fcf3ce44SJohn Forte  * ULPs using port handles
2485fcf3ce44SJohn Forte  */
2486fcf3ce44SJohn Forte static fcip_port_info_t *
2487fcf3ce44SJohn Forte fcip_get_port(opaque_t phandle)
2488fcf3ce44SJohn Forte {
2489fcf3ce44SJohn Forte 	fcip_port_info_t *fport;
2490fcf3ce44SJohn Forte 
2491fcf3ce44SJohn Forte 	ASSERT(phandle != NULL);
2492fcf3ce44SJohn Forte 
2493fcf3ce44SJohn Forte 	mutex_enter(&fcip_global_mutex);
2494fcf3ce44SJohn Forte 	fport = fcip_port_head;
2495fcf3ce44SJohn Forte 
2496fcf3ce44SJohn Forte 	while (fport != NULL) {
2497fcf3ce44SJohn Forte 		if (fport->fcipp_handle == phandle) {
2498fcf3ce44SJohn Forte 			/* found */
2499fcf3ce44SJohn Forte 			break;
2500fcf3ce44SJohn Forte 		}
2501fcf3ce44SJohn Forte 		fport = fport->fcipp_next;
2502fcf3ce44SJohn Forte 	}
2503fcf3ce44SJohn Forte 
2504fcf3ce44SJohn Forte 	mutex_exit(&fcip_global_mutex);
2505fcf3ce44SJohn Forte 
2506fcf3ce44SJohn Forte 	return (fport);
2507fcf3ce44SJohn Forte }
2508fcf3ce44SJohn Forte 
2509fcf3ce44SJohn Forte /*
2510fcf3ce44SJohn Forte  * Handle inbound ELS requests received by the transport. We are only
2511fcf3ce44SJohn Forte  * intereseted in FARP/InARP mostly.
2512fcf3ce44SJohn Forte  */
2513fcf3ce44SJohn Forte /* ARGSUSED */
2514fcf3ce44SJohn Forte static int
2515fcf3ce44SJohn Forte fcip_els_cb(opaque_t ulp_handle, opaque_t phandle,
2516fcf3ce44SJohn Forte     fc_unsol_buf_t *buf, uint32_t claimed)
2517fcf3ce44SJohn Forte {
2518fcf3ce44SJohn Forte 	fcip_port_info_t	*fport;
2519fcf3ce44SJohn Forte 	struct fcip 		*fptr;
2520fcf3ce44SJohn Forte 	int			instance;
2521fcf3ce44SJohn Forte 	uchar_t			r_ctl;
2522fcf3ce44SJohn Forte 	uchar_t			ls_code;
2523fcf3ce44SJohn Forte 	la_els_farp_t		farp_cmd;
2524fcf3ce44SJohn Forte 	la_els_farp_t		*fcmd;
2525fcf3ce44SJohn Forte 	int			rval = FC_UNCLAIMED;
2526fcf3ce44SJohn Forte 
2527fcf3ce44SJohn Forte 	fport = fcip_get_port(phandle);
2528fcf3ce44SJohn Forte 	if (fport == NULL) {
2529fcf3ce44SJohn Forte 		return (FC_UNCLAIMED);
2530fcf3ce44SJohn Forte 	}
2531fcf3ce44SJohn Forte 
2532fcf3ce44SJohn Forte 	fptr = fport->fcipp_fcip;
2533fcf3ce44SJohn Forte 	ASSERT(fptr != NULL);
2534fcf3ce44SJohn Forte 	if (fptr == NULL) {
2535fcf3ce44SJohn Forte 		return (FC_UNCLAIMED);
2536fcf3ce44SJohn Forte 	}
2537fcf3ce44SJohn Forte 
2538fcf3ce44SJohn Forte 	instance = ddi_get_instance(fport->fcipp_dip);
2539fcf3ce44SJohn Forte 
2540fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_mutex);
2541fcf3ce44SJohn Forte 	if ((fptr->fcip_flags & (FCIP_DETACHING | FCIP_DETACHED)) ||
2542fcf3ce44SJohn Forte 	    (fptr->fcip_flags & (FCIP_SUSPENDED | FCIP_POWER_DOWN))) {
2543fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_mutex);
2544fcf3ce44SJohn Forte 		return (FC_UNCLAIMED);
2545fcf3ce44SJohn Forte 	}
2546fcf3ce44SJohn Forte 
2547fcf3ce44SJohn Forte 	/*
2548fcf3ce44SJohn Forte 	 * set fcip flags to indicate we are in the middle of a
2549fcf3ce44SJohn Forte 	 * ELS callback so we can wait till the statechange
2550fcf3ce44SJohn Forte 	 * is handled before succeeding/failing the SUSPEND/POWER DOWN.
2551fcf3ce44SJohn Forte 	 */
2552fcf3ce44SJohn Forte 	fptr->fcip_flags |= FCIP_IN_ELS_CB;
2553fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_mutex);
2554fcf3ce44SJohn Forte 
2555fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_2((fcip_els_cb, "fcip io", /* CSTYLED */,
2556fcf3ce44SJohn Forte 		tnf_string, msg, "ELS callback",
2557fcf3ce44SJohn Forte 		tnf_uint, instance, instance));
2558fcf3ce44SJohn Forte 
2559fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_ELS,
2560fcf3ce44SJohn Forte 	    (CE_NOTE, "fcip%d, ELS callback , ", instance));
2561fcf3ce44SJohn Forte 
2562fcf3ce44SJohn Forte 	r_ctl = buf->ub_frame.r_ctl;
2563fcf3ce44SJohn Forte 	switch (r_ctl & R_CTL_ROUTING) {
2564fcf3ce44SJohn Forte 	case R_CTL_EXTENDED_SVC:
2565fcf3ce44SJohn Forte 		if (r_ctl == R_CTL_ELS_REQ) {
2566fcf3ce44SJohn Forte 			ls_code = buf->ub_buffer[0];
2567fcf3ce44SJohn Forte 			if (ls_code == LA_ELS_FARP_REQ) {
2568fcf3ce44SJohn Forte 				/*
2569fcf3ce44SJohn Forte 				 * Inbound FARP broadcast request
2570fcf3ce44SJohn Forte 				 */
2571fcf3ce44SJohn Forte 				if (buf->ub_bufsize != sizeof (la_els_farp_t)) {
2572fcf3ce44SJohn Forte 					FCIP_DEBUG(FCIP_DEBUG_ELS, (CE_WARN,
2573fcf3ce44SJohn Forte 					    "Invalid FARP req buffer size "
2574fcf3ce44SJohn Forte 					    "expected 0x%lx, got 0x%x",
2575fcf3ce44SJohn Forte 					    (long)(sizeof (la_els_farp_t)),
2576fcf3ce44SJohn Forte 					    buf->ub_bufsize));
2577fcf3ce44SJohn Forte 					rval = FC_UNCLAIMED;
2578fcf3ce44SJohn Forte 					goto els_cb_done;
2579fcf3ce44SJohn Forte 				}
2580fcf3ce44SJohn Forte 				fcmd = (la_els_farp_t *)buf;
2581fcf3ce44SJohn Forte 				if (fcip_wwn_compare(&fcmd->resp_nwwn,
2582fcf3ce44SJohn Forte 				    &fport->fcipp_nwwn,
2583fcf3ce44SJohn Forte 				    FCIP_COMPARE_NWWN) != 0) {
2584fcf3ce44SJohn Forte 					rval = FC_UNCLAIMED;
2585fcf3ce44SJohn Forte 					goto els_cb_done;
2586fcf3ce44SJohn Forte 				}
2587fcf3ce44SJohn Forte 				/*
2588fcf3ce44SJohn Forte 				 * copy the FARP request and release the
2589fcf3ce44SJohn Forte 				 * unsolicited buffer
2590fcf3ce44SJohn Forte 				 */
2591fcf3ce44SJohn Forte 				fcmd = &farp_cmd;
2592fcf3ce44SJohn Forte 				bcopy((void *)buf, (void *)fcmd,
2593fcf3ce44SJohn Forte 				    sizeof (la_els_farp_t));
2594fcf3ce44SJohn Forte 				(void) fc_ulp_ubrelease(fport->fcipp_handle, 1,
2595fcf3ce44SJohn Forte 				    &buf->ub_token);
2596fcf3ce44SJohn Forte 
2597fcf3ce44SJohn Forte 				if (fcip_farp_supported &&
2598fcf3ce44SJohn Forte 				    fcip_handle_farp_request(fptr, fcmd) ==
2599fcf3ce44SJohn Forte 				    FC_SUCCESS) {
2600fcf3ce44SJohn Forte 					/*
2601fcf3ce44SJohn Forte 					 * We successfully sent out a FARP
2602fcf3ce44SJohn Forte 					 * reply to the requesting port
2603fcf3ce44SJohn Forte 					 */
2604fcf3ce44SJohn Forte 					rval = FC_SUCCESS;
2605fcf3ce44SJohn Forte 					goto els_cb_done;
2606fcf3ce44SJohn Forte 				} else {
2607fcf3ce44SJohn Forte 					rval = FC_UNCLAIMED;
2608fcf3ce44SJohn Forte 					goto els_cb_done;
2609fcf3ce44SJohn Forte 				}
2610fcf3ce44SJohn Forte 			}
2611fcf3ce44SJohn Forte 		} else if (r_ctl == R_CTL_ELS_RSP) {
2612fcf3ce44SJohn Forte 			ls_code = buf->ub_buffer[0];
2613fcf3ce44SJohn Forte 			if (ls_code == LA_ELS_FARP_REPLY) {
2614fcf3ce44SJohn Forte 				/*
2615fcf3ce44SJohn Forte 				 * We received a REPLY to our FARP request
2616fcf3ce44SJohn Forte 				 */
2617fcf3ce44SJohn Forte 				if (buf->ub_bufsize != sizeof (la_els_farp_t)) {
2618fcf3ce44SJohn Forte 					FCIP_DEBUG(FCIP_DEBUG_ELS, (CE_WARN,
2619fcf3ce44SJohn Forte 					    "Invalid FARP req buffer size "
2620fcf3ce44SJohn Forte 					    "expected 0x%lx, got 0x%x",
2621fcf3ce44SJohn Forte 					    (long)(sizeof (la_els_farp_t)),
2622fcf3ce44SJohn Forte 					    buf->ub_bufsize));
2623fcf3ce44SJohn Forte 					rval = FC_UNCLAIMED;
2624fcf3ce44SJohn Forte 					goto els_cb_done;
2625fcf3ce44SJohn Forte 				}
2626fcf3ce44SJohn Forte 				fcmd = &farp_cmd;
2627fcf3ce44SJohn Forte 				bcopy((void *)buf, (void *)fcmd,
2628fcf3ce44SJohn Forte 				    sizeof (la_els_farp_t));
2629fcf3ce44SJohn Forte 				(void) fc_ulp_ubrelease(fport->fcipp_handle, 1,
2630fcf3ce44SJohn Forte 				    &buf->ub_token);
2631fcf3ce44SJohn Forte 				if (fcip_farp_supported &&
2632fcf3ce44SJohn Forte 				    fcip_handle_farp_response(fptr, fcmd) ==
2633fcf3ce44SJohn Forte 				    FC_SUCCESS) {
2634fcf3ce44SJohn Forte 					FCIP_DEBUG(FCIP_DEBUG_ELS, (CE_NOTE,
2635fcf3ce44SJohn Forte 					    "Successfully recevied a FARP "
2636fcf3ce44SJohn Forte 					    "response"));
2637fcf3ce44SJohn Forte 					mutex_enter(&fptr->fcip_mutex);
2638fcf3ce44SJohn Forte 					fptr->fcip_farp_rsp_flag = 1;
2639fcf3ce44SJohn Forte 					cv_signal(&fptr->fcip_farp_cv);
2640fcf3ce44SJohn Forte 					mutex_exit(&fptr->fcip_mutex);
2641fcf3ce44SJohn Forte 					rval = FC_SUCCESS;
2642fcf3ce44SJohn Forte 					goto els_cb_done;
2643fcf3ce44SJohn Forte 				} else {
2644fcf3ce44SJohn Forte 					FCIP_DEBUG(FCIP_DEBUG_ELS, (CE_WARN,
2645fcf3ce44SJohn Forte 					    "Unable to handle a FARP response "
2646fcf3ce44SJohn Forte 					    "receive"));
2647fcf3ce44SJohn Forte 					rval = FC_UNCLAIMED;
2648fcf3ce44SJohn Forte 					goto els_cb_done;
2649fcf3ce44SJohn Forte 				}
2650fcf3ce44SJohn Forte 			}
2651fcf3ce44SJohn Forte 		}
2652fcf3ce44SJohn Forte 		break;
2653fcf3ce44SJohn Forte 	default:
2654fcf3ce44SJohn Forte 		break;
2655fcf3ce44SJohn Forte 	}
2656fcf3ce44SJohn Forte els_cb_done:
2657fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_mutex);
2658fcf3ce44SJohn Forte 	fptr->fcip_flags &= ~(FCIP_IN_ELS_CB);
2659fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_mutex);
2660fcf3ce44SJohn Forte 	return (rval);
2661fcf3ce44SJohn Forte }
2662fcf3ce44SJohn Forte 
2663fcf3ce44SJohn Forte 
2664fcf3ce44SJohn Forte /*
2665fcf3ce44SJohn Forte  * Handle inbound FARP requests
2666fcf3ce44SJohn Forte  */
2667fcf3ce44SJohn Forte static int
2668fcf3ce44SJohn Forte fcip_handle_farp_request(struct fcip *fptr, la_els_farp_t *fcmd)
2669fcf3ce44SJohn Forte {
2670fcf3ce44SJohn Forte 	fcip_pkt_t		*fcip_pkt;
2671fcf3ce44SJohn Forte 	fc_packet_t		*fc_pkt;
2672fcf3ce44SJohn Forte 	fcip_port_info_t	*fport = fptr->fcip_port_info;
2673fcf3ce44SJohn Forte 	int			rval = FC_FAILURE;
2674fcf3ce44SJohn Forte 	opaque_t		fca_dev;
2675fcf3ce44SJohn Forte 	fc_portmap_t 		map;
2676fcf3ce44SJohn Forte 	struct fcip_routing_table *frp;
2677fcf3ce44SJohn Forte 	struct fcip_dest *fdestp;
2678fcf3ce44SJohn Forte 
2679fcf3ce44SJohn Forte 	/*
2680fcf3ce44SJohn Forte 	 * Add an entry for the remote port into our routing and destination
2681fcf3ce44SJohn Forte 	 * tables.
2682fcf3ce44SJohn Forte 	 */
2683fcf3ce44SJohn Forte 	map.map_did = fcmd->req_id;
2684fcf3ce44SJohn Forte 	map.map_hard_addr.hard_addr = fcmd->req_id.port_id;
2685fcf3ce44SJohn Forte 	map.map_state = PORT_DEVICE_VALID;
2686fcf3ce44SJohn Forte 	map.map_type = PORT_DEVICE_NEW;
2687fcf3ce44SJohn Forte 	map.map_flags = 0;
2688fcf3ce44SJohn Forte 	map.map_pd = NULL;
2689fcf3ce44SJohn Forte 	bcopy((void *)&fcmd->req_pwwn, (void *)&map.map_pwwn,
2690fcf3ce44SJohn Forte 	    sizeof (la_wwn_t));
2691fcf3ce44SJohn Forte 	bcopy((void *)&fcmd->req_nwwn, (void *)&map.map_nwwn,
2692fcf3ce44SJohn Forte 	    sizeof (la_wwn_t));
2693fcf3ce44SJohn Forte 	fcip_rt_update(fptr, &map, 1);
2694fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_rt_mutex);
2695fcf3ce44SJohn Forte 	frp = fcip_lookup_rtable(fptr, &fcmd->req_pwwn, FCIP_COMPARE_NWWN);
2696fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_rt_mutex);
2697fcf3ce44SJohn Forte 
2698fcf3ce44SJohn Forte 	fdestp = fcip_add_dest(fptr, frp);
2699fcf3ce44SJohn Forte 
2700fcf3ce44SJohn Forte 	fcip_pkt = fcip_ipkt_alloc(fptr, sizeof (la_els_farp_t),
2701fcf3ce44SJohn Forte 	    sizeof (la_els_farp_t), NULL, KM_SLEEP);
2702fcf3ce44SJohn Forte 	if (fcip_pkt == NULL) {
2703fcf3ce44SJohn Forte 		rval = FC_FAILURE;
2704fcf3ce44SJohn Forte 		goto farp_done;
2705fcf3ce44SJohn Forte 	}
2706fcf3ce44SJohn Forte 	/*
2707fcf3ce44SJohn Forte 	 * Fill in our port's PWWN and NWWN
2708fcf3ce44SJohn Forte 	 */
2709fcf3ce44SJohn Forte 	fcmd->resp_pwwn = fport->fcipp_pwwn;
2710fcf3ce44SJohn Forte 	fcmd->resp_nwwn = fport->fcipp_nwwn;
2711fcf3ce44SJohn Forte 
2712fcf3ce44SJohn Forte 	fcip_init_unicast_pkt(fcip_pkt, fport->fcipp_sid,
2713fcf3ce44SJohn Forte 	    fcmd->req_id, NULL);
2714fcf3ce44SJohn Forte 
2715fcf3ce44SJohn Forte 	fca_dev =
2716fcf3ce44SJohn Forte 	    fc_ulp_get_fca_device(fport->fcipp_handle, fcmd->req_id);
2717fcf3ce44SJohn Forte 	fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
2718fcf3ce44SJohn Forte 	fc_pkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_RSP;
2719fcf3ce44SJohn Forte 	fc_pkt->pkt_fca_device = fca_dev;
2720fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_dest = fdestp;
2721fcf3ce44SJohn Forte 
2722fcf3ce44SJohn Forte 	/*
2723fcf3ce44SJohn Forte 	 * Attempt a PLOGI again
2724fcf3ce44SJohn Forte 	 */
2725fcf3ce44SJohn Forte 	if (fcmd->resp_flags & FARP_INIT_P_LOGI) {
2726fcf3ce44SJohn Forte 		if (fcip_do_plogi(fptr, frp) != FC_SUCCESS) {
2727fcf3ce44SJohn Forte 			/*
2728fcf3ce44SJohn Forte 			 * Login to the remote port failed. There is no
2729fcf3ce44SJohn Forte 			 * point continuing with the FARP request further
2730fcf3ce44SJohn Forte 			 * so bail out here.
2731fcf3ce44SJohn Forte 			 */
2732fcf3ce44SJohn Forte 			frp->fcipr_state = PORT_DEVICE_INVALID;
2733fcf3ce44SJohn Forte 			rval = FC_FAILURE;
2734fcf3ce44SJohn Forte 			goto farp_done;
2735fcf3ce44SJohn Forte 		}
2736fcf3ce44SJohn Forte 	}
2737fcf3ce44SJohn Forte 
2738fcf3ce44SJohn Forte 	FCIP_CP_OUT(fcmd, fc_pkt->pkt_cmd, fc_pkt->pkt_cmd_acc,
2739fcf3ce44SJohn Forte 	    sizeof (la_els_farp_t));
2740fcf3ce44SJohn Forte 
2741fcf3ce44SJohn Forte 	rval = fc_ulp_issue_els(fport->fcipp_handle, fc_pkt);
2742fcf3ce44SJohn Forte 	if (rval != FC_SUCCESS) {
2743fcf3ce44SJohn Forte 		FCIP_TNF_PROBE_2((fcip_handle_farp_request, "fcip io",
2744fcf3ce44SJohn Forte 		    /* CSTYLED */, tnf_string, msg,
2745fcf3ce44SJohn Forte 		    "fcip_transport of farp reply failed",
2746fcf3ce44SJohn Forte 		    tnf_uint, rval, rval));
2747fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_ELS, (CE_WARN,
2748fcf3ce44SJohn Forte 		    "fcip_transport of farp reply failed 0x%x", rval));
2749fcf3ce44SJohn Forte 	}
2750fcf3ce44SJohn Forte 
2751fcf3ce44SJohn Forte farp_done:
2752fcf3ce44SJohn Forte 	return (rval);
2753fcf3ce44SJohn Forte }
2754fcf3ce44SJohn Forte 
2755fcf3ce44SJohn Forte 
2756fcf3ce44SJohn Forte /*
2757fcf3ce44SJohn Forte  * Handle FARP responses to our FARP requests. When we receive a FARP
2758fcf3ce44SJohn Forte  * reply, we need to add the entry for the Port that replied into our
2759fcf3ce44SJohn Forte  * routing and destination hash tables. It is possible that the remote
2760fcf3ce44SJohn Forte  * port did not login into us (FARP responses can be received without
2761fcf3ce44SJohn Forte  * a PLOGI)
2762fcf3ce44SJohn Forte  */
2763fcf3ce44SJohn Forte static int
2764fcf3ce44SJohn Forte fcip_handle_farp_response(struct fcip *fptr, la_els_farp_t *fcmd)
2765fcf3ce44SJohn Forte {
2766fcf3ce44SJohn Forte 	int			rval = FC_FAILURE;
2767fcf3ce44SJohn Forte 	fc_portmap_t 		map;
2768fcf3ce44SJohn Forte 	struct fcip_routing_table *frp;
2769fcf3ce44SJohn Forte 	struct fcip_dest *fdestp;
2770fcf3ce44SJohn Forte 
2771fcf3ce44SJohn Forte 	/*
2772fcf3ce44SJohn Forte 	 * Add an entry for the remote port into our routing and destination
2773fcf3ce44SJohn Forte 	 * tables.
2774fcf3ce44SJohn Forte 	 */
2775fcf3ce44SJohn Forte 	map.map_did = fcmd->dest_id;
2776fcf3ce44SJohn Forte 	map.map_hard_addr.hard_addr = fcmd->dest_id.port_id;
2777fcf3ce44SJohn Forte 	map.map_state = PORT_DEVICE_VALID;
2778fcf3ce44SJohn Forte 	map.map_type = PORT_DEVICE_NEW;
2779fcf3ce44SJohn Forte 	map.map_flags = 0;
2780fcf3ce44SJohn Forte 	map.map_pd = NULL;
2781fcf3ce44SJohn Forte 	bcopy((void *)&fcmd->resp_pwwn, (void *)&map.map_pwwn,
2782fcf3ce44SJohn Forte 	    sizeof (la_wwn_t));
2783fcf3ce44SJohn Forte 	bcopy((void *)&fcmd->resp_nwwn, (void *)&map.map_nwwn,
2784fcf3ce44SJohn Forte 	    sizeof (la_wwn_t));
2785fcf3ce44SJohn Forte 	fcip_rt_update(fptr, &map, 1);
2786fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_rt_mutex);
2787fcf3ce44SJohn Forte 	frp = fcip_lookup_rtable(fptr, &fcmd->resp_pwwn, FCIP_COMPARE_NWWN);
2788fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_rt_mutex);
2789fcf3ce44SJohn Forte 
2790fcf3ce44SJohn Forte 	fdestp = fcip_add_dest(fptr, frp);
2791fcf3ce44SJohn Forte 
2792fcf3ce44SJohn Forte 	if (fdestp != NULL) {
2793fcf3ce44SJohn Forte 		rval = FC_SUCCESS;
2794fcf3ce44SJohn Forte 	}
2795fcf3ce44SJohn Forte 	return (rval);
2796fcf3ce44SJohn Forte }
2797fcf3ce44SJohn Forte 
2798fcf3ce44SJohn Forte 
2799fcf3ce44SJohn Forte #define	FCIP_HDRS_LENGTH	\
2800fcf3ce44SJohn Forte 	sizeof (fcph_network_hdr_t)+sizeof (llc_snap_hdr_t)+sizeof (ipha_t)
2801fcf3ce44SJohn Forte 
2802fcf3ce44SJohn Forte /*
2803fcf3ce44SJohn Forte  * fcip_data_cb is the heart of most IP operations. This routine is called
2804fcf3ce44SJohn Forte  * by the transport when any unsolicited IP data arrives at a port (which
2805fcf3ce44SJohn Forte  * is almost all IP data). This routine then strips off the Network header
2806fcf3ce44SJohn Forte  * from the payload (after authenticating the received payload ofcourse),
2807fcf3ce44SJohn Forte  * creates a message blk and sends the data upstream. You will see ugly
2808fcf3ce44SJohn Forte  * #defines because of problems with using esballoc() as opposed to
2809fcf3ce44SJohn Forte  * allocb to prevent an extra copy of data. We should probably move to
2810fcf3ce44SJohn Forte  * esballoc entirely when the MTU eventually will be larger than 1500 bytes
2811fcf3ce44SJohn Forte  * since copies will get more expensive then. At 1500 byte MTUs, there is
2812fcf3ce44SJohn Forte  * no noticable difference between using allocb and esballoc. The other
2813fcf3ce44SJohn Forte  * caveat is that the qlc firmware still cannot tell us accurately the
2814fcf3ce44SJohn Forte  * no. of valid bytes in the unsol buffer it DMA'ed so we have to resort
2815fcf3ce44SJohn Forte  * to looking into the IP header and hoping that the no. of bytes speficified
2816fcf3ce44SJohn Forte  * in the header was actually received.
2817fcf3ce44SJohn Forte  */
2818fcf3ce44SJohn Forte /* ARGSUSED */
2819fcf3ce44SJohn Forte static int
2820fcf3ce44SJohn Forte fcip_data_cb(opaque_t ulp_handle, opaque_t phandle,
2821fcf3ce44SJohn Forte     fc_unsol_buf_t *buf, uint32_t claimed)
2822fcf3ce44SJohn Forte {
2823fcf3ce44SJohn Forte 	fcip_port_info_t		*fport;
2824fcf3ce44SJohn Forte 	struct fcip 			*fptr;
2825fcf3ce44SJohn Forte 	fcph_network_hdr_t		*nhdr;
2826fcf3ce44SJohn Forte 	llc_snap_hdr_t			*snaphdr;
2827fcf3ce44SJohn Forte 	mblk_t				*bp;
2828fcf3ce44SJohn Forte 	uint32_t 			len;
2829fcf3ce44SJohn Forte 	uint32_t			hdrlen;
2830fcf3ce44SJohn Forte 	ushort_t			type;
2831fcf3ce44SJohn Forte 	ipha_t				*iphdr;
2832fcf3ce44SJohn Forte 	int				rval;
2833fcf3ce44SJohn Forte 
2834fcf3ce44SJohn Forte #ifdef FCIP_ESBALLOC
2835fcf3ce44SJohn Forte 	frtn_t				*free_ubuf;
2836fcf3ce44SJohn Forte 	struct fcip_esballoc_arg	*fesb_argp;
2837fcf3ce44SJohn Forte #endif /* FCIP_ESBALLOC */
2838fcf3ce44SJohn Forte 
2839fcf3ce44SJohn Forte 	fport = fcip_get_port(phandle);
2840fcf3ce44SJohn Forte 	if (fport == NULL) {
2841fcf3ce44SJohn Forte 		return (FC_UNCLAIMED);
2842fcf3ce44SJohn Forte 	}
2843fcf3ce44SJohn Forte 
2844fcf3ce44SJohn Forte 	fptr = fport->fcipp_fcip;
2845fcf3ce44SJohn Forte 	ASSERT(fptr != NULL);
2846fcf3ce44SJohn Forte 
2847fcf3ce44SJohn Forte 	if (fptr == NULL) {
2848fcf3ce44SJohn Forte 		return (FC_UNCLAIMED);
2849fcf3ce44SJohn Forte 	}
2850fcf3ce44SJohn Forte 
2851fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_mutex);
2852fcf3ce44SJohn Forte 	if ((fptr->fcip_flags & (FCIP_DETACHING | FCIP_DETACHED)) ||
2853fcf3ce44SJohn Forte 	    (fptr->fcip_flags & (FCIP_SUSPENDED | FCIP_POWER_DOWN))) {
2854fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_mutex);
2855fcf3ce44SJohn Forte 		rval = FC_UNCLAIMED;
2856fcf3ce44SJohn Forte 		goto data_cb_done;
2857fcf3ce44SJohn Forte 	}
2858fcf3ce44SJohn Forte 
2859fcf3ce44SJohn Forte 	/*
2860fcf3ce44SJohn Forte 	 * set fcip flags to indicate we are in the middle of a
2861fcf3ce44SJohn Forte 	 * data callback so we can wait till the statechange
2862fcf3ce44SJohn Forte 	 * is handled before succeeding/failing the SUSPEND/POWER DOWN.
2863fcf3ce44SJohn Forte 	 */
2864fcf3ce44SJohn Forte 	fptr->fcip_flags |= FCIP_IN_DATA_CB;
2865fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_mutex);
2866fcf3ce44SJohn Forte 
2867fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_2((fcip_data_cb, "fcip io", /* CSTYLED */,
2868fcf3ce44SJohn Forte 		tnf_string, msg, "data callback",
2869fcf3ce44SJohn Forte 		tnf_int, instance, ddi_get_instance(fport->fcipp_dip)));
2870fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_UPSTREAM,
2871fcf3ce44SJohn Forte 	    (CE_NOTE, "fcip%d, data callback",
2872fcf3ce44SJohn Forte 	    ddi_get_instance(fport->fcipp_dip)));
2873fcf3ce44SJohn Forte 
2874fcf3ce44SJohn Forte 	/*
2875fcf3ce44SJohn Forte 	 * get to the network and snap headers in the payload
2876fcf3ce44SJohn Forte 	 */
2877fcf3ce44SJohn Forte 	nhdr = (fcph_network_hdr_t *)buf->ub_buffer;
2878fcf3ce44SJohn Forte 	snaphdr = (llc_snap_hdr_t *)(buf->ub_buffer +
2879fcf3ce44SJohn Forte 	    sizeof (fcph_network_hdr_t));
2880fcf3ce44SJohn Forte 
2881fcf3ce44SJohn Forte 	hdrlen = sizeof (fcph_network_hdr_t) + sizeof (llc_snap_hdr_t);
2882fcf3ce44SJohn Forte 
2883fcf3ce44SJohn Forte 	/*
2884fcf3ce44SJohn Forte 	 * get the IP header to obtain the no. of bytes we need to read
2885fcf3ce44SJohn Forte 	 * off from the unsol buffer. This obviously is because not all
2886fcf3ce44SJohn Forte 	 * data fills up the unsol buffer completely and the firmware
2887fcf3ce44SJohn Forte 	 * doesn't tell us how many valid bytes are in there as well
2888fcf3ce44SJohn Forte 	 */
2889fcf3ce44SJohn Forte 	iphdr = (ipha_t *)(buf->ub_buffer + hdrlen);
2890fcf3ce44SJohn Forte 	snaphdr->pid = BE_16(snaphdr->pid);
2891fcf3ce44SJohn Forte 	type = snaphdr->pid;
2892fcf3ce44SJohn Forte 
2893fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_UPSTREAM,
2894fcf3ce44SJohn Forte 	    (CE_CONT, "SNAPHDR: dsap %x, ssap %x, ctrl %x\n",
2895fcf3ce44SJohn Forte 	    snaphdr->dsap, snaphdr->ssap, snaphdr->ctrl));
2896fcf3ce44SJohn Forte 
2897fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_UPSTREAM,
2898fcf3ce44SJohn Forte 	    (CE_CONT, "oui[0] 0x%x oui[1] 0x%x oui[2] 0x%x pid 0x%x\n",
2899fcf3ce44SJohn Forte 	    snaphdr->oui[0], snaphdr->oui[1], snaphdr->oui[2], snaphdr->pid));
2900fcf3ce44SJohn Forte 
2901fcf3ce44SJohn Forte 	/* Authneticate, Authenticate */
2902fcf3ce44SJohn Forte 	if (type == ETHERTYPE_IP) {
2903fcf3ce44SJohn Forte 		len = hdrlen + BE_16(iphdr->ipha_length);
2904fcf3ce44SJohn Forte 	} else if (type == ETHERTYPE_ARP) {
2905fcf3ce44SJohn Forte 		len = hdrlen + 28;
2906fcf3ce44SJohn Forte 	} else {
2907fcf3ce44SJohn Forte 		len = buf->ub_bufsize;
2908fcf3ce44SJohn Forte 	}
2909fcf3ce44SJohn Forte 
2910fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_UPSTREAM,
2911fcf3ce44SJohn Forte 	    (CE_CONT, "effective packet length is %d bytes.\n", len));
2912fcf3ce44SJohn Forte 
2913fcf3ce44SJohn Forte 	if (len < hdrlen || len > FCIP_UB_SIZE) {
2914fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_UPSTREAM,
2915fcf3ce44SJohn Forte 		    (CE_NOTE, "Incorrect buffer size %d bytes", len));
2916fcf3ce44SJohn Forte 		rval = FC_UNCLAIMED;
2917fcf3ce44SJohn Forte 		goto data_cb_done;
2918fcf3ce44SJohn Forte 	}
2919fcf3ce44SJohn Forte 
2920fcf3ce44SJohn Forte 	if (buf->ub_frame.type != FC_TYPE_IS8802_SNAP) {
2921fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_UPSTREAM, (CE_NOTE, "Not IP/ARP data"));
2922fcf3ce44SJohn Forte 		rval = FC_UNCLAIMED;
2923fcf3ce44SJohn Forte 		goto data_cb_done;
2924fcf3ce44SJohn Forte 	}
2925fcf3ce44SJohn Forte 
2926fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_UPSTREAM, (CE_NOTE, "checking wwn"));
2927fcf3ce44SJohn Forte 
2928fcf3ce44SJohn Forte 	if ((fcip_wwn_compare(&nhdr->net_dest_addr, &fport->fcipp_pwwn,
2929fcf3ce44SJohn Forte 	    FCIP_COMPARE_NWWN) != 0) &&
2930fcf3ce44SJohn Forte 	    (!IS_BROADCAST_ADDR(&nhdr->net_dest_addr))) {
2931fcf3ce44SJohn Forte 		rval = FC_UNCLAIMED;
2932fcf3ce44SJohn Forte 		goto data_cb_done;
2933fcf3ce44SJohn Forte 	} else if (fcip_cache_on_arp_broadcast &&
2934fcf3ce44SJohn Forte 	    IS_BROADCAST_ADDR(&nhdr->net_dest_addr)) {
2935fcf3ce44SJohn Forte 		fcip_cache_arp_broadcast(fptr, buf);
2936fcf3ce44SJohn Forte 	}
2937fcf3ce44SJohn Forte 
2938fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_UPSTREAM, (CE_NOTE, "Allocate streams block"));
2939fcf3ce44SJohn Forte 
2940fcf3ce44SJohn Forte 	/*
2941fcf3ce44SJohn Forte 	 * Using esballoc instead of allocb should be faster, atleast at
2942fcf3ce44SJohn Forte 	 * larger MTUs than 1500 bytes. Someday we'll get there :)
2943fcf3ce44SJohn Forte 	 */
2944fcf3ce44SJohn Forte #if defined(FCIP_ESBALLOC)
2945fcf3ce44SJohn Forte 	/*
2946fcf3ce44SJohn Forte 	 * allocate memory for the frtn function arg. The Function
2947fcf3ce44SJohn Forte 	 * (fcip_ubfree) arg is a struct fcip_esballoc_arg type
2948fcf3ce44SJohn Forte 	 * which contains pointers to the unsol buffer and the
2949fcf3ce44SJohn Forte 	 * opaque port handle for releasing the unsol buffer back to
2950fcf3ce44SJohn Forte 	 * the FCA for reuse
2951fcf3ce44SJohn Forte 	 */
2952fcf3ce44SJohn Forte 	fesb_argp = (struct fcip_esballoc_arg *)
2953fcf3ce44SJohn Forte 	    kmem_zalloc(sizeof (struct fcip_esballoc_arg), KM_NOSLEEP);
2954fcf3ce44SJohn Forte 
2955fcf3ce44SJohn Forte 	if (fesb_argp == NULL) {
2956fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_UPSTREAM,
2957fcf3ce44SJohn Forte 		    (CE_WARN, "esballoc of mblk failed in data_cb"));
2958fcf3ce44SJohn Forte 		rval = FC_UNCLAIMED;
2959fcf3ce44SJohn Forte 		goto data_cb_done;
2960fcf3ce44SJohn Forte 	}
2961fcf3ce44SJohn Forte 	/*
2962fcf3ce44SJohn Forte 	 * Check with KM_NOSLEEP
2963fcf3ce44SJohn Forte 	 */
2964fcf3ce44SJohn Forte 	free_ubuf = (frtn_t *)kmem_zalloc(sizeof (frtn_t), KM_NOSLEEP);
2965fcf3ce44SJohn Forte 	if (free_ubuf == NULL) {
2966fcf3ce44SJohn Forte 		kmem_free(fesb_argp, sizeof (struct fcip_esballoc_arg));
2967fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_UPSTREAM,
2968fcf3ce44SJohn Forte 		    (CE_WARN, "esballoc of mblk failed in data_cb"));
2969fcf3ce44SJohn Forte 		rval = FC_UNCLAIMED;
2970fcf3ce44SJohn Forte 		goto data_cb_done;
2971fcf3ce44SJohn Forte 	}
2972fcf3ce44SJohn Forte 
2973fcf3ce44SJohn Forte 	fesb_argp->frtnp = free_ubuf;
2974fcf3ce44SJohn Forte 	fesb_argp->buf = buf;
2975fcf3ce44SJohn Forte 	fesb_argp->phandle = phandle;
2976fcf3ce44SJohn Forte 	free_ubuf->free_func = fcip_ubfree;
2977fcf3ce44SJohn Forte 	free_ubuf->free_arg = (char *)fesb_argp;
2978fcf3ce44SJohn Forte 	if ((bp = (mblk_t *)esballoc((unsigned char *)buf->ub_buffer,
2979fcf3ce44SJohn Forte 	    len, BPRI_MED, free_ubuf)) == NULL) {
2980fcf3ce44SJohn Forte 		kmem_free(fesb_argp, sizeof (struct fcip_esballoc_arg));
2981fcf3ce44SJohn Forte 		kmem_free(free_ubuf, sizeof (frtn_t));
2982fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_UPSTREAM,
2983fcf3ce44SJohn Forte 		    (CE_WARN, "esballoc of mblk failed in data_cb"));
2984fcf3ce44SJohn Forte 		rval = FC_UNCLAIMED;
2985fcf3ce44SJohn Forte 		goto data_cb_done;
2986fcf3ce44SJohn Forte 	}
2987fcf3ce44SJohn Forte #elif !defined(FCIP_ESBALLOC)
2988fcf3ce44SJohn Forte 	/*
2989fcf3ce44SJohn Forte 	 * allocate streams mblk and copy the contents of the
2990fcf3ce44SJohn Forte 	 * unsolicited buffer into this newly alloc'ed mblk
2991fcf3ce44SJohn Forte 	 */
2992fcf3ce44SJohn Forte 	if ((bp = (mblk_t *)fcip_allocb((size_t)len, BPRI_LO)) == NULL) {
2993fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_UPSTREAM,
2994fcf3ce44SJohn Forte 		    (CE_WARN, "alloc of mblk failed in data_cb"));
2995fcf3ce44SJohn Forte 		rval = FC_UNCLAIMED;
2996fcf3ce44SJohn Forte 		goto data_cb_done;
2997fcf3ce44SJohn Forte 	}
2998fcf3ce44SJohn Forte 
2999fcf3ce44SJohn Forte 	/*
3000fcf3ce44SJohn Forte 	 * Unsolicited buffers handed up to us from the FCA must be
3001fcf3ce44SJohn Forte 	 * endian clean so just bcopy the data into our mblk. Else
3002fcf3ce44SJohn Forte 	 * we may have to either copy the data byte by byte or
3003fcf3ce44SJohn Forte 	 * use the ddi_rep_get* routines to do the copy for us.
3004fcf3ce44SJohn Forte 	 */
3005fcf3ce44SJohn Forte 	bcopy(buf->ub_buffer, bp->b_rptr, len);
3006fcf3ce44SJohn Forte 
3007fcf3ce44SJohn Forte 	/*
3008fcf3ce44SJohn Forte 	 * for esballoc'ed mblks - free the UB in the frtn function
3009fcf3ce44SJohn Forte 	 * along with the memory allocated for the function arg.
3010fcf3ce44SJohn Forte 	 * for allocb'ed mblk - release the unsolicited buffer here
3011fcf3ce44SJohn Forte 	 */
3012fcf3ce44SJohn Forte 	(void) fc_ulp_ubrelease(phandle, 1, &buf->ub_token);
3013fcf3ce44SJohn Forte 
3014fcf3ce44SJohn Forte #endif	/* FCIP_ESBALLOC */
3015fcf3ce44SJohn Forte 
3016fcf3ce44SJohn Forte 	bp->b_wptr = bp->b_rptr + len;
3017fcf3ce44SJohn Forte 	fptr->fcip_ipackets++;
3018fcf3ce44SJohn Forte 
3019fcf3ce44SJohn Forte 	if (type == ETHERTYPE_IP) {
3020fcf3ce44SJohn Forte 		mutex_enter(&fptr->fcip_mutex);
3021fcf3ce44SJohn Forte 		fptr->fcip_ub_upstream++;
3022fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_mutex);
3023fcf3ce44SJohn Forte 		bp->b_rptr += hdrlen;
3024fcf3ce44SJohn Forte 
3025fcf3ce44SJohn Forte 		/*
3026fcf3ce44SJohn Forte 		 * Check if ipq is valid in the sendup thread
3027fcf3ce44SJohn Forte 		 */
3028fcf3ce44SJohn Forte 		if (fcip_sendup_alloc_enque(fptr, bp, NULL) != FC_SUCCESS) {
3029fcf3ce44SJohn Forte 			freemsg(bp);
3030fcf3ce44SJohn Forte 		}
3031fcf3ce44SJohn Forte 	} else {
3032fcf3ce44SJohn Forte 		/*
3033fcf3ce44SJohn Forte 		 * We won't get ethernet 802.3 packets in FCIP but we may get
3034fcf3ce44SJohn Forte 		 * types other than ETHERTYPE_IP, such as ETHERTYPE_ARP. Let
3035fcf3ce44SJohn Forte 		 * fcip_sendup() do the matching.
3036fcf3ce44SJohn Forte 		 */
3037fcf3ce44SJohn Forte 		mutex_enter(&fptr->fcip_mutex);
3038fcf3ce44SJohn Forte 		fptr->fcip_ub_upstream++;
3039fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_mutex);
3040fcf3ce44SJohn Forte 		if (fcip_sendup_alloc_enque(fptr, bp,
3041fcf3ce44SJohn Forte 		    fcip_accept) != FC_SUCCESS) {
3042fcf3ce44SJohn Forte 			freemsg(bp);
3043fcf3ce44SJohn Forte 		}
3044fcf3ce44SJohn Forte 	}
3045fcf3ce44SJohn Forte 
3046fcf3ce44SJohn Forte 	rval = FC_SUCCESS;
3047fcf3ce44SJohn Forte 
3048fcf3ce44SJohn Forte 	/*
3049fcf3ce44SJohn Forte 	 * Unset fcip_flags to indicate we are out of callback and return
3050fcf3ce44SJohn Forte 	 */
3051fcf3ce44SJohn Forte data_cb_done:
3052fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_mutex);
3053fcf3ce44SJohn Forte 	fptr->fcip_flags &= ~(FCIP_IN_DATA_CB);
3054fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_mutex);
3055fcf3ce44SJohn Forte 	return (rval);
3056fcf3ce44SJohn Forte }
3057fcf3ce44SJohn Forte 
3058fcf3ce44SJohn Forte #if !defined(FCIP_ESBALLOC)
3059fcf3ce44SJohn Forte /*
3060fcf3ce44SJohn Forte  * Allocate a message block for the inbound data to be sent upstream.
3061fcf3ce44SJohn Forte  */
3062fcf3ce44SJohn Forte static void *
3063fcf3ce44SJohn Forte fcip_allocb(size_t size, uint_t pri)
3064fcf3ce44SJohn Forte {
3065fcf3ce44SJohn Forte 	mblk_t	*mp;
3066fcf3ce44SJohn Forte 
3067fcf3ce44SJohn Forte 	if ((mp = allocb(size, pri)) == NULL) {
3068fcf3ce44SJohn Forte 		return (NULL);
3069fcf3ce44SJohn Forte 	}
3070fcf3ce44SJohn Forte 	return (mp);
3071fcf3ce44SJohn Forte }
3072fcf3ce44SJohn Forte 
3073fcf3ce44SJohn Forte #endif
3074fcf3ce44SJohn Forte 
3075fcf3ce44SJohn Forte /*
3076fcf3ce44SJohn Forte  * This helper routine kmem cache alloc's a sendup element for enquing
3077fcf3ce44SJohn Forte  * into the sendup list for callbacks upstream from the dedicated sendup
3078fcf3ce44SJohn Forte  * thread. We enque the msg buf into the sendup list and cv_signal the
3079fcf3ce44SJohn Forte  * sendup thread to finish the callback for us.
3080fcf3ce44SJohn Forte  */
3081fcf3ce44SJohn Forte static int
3082fcf3ce44SJohn Forte fcip_sendup_alloc_enque(struct fcip *fptr, mblk_t *mp, struct fcipstr *(*f)())
3083fcf3ce44SJohn Forte {
3084fcf3ce44SJohn Forte 	struct fcip_sendup_elem 	*msg_elem;
3085fcf3ce44SJohn Forte 	int				rval = FC_FAILURE;
3086fcf3ce44SJohn Forte 
3087fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_1((fcip_sendup_alloc_enque, "fcip io", /* CSTYLED */,
3088fcf3ce44SJohn Forte 		tnf_string, msg, "sendup msg enque"));
3089fcf3ce44SJohn Forte 	msg_elem = kmem_cache_alloc(fptr->fcip_sendup_cache, KM_NOSLEEP);
3090fcf3ce44SJohn Forte 	if (msg_elem == NULL) {
3091fcf3ce44SJohn Forte 		/* drop pkt to floor - update stats */
3092fcf3ce44SJohn Forte 		rval = FC_FAILURE;
3093fcf3ce44SJohn Forte 		goto sendup_alloc_done;
3094fcf3ce44SJohn Forte 	}
3095fcf3ce44SJohn Forte 	msg_elem->fcipsu_mp = mp;
3096fcf3ce44SJohn Forte 	msg_elem->fcipsu_func = f;
3097fcf3ce44SJohn Forte 
3098fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_sendup_mutex);
3099fcf3ce44SJohn Forte 	if (fptr->fcip_sendup_head == NULL) {
3100fcf3ce44SJohn Forte 		fptr->fcip_sendup_head = fptr->fcip_sendup_tail = msg_elem;
3101fcf3ce44SJohn Forte 	} else {
3102fcf3ce44SJohn Forte 		fptr->fcip_sendup_tail->fcipsu_next = msg_elem;
3103fcf3ce44SJohn Forte 		fptr->fcip_sendup_tail = msg_elem;
3104fcf3ce44SJohn Forte 	}
3105fcf3ce44SJohn Forte 	fptr->fcip_sendup_cnt++;
3106fcf3ce44SJohn Forte 	cv_signal(&fptr->fcip_sendup_cv);
3107fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_sendup_mutex);
3108fcf3ce44SJohn Forte 	rval = FC_SUCCESS;
3109fcf3ce44SJohn Forte 
3110fcf3ce44SJohn Forte sendup_alloc_done:
3111fcf3ce44SJohn Forte 	return (rval);
3112fcf3ce44SJohn Forte }
3113fcf3ce44SJohn Forte 
3114fcf3ce44SJohn Forte /*
3115fcf3ce44SJohn Forte  * One of the ways of performing the WWN to D_ID mapping required for
3116fcf3ce44SJohn Forte  * IPFC data is to cache the unsolicited ARP broadcast messages received
3117fcf3ce44SJohn Forte  * and update the routing table to add entry for the destination port
3118fcf3ce44SJohn Forte  * if we are the intended recipient of the ARP broadcast message. This is
3119fcf3ce44SJohn Forte  * one of the methods recommended in the rfc to obtain the WWN to D_ID mapping
3120fcf3ce44SJohn Forte  * but is not typically used unless enabled. The driver prefers to use the
3121fcf3ce44SJohn Forte  * nameserver/lilp map to obtain this mapping.
3122fcf3ce44SJohn Forte  */
3123fcf3ce44SJohn Forte static void
3124fcf3ce44SJohn Forte fcip_cache_arp_broadcast(struct fcip *fptr, fc_unsol_buf_t *buf)
3125fcf3ce44SJohn Forte {
3126fcf3ce44SJohn Forte 	fcip_port_info_t		*fport;
3127fcf3ce44SJohn Forte 	fcph_network_hdr_t		*nhdr;
3128fcf3ce44SJohn Forte 	struct fcip_routing_table	*frp;
3129fcf3ce44SJohn Forte 	fc_portmap_t			map;
3130fcf3ce44SJohn Forte 
3131fcf3ce44SJohn Forte 	fport = fptr->fcip_port_info;
3132fcf3ce44SJohn Forte 	if (fport == NULL) {
3133fcf3ce44SJohn Forte 		return;
3134fcf3ce44SJohn Forte 	}
3135fcf3ce44SJohn Forte 	ASSERT(fport != NULL);
3136fcf3ce44SJohn Forte 
3137fcf3ce44SJohn Forte 	nhdr = (fcph_network_hdr_t *)buf->ub_buffer;
3138fcf3ce44SJohn Forte 
3139fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_rt_mutex);
3140fcf3ce44SJohn Forte 	frp = fcip_lookup_rtable(fptr, &nhdr->net_src_addr, FCIP_COMPARE_NWWN);
3141fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_rt_mutex);
3142fcf3ce44SJohn Forte 	if (frp == NULL) {
3143fcf3ce44SJohn Forte 		map.map_did.port_id = buf->ub_frame.s_id;
3144fcf3ce44SJohn Forte 		map.map_hard_addr.hard_addr = buf->ub_frame.s_id;
3145fcf3ce44SJohn Forte 		map.map_state = PORT_DEVICE_VALID;
3146fcf3ce44SJohn Forte 		map.map_type = PORT_DEVICE_NEW;
3147fcf3ce44SJohn Forte 		map.map_flags = 0;
3148fcf3ce44SJohn Forte 		map.map_pd = NULL;
3149fcf3ce44SJohn Forte 		bcopy((void *)&nhdr->net_src_addr, (void *)&map.map_pwwn,
3150fcf3ce44SJohn Forte 		    sizeof (la_wwn_t));
3151fcf3ce44SJohn Forte 		bcopy((void *)&nhdr->net_src_addr, (void *)&map.map_nwwn,
3152fcf3ce44SJohn Forte 		    sizeof (la_wwn_t));
3153fcf3ce44SJohn Forte 		fcip_rt_update(fptr, &map, 1);
3154fcf3ce44SJohn Forte 		mutex_enter(&fptr->fcip_rt_mutex);
3155fcf3ce44SJohn Forte 		frp = fcip_lookup_rtable(fptr, &nhdr->net_src_addr,
3156fcf3ce44SJohn Forte 		    FCIP_COMPARE_NWWN);
3157fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_rt_mutex);
3158fcf3ce44SJohn Forte 
3159fcf3ce44SJohn Forte 		(void) fcip_add_dest(fptr, frp);
3160fcf3ce44SJohn Forte 	}
3161fcf3ce44SJohn Forte 
3162fcf3ce44SJohn Forte }
3163fcf3ce44SJohn Forte 
3164fcf3ce44SJohn Forte /*
3165fcf3ce44SJohn Forte  * This is a dedicated thread to do callbacks from fcip's data callback
3166fcf3ce44SJohn Forte  * routines into the modules upstream. The reason for this thread is
3167fcf3ce44SJohn Forte  * the data callback function can be called from an interrupt context and
3168fcf3ce44SJohn Forte  * the upstream modules *can* make calls downstream in the same thread
3169fcf3ce44SJohn Forte  * context. If the call is to a fabric port which is not yet in our
3170fcf3ce44SJohn Forte  * routing tables, we may have to query the nameserver/fabric for the
3171fcf3ce44SJohn Forte  * MAC addr to Port_ID mapping which may be blocking calls.
3172fcf3ce44SJohn Forte  */
3173fcf3ce44SJohn Forte static void
3174fcf3ce44SJohn Forte fcip_sendup_thr(void *arg)
3175fcf3ce44SJohn Forte {
3176fcf3ce44SJohn Forte 	struct fcip		*fptr = (struct fcip *)arg;
3177fcf3ce44SJohn Forte 	struct fcip_sendup_elem	*msg_elem;
3178fcf3ce44SJohn Forte 	queue_t			*ip4q = NULL;
3179fcf3ce44SJohn Forte 
3180fcf3ce44SJohn Forte 	CALLB_CPR_INIT(&fptr->fcip_cpr_info, &fptr->fcip_sendup_mutex,
3181fcf3ce44SJohn Forte 	    callb_generic_cpr, "fcip_sendup_thr");
3182fcf3ce44SJohn Forte 
3183fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_sendup_mutex);
3184fcf3ce44SJohn Forte 	for (;;) {
3185fcf3ce44SJohn Forte 
3186fcf3ce44SJohn Forte 		while (fptr->fcip_sendup_thr_initted &&
3187fcf3ce44SJohn Forte 		    fptr->fcip_sendup_head == NULL) {
3188fcf3ce44SJohn Forte 			CALLB_CPR_SAFE_BEGIN(&fptr->fcip_cpr_info);
3189fcf3ce44SJohn Forte 			cv_wait(&fptr->fcip_sendup_cv,
3190fcf3ce44SJohn Forte 			    &fptr->fcip_sendup_mutex);
3191fcf3ce44SJohn Forte 			CALLB_CPR_SAFE_END(&fptr->fcip_cpr_info,
3192fcf3ce44SJohn Forte 			    &fptr->fcip_sendup_mutex);
3193fcf3ce44SJohn Forte 		}
3194fcf3ce44SJohn Forte 
3195fcf3ce44SJohn Forte 		if (fptr->fcip_sendup_thr_initted == 0) {
3196fcf3ce44SJohn Forte 			break;
3197fcf3ce44SJohn Forte 		}
3198fcf3ce44SJohn Forte 
3199fcf3ce44SJohn Forte 		FCIP_TNF_PROBE_1((fcip_sendup_thr, "fcip io", /* CSTYLED */,
3200fcf3ce44SJohn Forte 		    tnf_string, msg, "fcip sendup thr - new msg"));
3201fcf3ce44SJohn Forte 
3202fcf3ce44SJohn Forte 		msg_elem = fptr->fcip_sendup_head;
3203fcf3ce44SJohn Forte 		fptr->fcip_sendup_head = msg_elem->fcipsu_next;
3204fcf3ce44SJohn Forte 		msg_elem->fcipsu_next = NULL;
3205fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_sendup_mutex);
3206fcf3ce44SJohn Forte 
3207fcf3ce44SJohn Forte 		if (msg_elem->fcipsu_func == NULL) {
3208fcf3ce44SJohn Forte 			/*
3209fcf3ce44SJohn Forte 			 * Message for ipq. Check to see if the ipq is
3210fcf3ce44SJohn Forte 			 * is still valid. Since the thread is asynchronous,
3211fcf3ce44SJohn Forte 			 * there could have been a close on the stream
3212fcf3ce44SJohn Forte 			 */
3213fcf3ce44SJohn Forte 			mutex_enter(&fptr->fcip_mutex);
3214fcf3ce44SJohn Forte 			if (fptr->fcip_ipq && canputnext(fptr->fcip_ipq)) {
3215fcf3ce44SJohn Forte 				ip4q = fptr->fcip_ipq;
3216fcf3ce44SJohn Forte 				mutex_exit(&fptr->fcip_mutex);
3217fcf3ce44SJohn Forte 				putnext(ip4q, msg_elem->fcipsu_mp);
3218fcf3ce44SJohn Forte 			} else {
3219fcf3ce44SJohn Forte 				mutex_exit(&fptr->fcip_mutex);
3220fcf3ce44SJohn Forte 				freemsg(msg_elem->fcipsu_mp);
3221fcf3ce44SJohn Forte 			}
3222fcf3ce44SJohn Forte 		} else {
3223fcf3ce44SJohn Forte 			fcip_sendup(fptr, msg_elem->fcipsu_mp,
3224fcf3ce44SJohn Forte 			    msg_elem->fcipsu_func);
3225fcf3ce44SJohn Forte 		}
3226fcf3ce44SJohn Forte 
3227fcf3ce44SJohn Forte #if !defined(FCIP_ESBALLOC)
3228fcf3ce44SJohn Forte 		/*
3229fcf3ce44SJohn Forte 		 * for allocb'ed mblk - decrement upstream count here
3230fcf3ce44SJohn Forte 		 */
3231fcf3ce44SJohn Forte 		mutex_enter(&fptr->fcip_mutex);
3232fcf3ce44SJohn Forte 		ASSERT(fptr->fcip_ub_upstream > 0);
3233fcf3ce44SJohn Forte 		fptr->fcip_ub_upstream--;
3234fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_mutex);
3235fcf3ce44SJohn Forte #endif /* FCIP_ESBALLOC */
3236fcf3ce44SJohn Forte 
3237fcf3ce44SJohn Forte 		kmem_cache_free(fptr->fcip_sendup_cache, (void *)msg_elem);
3238fcf3ce44SJohn Forte 		mutex_enter(&fptr->fcip_sendup_mutex);
3239fcf3ce44SJohn Forte 		fptr->fcip_sendup_cnt--;
3240fcf3ce44SJohn Forte 	}
3241fcf3ce44SJohn Forte 
3242fcf3ce44SJohn Forte 
3243fcf3ce44SJohn Forte #ifndef	__lock_lint
3244fcf3ce44SJohn Forte 	CALLB_CPR_EXIT(&fptr->fcip_cpr_info);
3245fcf3ce44SJohn Forte #else
3246fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_sendup_mutex);
3247fcf3ce44SJohn Forte #endif /* __lock_lint */
3248fcf3ce44SJohn Forte 
3249fcf3ce44SJohn Forte 	/* Wake up fcip detach thread by the end */
3250fcf3ce44SJohn Forte 	cv_signal(&fptr->fcip_sendup_cv);
3251fcf3ce44SJohn Forte 
3252fcf3ce44SJohn Forte 	thread_exit();
3253fcf3ce44SJohn Forte }
3254fcf3ce44SJohn Forte 
3255fcf3ce44SJohn Forte #ifdef FCIP_ESBALLOC
3256fcf3ce44SJohn Forte 
3257fcf3ce44SJohn Forte /*
3258fcf3ce44SJohn Forte  * called from the stream head when it is done using an unsolicited buffer.
3259fcf3ce44SJohn Forte  * We release this buffer then to the FCA for reuse.
3260fcf3ce44SJohn Forte  */
3261fcf3ce44SJohn Forte static void
3262fcf3ce44SJohn Forte fcip_ubfree(char *arg)
3263fcf3ce44SJohn Forte {
3264fcf3ce44SJohn Forte 	struct fcip_esballoc_arg *fesb_argp = (struct fcip_esballoc_arg *)arg;
3265fcf3ce44SJohn Forte 	fc_unsol_buf_t	*ubuf;
3266fcf3ce44SJohn Forte 	frtn_t		*frtnp;
3267fcf3ce44SJohn Forte 	fcip_port_info_t		*fport;
3268fcf3ce44SJohn Forte 	struct fcip 			*fptr;
3269fcf3ce44SJohn Forte 
3270fcf3ce44SJohn Forte 
3271fcf3ce44SJohn Forte 	fport = fcip_get_port(fesb_argp->phandle);
3272fcf3ce44SJohn Forte 	fptr = fport->fcipp_fcip;
3273fcf3ce44SJohn Forte 
3274fcf3ce44SJohn Forte 	ASSERT(fesb_argp != NULL);
3275fcf3ce44SJohn Forte 	ubuf = fesb_argp->buf;
3276fcf3ce44SJohn Forte 	frtnp = fesb_argp->frtnp;
3277fcf3ce44SJohn Forte 
3278fcf3ce44SJohn Forte 
3279fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_UPSTREAM,
3280fcf3ce44SJohn Forte 	    (CE_WARN, "freeing ubuf after esballoc in fcip_ubfree"));
3281fcf3ce44SJohn Forte 	(void) fc_ulp_ubrelease(fesb_argp->phandle, 1, &ubuf->ub_token);
3282fcf3ce44SJohn Forte 
3283fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_mutex);
3284fcf3ce44SJohn Forte 	ASSERT(fptr->fcip_ub_upstream > 0);
3285fcf3ce44SJohn Forte 	fptr->fcip_ub_upstream--;
3286fcf3ce44SJohn Forte 	cv_signal(&fptr->fcip_ub_cv);
3287fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_mutex);
3288fcf3ce44SJohn Forte 
3289fcf3ce44SJohn Forte 	kmem_free(frtnp, sizeof (frtn_t));
3290fcf3ce44SJohn Forte 	kmem_free(fesb_argp, sizeof (struct fcip_esballoc_arg));
3291fcf3ce44SJohn Forte }
3292fcf3ce44SJohn Forte 
3293fcf3ce44SJohn Forte #endif /* FCIP_ESBALLOC */
3294fcf3ce44SJohn Forte 
3295fcf3ce44SJohn Forte /*
3296fcf3ce44SJohn Forte  * handle data other than that of type ETHERTYPE_IP and send it on its
3297fcf3ce44SJohn Forte  * way upstream to the right streams module to handle
3298fcf3ce44SJohn Forte  */
3299fcf3ce44SJohn Forte static void
3300fcf3ce44SJohn Forte fcip_sendup(struct fcip *fptr, mblk_t *mp, struct fcipstr *(*acceptfunc)())
3301fcf3ce44SJohn Forte {
3302fcf3ce44SJohn Forte 	struct fcipstr	*slp, *nslp;
3303fcf3ce44SJohn Forte 	la_wwn_t	*dhostp;
3304fcf3ce44SJohn Forte 	mblk_t		*nmp;
3305fcf3ce44SJohn Forte 	uint32_t 	isgroupaddr;
3306fcf3ce44SJohn Forte 	int 		type;
3307fcf3ce44SJohn Forte 	uint32_t	hdrlen;
3308fcf3ce44SJohn Forte 	fcph_network_hdr_t	*nhdr;
3309fcf3ce44SJohn Forte 	llc_snap_hdr_t		*snaphdr;
3310fcf3ce44SJohn Forte 
3311fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_1((fcip_sendup, "fcip io", /* CSTYLED */,
3312fcf3ce44SJohn Forte 		tnf_string, msg, "fcip sendup"));
3313fcf3ce44SJohn Forte 	nhdr = (fcph_network_hdr_t *)mp->b_rptr;
3314fcf3ce44SJohn Forte 	snaphdr =
3315fcf3ce44SJohn Forte 	    (llc_snap_hdr_t *)(mp->b_rptr + sizeof (fcph_network_hdr_t));
3316fcf3ce44SJohn Forte 	dhostp = &nhdr->net_dest_addr;
3317fcf3ce44SJohn Forte 	type = snaphdr->pid;
3318fcf3ce44SJohn Forte 	hdrlen = sizeof (fcph_network_hdr_t) + sizeof (llc_snap_hdr_t);
3319fcf3ce44SJohn Forte 
3320fcf3ce44SJohn Forte 	/* No group address with fibre channel */
3321fcf3ce44SJohn Forte 	isgroupaddr = 0;
3322fcf3ce44SJohn Forte 
3323fcf3ce44SJohn Forte 	/*
3324fcf3ce44SJohn Forte 	 * While holding a reader lock on the linked list of streams structures,
3325fcf3ce44SJohn Forte 	 * attempt to match the address criteria for each stream
3326fcf3ce44SJohn Forte 	 * and pass up the raw M_DATA ("fastpath") or a DL_UNITDATA_IND.
3327fcf3ce44SJohn Forte 	 */
3328fcf3ce44SJohn Forte 
3329fcf3ce44SJohn Forte 	rw_enter(&fcipstruplock, RW_READER);
3330fcf3ce44SJohn Forte 
3331fcf3ce44SJohn Forte 	if ((slp = (*acceptfunc)(fcipstrup, fptr, type, dhostp)) == NULL) {
3332fcf3ce44SJohn Forte 		rw_exit(&fcipstruplock);
3333fcf3ce44SJohn Forte 		FCIP_TNF_PROBE_1((fcip_sendup, "fcip io", /* CSTYLED */,
3334fcf3ce44SJohn Forte 		    tnf_string, msg, "fcip sendup - no slp"));
3335fcf3ce44SJohn Forte 		freemsg(mp);
3336fcf3ce44SJohn Forte 		return;
3337fcf3ce44SJohn Forte 	}
3338fcf3ce44SJohn Forte 
3339fcf3ce44SJohn Forte 	/*
3340fcf3ce44SJohn Forte 	 * Loop on matching open streams until (*acceptfunc)() returns NULL.
3341fcf3ce44SJohn Forte 	 */
3342fcf3ce44SJohn Forte 	for (; nslp = (*acceptfunc)(slp->sl_nextp, fptr, type, dhostp);
3343fcf3ce44SJohn Forte 	    slp = nslp) {
3344fcf3ce44SJohn Forte 		if (canputnext(slp->sl_rq)) {
3345fcf3ce44SJohn Forte 			if (nmp = dupmsg(mp)) {
3346fcf3ce44SJohn Forte 				if ((slp->sl_flags & FCIP_SLFAST) &&
3347fcf3ce44SJohn Forte 							!isgroupaddr) {
3348fcf3ce44SJohn Forte 					nmp->b_rptr += hdrlen;
3349fcf3ce44SJohn Forte 					putnext(slp->sl_rq, nmp);
3350fcf3ce44SJohn Forte 				} else if (slp->sl_flags & FCIP_SLRAW) {
3351fcf3ce44SJohn Forte 					/* No headers when FCIP_SLRAW is set */
3352fcf3ce44SJohn Forte 					putnext(slp->sl_rq, nmp);
3353fcf3ce44SJohn Forte 				} else if ((nmp = fcip_addudind(fptr, nmp,
3354fcf3ce44SJohn Forte 				    nhdr, type))) {
3355fcf3ce44SJohn Forte 					putnext(slp->sl_rq, nmp);
3356fcf3ce44SJohn Forte 				}
3357fcf3ce44SJohn Forte 			}
3358fcf3ce44SJohn Forte 		}
3359fcf3ce44SJohn Forte 	}
3360fcf3ce44SJohn Forte 
3361fcf3ce44SJohn Forte 	/*
3362fcf3ce44SJohn Forte 	 * Do the last one.
3363fcf3ce44SJohn Forte 	 */
3364fcf3ce44SJohn Forte 	if (canputnext(slp->sl_rq)) {
3365fcf3ce44SJohn Forte 		if (slp->sl_flags & FCIP_SLFAST) {
3366fcf3ce44SJohn Forte 			mp->b_rptr += hdrlen;
3367fcf3ce44SJohn Forte 			putnext(slp->sl_rq, mp);
3368fcf3ce44SJohn Forte 		} else if (slp->sl_flags & FCIP_SLRAW) {
3369fcf3ce44SJohn Forte 			putnext(slp->sl_rq, mp);
3370fcf3ce44SJohn Forte 		} else if ((mp = fcip_addudind(fptr, mp, nhdr, type))) {
3371fcf3ce44SJohn Forte 			putnext(slp->sl_rq, mp);
3372fcf3ce44SJohn Forte 		}
3373fcf3ce44SJohn Forte 	} else {
3374fcf3ce44SJohn Forte 		freemsg(mp);
3375fcf3ce44SJohn Forte 	}
3376fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_1((fcip_sendup, "fcip io", /* CSTYLED */,
3377fcf3ce44SJohn Forte 	    tnf_string, msg, "fcip sendup done"));
3378fcf3ce44SJohn Forte 
3379fcf3ce44SJohn Forte 	rw_exit(&fcipstruplock);
3380fcf3ce44SJohn Forte }
3381fcf3ce44SJohn Forte 
3382fcf3ce44SJohn Forte /*
3383fcf3ce44SJohn Forte  * Match the stream based on type and wwn if necessary.
3384fcf3ce44SJohn Forte  * Destination wwn dhostp is passed to this routine is reserved
3385fcf3ce44SJohn Forte  * for future usage. We don't need to use it right now since port
3386fcf3ce44SJohn Forte  * to fcip instance mapping is unique and wwn is already validated when
3387fcf3ce44SJohn Forte  * packet comes to fcip.
3388fcf3ce44SJohn Forte  */
3389fcf3ce44SJohn Forte /* ARGSUSED */
3390fcf3ce44SJohn Forte static struct fcipstr *
3391fcf3ce44SJohn Forte fcip_accept(struct fcipstr *slp, struct fcip *fptr, int type, la_wwn_t *dhostp)
3392fcf3ce44SJohn Forte {
3393fcf3ce44SJohn Forte 	t_uscalar_t 	sap;
3394fcf3ce44SJohn Forte 
3395fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_1((fcip_accept, "fcip io", /* CSTYLED */,
3396fcf3ce44SJohn Forte 	    tnf_string, msg, "fcip accept"));
3397fcf3ce44SJohn Forte 
3398fcf3ce44SJohn Forte 	for (; slp; slp = slp->sl_nextp) {
3399fcf3ce44SJohn Forte 		sap = slp->sl_sap;
3400fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_UPSTREAM, (CE_CONT,
3401fcf3ce44SJohn Forte 		    "fcip_accept: checking next sap = %x, type = %x",
3402fcf3ce44SJohn Forte 		    sap, type));
3403fcf3ce44SJohn Forte 
3404fcf3ce44SJohn Forte 		if ((slp->sl_fcip == fptr) && (type == sap)) {
3405fcf3ce44SJohn Forte 			return (slp);
3406fcf3ce44SJohn Forte 		}
3407fcf3ce44SJohn Forte 	}
3408fcf3ce44SJohn Forte 	return (NULL);
3409fcf3ce44SJohn Forte }
3410fcf3ce44SJohn Forte 
3411fcf3ce44SJohn Forte /*
3412fcf3ce44SJohn Forte  * Handle DL_UNITDATA_IND messages
3413fcf3ce44SJohn Forte  */
3414fcf3ce44SJohn Forte static mblk_t *
3415fcf3ce44SJohn Forte fcip_addudind(struct fcip *fptr, mblk_t *mp, fcph_network_hdr_t *nhdr,
3416fcf3ce44SJohn Forte     int type)
3417fcf3ce44SJohn Forte {
3418fcf3ce44SJohn Forte 	dl_unitdata_ind_t	*dludindp;
3419fcf3ce44SJohn Forte 	struct	fcipdladdr	*dlap;
3420fcf3ce44SJohn Forte 	mblk_t	*nmp;
3421fcf3ce44SJohn Forte 	int	size;
3422fcf3ce44SJohn Forte 	uint32_t hdrlen;
3423fcf3ce44SJohn Forte 	struct ether_addr	src_addr;
3424fcf3ce44SJohn Forte 	struct ether_addr	dest_addr;
3425fcf3ce44SJohn Forte 
3426fcf3ce44SJohn Forte 
3427fcf3ce44SJohn Forte 	hdrlen = (sizeof (llc_snap_hdr_t) + sizeof (fcph_network_hdr_t));
3428fcf3ce44SJohn Forte 	mp->b_rptr += hdrlen;
3429fcf3ce44SJohn Forte 
3430fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_1((fcip_addudind, "fcip io", /* CSTYLED */,
3431fcf3ce44SJohn Forte 	    tnf_string, msg, "fcip addudind"));
3432fcf3ce44SJohn Forte 
3433fcf3ce44SJohn Forte 	/*
3434fcf3ce44SJohn Forte 	 * Allocate an M_PROTO mblk for the DL_UNITDATA_IND.
3435fcf3ce44SJohn Forte 	 */
3436fcf3ce44SJohn Forte 	size = sizeof (dl_unitdata_ind_t) + FCIPADDRL + FCIPADDRL;
3437fcf3ce44SJohn Forte 	if ((nmp = allocb(size, BPRI_LO)) == NULL) {
3438fcf3ce44SJohn Forte 		fptr->fcip_allocbfail++;
3439fcf3ce44SJohn Forte 		freemsg(mp);
3440fcf3ce44SJohn Forte 		return (NULL);
3441fcf3ce44SJohn Forte 	}
3442fcf3ce44SJohn Forte 	DB_TYPE(nmp) = M_PROTO;
3443fcf3ce44SJohn Forte 	nmp->b_wptr = nmp->b_datap->db_lim;
3444fcf3ce44SJohn Forte 	nmp->b_rptr = nmp->b_wptr - size;
3445fcf3ce44SJohn Forte 
3446fcf3ce44SJohn Forte 	/*
3447fcf3ce44SJohn Forte 	 * Construct a DL_UNITDATA_IND primitive.
3448fcf3ce44SJohn Forte 	 */
3449fcf3ce44SJohn Forte 	dludindp = (dl_unitdata_ind_t *)nmp->b_rptr;
3450fcf3ce44SJohn Forte 	dludindp->dl_primitive = DL_UNITDATA_IND;
3451fcf3ce44SJohn Forte 	dludindp->dl_dest_addr_length = FCIPADDRL;
3452fcf3ce44SJohn Forte 	dludindp->dl_dest_addr_offset = sizeof (dl_unitdata_ind_t);
3453fcf3ce44SJohn Forte 	dludindp->dl_src_addr_length = FCIPADDRL;
3454fcf3ce44SJohn Forte 	dludindp->dl_src_addr_offset = sizeof (dl_unitdata_ind_t) + FCIPADDRL;
3455fcf3ce44SJohn Forte 	dludindp->dl_group_address = 0;		/* not DL_MULTI */
3456fcf3ce44SJohn Forte 
3457fcf3ce44SJohn Forte 	dlap = (struct fcipdladdr *)(nmp->b_rptr + sizeof (dl_unitdata_ind_t));
3458fcf3ce44SJohn Forte 	wwn_to_ether(&nhdr->net_dest_addr, &dest_addr);
3459fcf3ce44SJohn Forte 	ether_bcopy(&dest_addr, &dlap->dl_phys);
3460fcf3ce44SJohn Forte 	dlap->dl_sap = (uint16_t)type;
3461fcf3ce44SJohn Forte 
3462fcf3ce44SJohn Forte 	dlap = (struct fcipdladdr *)(nmp->b_rptr + sizeof (dl_unitdata_ind_t)
3463fcf3ce44SJohn Forte 		+ FCIPADDRL);
3464fcf3ce44SJohn Forte 	wwn_to_ether(&nhdr->net_src_addr, &src_addr);
3465fcf3ce44SJohn Forte 	ether_bcopy(&src_addr, &dlap->dl_phys);
3466fcf3ce44SJohn Forte 	dlap->dl_sap = (uint16_t)type;
3467fcf3ce44SJohn Forte 
3468fcf3ce44SJohn Forte 	/*
3469fcf3ce44SJohn Forte 	 * Link the M_PROTO and M_DATA together.
3470fcf3ce44SJohn Forte 	 */
3471fcf3ce44SJohn Forte 	nmp->b_cont = mp;
3472fcf3ce44SJohn Forte 	return (nmp);
3473fcf3ce44SJohn Forte }
3474fcf3ce44SJohn Forte 
3475fcf3ce44SJohn Forte 
3476fcf3ce44SJohn Forte /*
3477fcf3ce44SJohn Forte  * The open routine. For clone opens, we return the next available minor
3478fcf3ce44SJohn Forte  * no. for the stream to use
3479fcf3ce44SJohn Forte  */
3480fcf3ce44SJohn Forte /* ARGSUSED */
3481fcf3ce44SJohn Forte static int
3482fcf3ce44SJohn Forte fcip_open(queue_t *rq, dev_t *devp, int flag, int sflag, cred_t *credp)
3483fcf3ce44SJohn Forte {
3484fcf3ce44SJohn Forte 	struct fcipstr	*slp;
3485fcf3ce44SJohn Forte 	struct fcipstr	**prevslp;
3486fcf3ce44SJohn Forte 	minor_t	minor;
3487fcf3ce44SJohn Forte 
3488fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM, (CE_NOTE, "in fcip_open"));
3489fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_1((fcip_open, "fcip io", /* CSTYLED */,
3490fcf3ce44SJohn Forte 		tnf_string, msg, "enter"));
3491fcf3ce44SJohn Forte 	/*
3492fcf3ce44SJohn Forte 	 * We need to ensure that the port driver is loaded before
3493fcf3ce44SJohn Forte 	 * we proceed
3494fcf3ce44SJohn Forte 	 */
3495fcf3ce44SJohn Forte 	if (ddi_hold_installed_driver(ddi_name_to_major(PORT_DRIVER)) == NULL) {
3496fcf3ce44SJohn Forte 		/* no port driver instances found */
3497fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_STARTUP, (CE_WARN,
3498fcf3ce44SJohn Forte 		    "!ddi_hold_installed_driver of fp failed\n"));
3499fcf3ce44SJohn Forte 		return (ENXIO);
3500fcf3ce44SJohn Forte 	}
3501fcf3ce44SJohn Forte 	/* serialize opens */
3502fcf3ce44SJohn Forte 	rw_enter(&fcipstruplock, RW_WRITER);
3503fcf3ce44SJohn Forte 
3504fcf3ce44SJohn Forte 	prevslp = &fcipstrup;
3505fcf3ce44SJohn Forte 	if (sflag == CLONEOPEN) {
3506fcf3ce44SJohn Forte 		minor = 0;
3507fcf3ce44SJohn Forte 		for (; (slp = *prevslp) != NULL; prevslp = &slp->sl_nextp) {
3508fcf3ce44SJohn Forte 			if (minor < slp->sl_minor) {
3509fcf3ce44SJohn Forte 				break;
3510fcf3ce44SJohn Forte 			}
3511fcf3ce44SJohn Forte 			minor ++;
3512fcf3ce44SJohn Forte 		}
3513fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM, (CE_NOTE,
3514fcf3ce44SJohn Forte 		    "getmajor returns 0x%x", getmajor(*devp)));
3515fcf3ce44SJohn Forte 		*devp = makedevice(getmajor(*devp), minor);
3516fcf3ce44SJohn Forte 	} else {
3517fcf3ce44SJohn Forte 		minor = getminor(*devp);
3518fcf3ce44SJohn Forte 	}
3519fcf3ce44SJohn Forte 
3520fcf3ce44SJohn Forte 	/*
3521fcf3ce44SJohn Forte 	 * check if our qp's private area is already initialized. If yes
3522fcf3ce44SJohn Forte 	 * the stream is already open - just return
3523fcf3ce44SJohn Forte 	 */
3524fcf3ce44SJohn Forte 	if (rq->q_ptr) {
3525fcf3ce44SJohn Forte 		goto done;
3526fcf3ce44SJohn Forte 	}
3527fcf3ce44SJohn Forte 
3528fcf3ce44SJohn Forte 	slp = GETSTRUCT(struct fcipstr, 1);
3529fcf3ce44SJohn Forte 	slp->sl_minor = minor;
3530fcf3ce44SJohn Forte 	slp->sl_rq = rq;
3531fcf3ce44SJohn Forte 	slp->sl_sap = 0;
3532fcf3ce44SJohn Forte 	slp->sl_flags = 0;
3533fcf3ce44SJohn Forte 	slp->sl_state = DL_UNATTACHED;
3534fcf3ce44SJohn Forte 	slp->sl_fcip = NULL;
3535fcf3ce44SJohn Forte 
3536fcf3ce44SJohn Forte 	mutex_init(&slp->sl_lock, NULL, MUTEX_DRIVER, NULL);
3537fcf3ce44SJohn Forte 
3538fcf3ce44SJohn Forte 	/*
3539fcf3ce44SJohn Forte 	 * link this new stream entry into list of active streams
3540fcf3ce44SJohn Forte 	 */
3541fcf3ce44SJohn Forte 	slp->sl_nextp = *prevslp;
3542fcf3ce44SJohn Forte 	*prevslp = slp;
3543fcf3ce44SJohn Forte 
3544fcf3ce44SJohn Forte 	rq->q_ptr = WR(rq)->q_ptr = (char *)slp;
3545fcf3ce44SJohn Forte 
3546fcf3ce44SJohn Forte 	/*
3547fcf3ce44SJohn Forte 	 * Disable automatic enabling of our write service procedures
3548fcf3ce44SJohn Forte 	 * we need to control this explicitly. This will prevent
3549fcf3ce44SJohn Forte 	 * anyone scheduling of our write service procedures.
3550fcf3ce44SJohn Forte 	 */
3551fcf3ce44SJohn Forte 	noenable(WR(rq));
3552fcf3ce44SJohn Forte 
3553fcf3ce44SJohn Forte done:
3554fcf3ce44SJohn Forte 	rw_exit(&fcipstruplock);
3555fcf3ce44SJohn Forte 	/*
3556fcf3ce44SJohn Forte 	 * enable our put and service routines on the read side
3557fcf3ce44SJohn Forte 	 */
3558fcf3ce44SJohn Forte 	qprocson(rq);
3559fcf3ce44SJohn Forte 
3560fcf3ce44SJohn Forte 	/*
3561fcf3ce44SJohn Forte 	 * There is only one instance of fcip (instance = 0)
3562fcf3ce44SJohn Forte 	 * for multiple instances of hardware
3563fcf3ce44SJohn Forte 	 */
3564fcf3ce44SJohn Forte 	(void) qassociate(rq, 0);	/* don't allow drcompat to be pushed */
3565fcf3ce44SJohn Forte 	return (0);
3566fcf3ce44SJohn Forte }
3567fcf3ce44SJohn Forte 
3568fcf3ce44SJohn Forte /*
3569fcf3ce44SJohn Forte  * close an opened stream. The minor no. will then be available for
3570fcf3ce44SJohn Forte  * future opens.
3571fcf3ce44SJohn Forte  */
3572fcf3ce44SJohn Forte /* ARGSUSED */
3573fcf3ce44SJohn Forte static int
35745e1743f0SToomas Soome fcip_close(queue_t *rq, int flag, cred_t *credp)
3575fcf3ce44SJohn Forte {
3576fcf3ce44SJohn Forte 	struct fcipstr *slp;
3577fcf3ce44SJohn Forte 	struct fcipstr **prevslp;
3578fcf3ce44SJohn Forte 
3579fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM, (CE_NOTE, "in fcip_close"));
3580fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_1((fcip_close, "fcip io", /* CSTYLED */,
3581fcf3ce44SJohn Forte 		tnf_string, msg, "enter"));
3582fcf3ce44SJohn Forte 	ASSERT(rq);
3583fcf3ce44SJohn Forte 	/* we should also have the active stream pointer in q_ptr */
3584fcf3ce44SJohn Forte 	ASSERT(rq->q_ptr);
3585fcf3ce44SJohn Forte 
3586fcf3ce44SJohn Forte 	ddi_rele_driver(ddi_name_to_major(PORT_DRIVER));
3587fcf3ce44SJohn Forte 	/*
3588fcf3ce44SJohn Forte 	 * disable our put and service procedures. We had enabled them
3589fcf3ce44SJohn Forte 	 * on open
3590fcf3ce44SJohn Forte 	 */
3591fcf3ce44SJohn Forte 	qprocsoff(rq);
3592fcf3ce44SJohn Forte 	slp = (struct fcipstr *)rq->q_ptr;
3593fcf3ce44SJohn Forte 
3594fcf3ce44SJohn Forte 	/*
3595fcf3ce44SJohn Forte 	 * Implicitly detach stream  a stream from an interface.
3596fcf3ce44SJohn Forte 	 */
3597fcf3ce44SJohn Forte 	if (slp->sl_fcip) {
3598fcf3ce44SJohn Forte 		fcip_dodetach(slp);
3599fcf3ce44SJohn Forte 	}
3600fcf3ce44SJohn Forte 
3601fcf3ce44SJohn Forte 	(void) qassociate(rq, -1);	/* undo association in open */
3602fcf3ce44SJohn Forte 
3603fcf3ce44SJohn Forte 	rw_enter(&fcipstruplock, RW_WRITER);
3604fcf3ce44SJohn Forte 
3605fcf3ce44SJohn Forte 	/*
3606fcf3ce44SJohn Forte 	 * unlink this stream from the active stream list and free it
3607fcf3ce44SJohn Forte 	 */
3608fcf3ce44SJohn Forte 	for (prevslp = &fcipstrup; (slp = *prevslp) != NULL;
3609fcf3ce44SJohn Forte 	    prevslp = &slp->sl_nextp) {
3610fcf3ce44SJohn Forte 		if (slp == (struct fcipstr *)rq->q_ptr) {
3611fcf3ce44SJohn Forte 			break;
3612fcf3ce44SJohn Forte 		}
3613fcf3ce44SJohn Forte 	}
3614fcf3ce44SJohn Forte 
3615fcf3ce44SJohn Forte 	/* we should have found slp */
3616fcf3ce44SJohn Forte 	ASSERT(slp);
3617fcf3ce44SJohn Forte 
3618fcf3ce44SJohn Forte 	*prevslp = slp->sl_nextp;
3619fcf3ce44SJohn Forte 	mutex_destroy(&slp->sl_lock);
3620fcf3ce44SJohn Forte 	kmem_free(slp, sizeof (struct fcipstr));
3621fcf3ce44SJohn Forte 	rq->q_ptr = WR(rq)->q_ptr = NULL;
3622fcf3ce44SJohn Forte 
3623fcf3ce44SJohn Forte 	rw_exit(&fcipstruplock);
3624fcf3ce44SJohn Forte 	return (0);
3625fcf3ce44SJohn Forte }
3626fcf3ce44SJohn Forte 
3627fcf3ce44SJohn Forte /*
3628fcf3ce44SJohn Forte  * This is not an extension of the DDI_DETACH request. This routine
3629fcf3ce44SJohn Forte  * only detaches a stream from an interface
3630fcf3ce44SJohn Forte  */
3631fcf3ce44SJohn Forte static void
3632fcf3ce44SJohn Forte fcip_dodetach(struct fcipstr *slp)
3633fcf3ce44SJohn Forte {
3634fcf3ce44SJohn Forte 	struct fcipstr	*tslp;
3635fcf3ce44SJohn Forte 	struct fcip	*fptr;
3636fcf3ce44SJohn Forte 
3637fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_DETACH, (CE_NOTE, "in fcip_dodetach"));
3638fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_1((fcip_dodetach, "fcip io", /* CSTYLED */,
3639fcf3ce44SJohn Forte 		tnf_string, msg, "enter"));
3640fcf3ce44SJohn Forte 	ASSERT(slp->sl_fcip != NULL);
3641fcf3ce44SJohn Forte 
3642fcf3ce44SJohn Forte 	fptr = slp->sl_fcip;
3643fcf3ce44SJohn Forte 	slp->sl_fcip = NULL;
3644fcf3ce44SJohn Forte 
3645fcf3ce44SJohn Forte 	/*
3646fcf3ce44SJohn Forte 	 * we don't support promiscuous mode currently but check
3647fcf3ce44SJohn Forte 	 * for and disable any promiscuous mode operation
3648fcf3ce44SJohn Forte 	 */
3649fcf3ce44SJohn Forte 	if (slp->sl_flags & SLALLPHYS) {
3650fcf3ce44SJohn Forte 		slp->sl_flags &= ~SLALLPHYS;
3651fcf3ce44SJohn Forte 	}
3652fcf3ce44SJohn Forte 
3653fcf3ce44SJohn Forte 	/*
3654fcf3ce44SJohn Forte 	 * disable ALLMULTI mode if all mulitcast addr are ON
3655fcf3ce44SJohn Forte 	 */
3656fcf3ce44SJohn Forte 	if (slp->sl_flags & SLALLMULTI) {
3657fcf3ce44SJohn Forte 		slp->sl_flags &= ~SLALLMULTI;
3658fcf3ce44SJohn Forte 	}
3659fcf3ce44SJohn Forte 
3660fcf3ce44SJohn Forte 	/*
3661fcf3ce44SJohn Forte 	 * we are most likely going to perform multicast by
3662fcf3ce44SJohn Forte 	 * broadcasting to the well known addr (D_ID) 0xFFFFFF or
3663fcf3ce44SJohn Forte 	 * ALPA 0x00 in case of public loops
3664fcf3ce44SJohn Forte 	 */
3665fcf3ce44SJohn Forte 
3666fcf3ce44SJohn Forte 
3667fcf3ce44SJohn Forte 	/*
3668fcf3ce44SJohn Forte 	 * detach unit from device structure.
3669fcf3ce44SJohn Forte 	 */
3670fcf3ce44SJohn Forte 	for (tslp = fcipstrup; tslp != NULL; tslp = tslp->sl_nextp) {
3671fcf3ce44SJohn Forte 		if (tslp->sl_fcip == fptr) {
3672fcf3ce44SJohn Forte 			break;
3673fcf3ce44SJohn Forte 		}
3674fcf3ce44SJohn Forte 	}
3675fcf3ce44SJohn Forte 	if (tslp == NULL) {
3676fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DETACH, (CE_WARN,
3677fcf3ce44SJohn Forte 		"fcip_dodeatch - active stream struct not found"));
3678fcf3ce44SJohn Forte 
3679fcf3ce44SJohn Forte 		/* unregister with Fabric nameserver?? */
3680fcf3ce44SJohn Forte 	}
3681fcf3ce44SJohn Forte 	slp->sl_state = DL_UNATTACHED;
3682fcf3ce44SJohn Forte 
3683fcf3ce44SJohn Forte 	fcip_setipq(fptr);
3684fcf3ce44SJohn Forte }
3685fcf3ce44SJohn Forte 
3686fcf3ce44SJohn Forte 
3687fcf3ce44SJohn Forte /*
3688fcf3ce44SJohn Forte  * Set or clear device ipq pointer.
3689fcf3ce44SJohn Forte  * Walk thru all the streams on this device, if a ETHERTYPE_IP
3690fcf3ce44SJohn Forte  * stream is found, assign device ipq to its sl_rq.
3691fcf3ce44SJohn Forte  */
3692fcf3ce44SJohn Forte static void
3693fcf3ce44SJohn Forte fcip_setipq(struct fcip *fptr)
3694fcf3ce44SJohn Forte {
3695fcf3ce44SJohn Forte 	struct fcipstr	*slp;
3696fcf3ce44SJohn Forte 	int		ok = 1;
3697fcf3ce44SJohn Forte 	queue_t		*ipq = NULL;
3698fcf3ce44SJohn Forte 
3699fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_INIT, (CE_NOTE, "entered fcip_setipq"));
3700fcf3ce44SJohn Forte 
3701fcf3ce44SJohn Forte 	rw_enter(&fcipstruplock, RW_READER);
3702fcf3ce44SJohn Forte 
3703fcf3ce44SJohn Forte 	for (slp = fcipstrup; slp != NULL; slp = slp->sl_nextp) {
3704fcf3ce44SJohn Forte 		if (slp->sl_fcip == fptr) {
3705fcf3ce44SJohn Forte 			if (slp->sl_flags & (SLALLPHYS|SLALLSAP)) {
3706fcf3ce44SJohn Forte 				ok = 0;
3707fcf3ce44SJohn Forte 			}
3708fcf3ce44SJohn Forte 			if (slp->sl_sap == ETHERTYPE_IP) {
3709fcf3ce44SJohn Forte 				if (ipq == NULL) {
3710fcf3ce44SJohn Forte 					ipq = slp->sl_rq;
3711fcf3ce44SJohn Forte 				} else {
3712fcf3ce44SJohn Forte 					ok = 0;
3713fcf3ce44SJohn Forte 				}
3714fcf3ce44SJohn Forte 			}
3715fcf3ce44SJohn Forte 		}
3716fcf3ce44SJohn Forte 	}
3717fcf3ce44SJohn Forte 
3718fcf3ce44SJohn Forte 	rw_exit(&fcipstruplock);
3719fcf3ce44SJohn Forte 
3720fcf3ce44SJohn Forte 	if (fcip_check_port_exists(fptr)) {
3721fcf3ce44SJohn Forte 		/* fptr passed to us is stale */
3722fcf3ce44SJohn Forte 		return;
3723fcf3ce44SJohn Forte 	}
3724fcf3ce44SJohn Forte 
3725fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_mutex);
3726fcf3ce44SJohn Forte 	if (ok) {
3727fcf3ce44SJohn Forte 		fptr->fcip_ipq = ipq;
3728fcf3ce44SJohn Forte 	} else {
3729fcf3ce44SJohn Forte 		fptr->fcip_ipq = NULL;
3730fcf3ce44SJohn Forte 	}
3731fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_mutex);
3732fcf3ce44SJohn Forte }
3733fcf3ce44SJohn Forte 
3734fcf3ce44SJohn Forte 
3735fcf3ce44SJohn Forte /* ARGSUSED */
3736fcf3ce44SJohn Forte static void
3737fcf3ce44SJohn Forte fcip_ioctl(queue_t *wq, mblk_t *mp)
3738fcf3ce44SJohn Forte {
3739fcf3ce44SJohn Forte 	struct iocblk		*iocp = (struct iocblk *)mp->b_rptr;
3740fcf3ce44SJohn Forte 	struct fcipstr		*slp = (struct fcipstr *)wq->q_ptr;
3741fcf3ce44SJohn Forte 
3742fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
3743fcf3ce44SJohn Forte 	    (CE_NOTE, "in fcip ioctl : %d", iocp->ioc_cmd));
3744fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_1((fcip_ioctl, "fcip io", /* CSTYLED */,
3745fcf3ce44SJohn Forte 		tnf_string, msg, "enter"));
3746fcf3ce44SJohn Forte 
3747fcf3ce44SJohn Forte 	switch (iocp->ioc_cmd) {
3748fcf3ce44SJohn Forte 	case DLIOCRAW:
3749fcf3ce44SJohn Forte 		slp->sl_flags |= FCIP_SLRAW;
3750fcf3ce44SJohn Forte 		miocack(wq, mp, 0, 0);
3751fcf3ce44SJohn Forte 		break;
3752fcf3ce44SJohn Forte 
3753fcf3ce44SJohn Forte 	case DL_IOC_HDR_INFO:
3754fcf3ce44SJohn Forte 		fcip_dl_ioc_hdr_info(wq, mp);
3755fcf3ce44SJohn Forte 		break;
3756fcf3ce44SJohn Forte 
3757fcf3ce44SJohn Forte 	default:
3758fcf3ce44SJohn Forte 		miocnak(wq, mp, 0, EINVAL);
3759fcf3ce44SJohn Forte 		break;
3760fcf3ce44SJohn Forte 	}
3761fcf3ce44SJohn Forte }
3762fcf3ce44SJohn Forte 
3763fcf3ce44SJohn Forte /*
3764fcf3ce44SJohn Forte  * The streams 'Put' routine.
3765fcf3ce44SJohn Forte  */
3766fcf3ce44SJohn Forte /* ARGSUSED */
3767fcf3ce44SJohn Forte static int
3768fcf3ce44SJohn Forte fcip_wput(queue_t *wq, mblk_t *mp)
3769fcf3ce44SJohn Forte {
3770fcf3ce44SJohn Forte 	struct fcipstr *slp = (struct fcipstr *)wq->q_ptr;
3771fcf3ce44SJohn Forte 	struct fcip *fptr;
3772fcf3ce44SJohn Forte 	struct fcip_dest *fdestp;
3773fcf3ce44SJohn Forte 	fcph_network_hdr_t *headerp;
3774fcf3ce44SJohn Forte 
3775fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
3776fcf3ce44SJohn Forte 	    (CE_NOTE, "in fcip_wput :: type:%x", DB_TYPE(mp)));
3777fcf3ce44SJohn Forte 
3778fcf3ce44SJohn Forte 	switch (DB_TYPE(mp)) {
3779fcf3ce44SJohn Forte 	case M_DATA: {
3780fcf3ce44SJohn Forte 
3781fcf3ce44SJohn Forte 		fptr = slp->sl_fcip;
3782fcf3ce44SJohn Forte 
3783fcf3ce44SJohn Forte 		if (((slp->sl_flags & (FCIP_SLFAST|FCIP_SLRAW)) == 0) ||
3784fcf3ce44SJohn Forte 		    (slp->sl_state != DL_IDLE) ||
3785fcf3ce44SJohn Forte 		    (fptr == NULL)) {
3786fcf3ce44SJohn Forte 			/*
3787fcf3ce44SJohn Forte 			 * set error in the message block and send a reply
3788fcf3ce44SJohn Forte 			 * back upstream. Sun's merror routine does this
3789fcf3ce44SJohn Forte 			 * for us more cleanly.
3790fcf3ce44SJohn Forte 			 */
3791fcf3ce44SJohn Forte 			merror(wq, mp, EPROTO);
3792fcf3ce44SJohn Forte 			break;
3793fcf3ce44SJohn Forte 		}
3794fcf3ce44SJohn Forte 
3795fcf3ce44SJohn Forte 		/*
3796fcf3ce44SJohn Forte 		 * if any messages are already enqueued or if the interface
3797fcf3ce44SJohn Forte 		 * is in promiscuous mode, causing the packets to loop back
3798fcf3ce44SJohn Forte 		 * up, then enqueue the message. Otherwise just transmit
3799fcf3ce44SJohn Forte 		 * the message. putq() puts the message on fcip's
3800fcf3ce44SJohn Forte 		 * write queue and qenable() puts the queue (wq) on
3801fcf3ce44SJohn Forte 		 * the list of queues to be called by the streams scheduler.
3802fcf3ce44SJohn Forte 		 */
3803fcf3ce44SJohn Forte 		if (wq->q_first) {
3804fcf3ce44SJohn Forte 			(void) putq(wq, mp);
3805fcf3ce44SJohn Forte 			fptr->fcip_wantw = 1;
3806fcf3ce44SJohn Forte 			qenable(wq);
3807fcf3ce44SJohn Forte 		} else if (fptr->fcip_flags & FCIP_PROMISC) {
3808fcf3ce44SJohn Forte 			/*
3809fcf3ce44SJohn Forte 			 * Promiscous mode not supported but add this code in
3810fcf3ce44SJohn Forte 			 * case it will be supported in future.
3811fcf3ce44SJohn Forte 			 */
3812fcf3ce44SJohn Forte 			(void) putq(wq, mp);
3813fcf3ce44SJohn Forte 			qenable(wq);
3814fcf3ce44SJohn Forte 		} else {
3815fcf3ce44SJohn Forte 
3816fcf3ce44SJohn Forte 			headerp = (fcph_network_hdr_t *)mp->b_rptr;
3817fcf3ce44SJohn Forte 			fdestp = fcip_get_dest(fptr, &headerp->net_dest_addr);
3818fcf3ce44SJohn Forte 
3819fcf3ce44SJohn Forte 			if (fdestp == NULL) {
3820fcf3ce44SJohn Forte 				merror(wq, mp, EPROTO);
3821fcf3ce44SJohn Forte 				break;
3822fcf3ce44SJohn Forte 			}
3823fcf3ce44SJohn Forte 
3824fcf3ce44SJohn Forte 			ASSERT(fdestp != NULL);
3825fcf3ce44SJohn Forte 
3826fcf3ce44SJohn Forte 			(void) fcip_start(wq, mp, fptr, fdestp, KM_SLEEP);
3827fcf3ce44SJohn Forte 		}
3828fcf3ce44SJohn Forte 		break;
3829fcf3ce44SJohn Forte 	}
3830fcf3ce44SJohn Forte 	case M_PROTO:
3831fcf3ce44SJohn Forte 	case M_PCPROTO:
3832fcf3ce44SJohn Forte 		/*
3833fcf3ce44SJohn Forte 		 * to prevent recursive calls into fcip_proto
3834fcf3ce44SJohn Forte 		 * (PROTO and PCPROTO messages are handled by fcip_proto)
3835fcf3ce44SJohn Forte 		 * let the service procedure handle these messages by
3836fcf3ce44SJohn Forte 		 * calling putq here.
3837fcf3ce44SJohn Forte 		 */
3838fcf3ce44SJohn Forte 		(void) putq(wq, mp);
3839fcf3ce44SJohn Forte 		qenable(wq);
3840fcf3ce44SJohn Forte 		break;
3841fcf3ce44SJohn Forte 
3842fcf3ce44SJohn Forte 	case M_IOCTL:
3843fcf3ce44SJohn Forte 		fcip_ioctl(wq, mp);
3844fcf3ce44SJohn Forte 		break;
3845fcf3ce44SJohn Forte 
3846fcf3ce44SJohn Forte 	case M_FLUSH:
3847fcf3ce44SJohn Forte 		if (*mp->b_rptr & FLUSHW) {
3848fcf3ce44SJohn Forte 			flushq(wq, FLUSHALL);
3849fcf3ce44SJohn Forte 			*mp->b_rptr &= ~FLUSHW;
3850fcf3ce44SJohn Forte 		}
3851fcf3ce44SJohn Forte 		/*
3852fcf3ce44SJohn Forte 		 * we have both FLUSHW and FLUSHR set with FLUSHRW
3853fcf3ce44SJohn Forte 		 */
3854fcf3ce44SJohn Forte 		if (*mp->b_rptr & FLUSHR) {
3855fcf3ce44SJohn Forte 			/*
3856fcf3ce44SJohn Forte 			 * send msg back upstream. qreply() takes care
3857fcf3ce44SJohn Forte 			 * of using the RD(wq) queue on its reply
3858fcf3ce44SJohn Forte 			 */
3859fcf3ce44SJohn Forte 			qreply(wq, mp);
3860fcf3ce44SJohn Forte 		} else {
3861fcf3ce44SJohn Forte 			freemsg(mp);
3862fcf3ce44SJohn Forte 		}
3863fcf3ce44SJohn Forte 		break;
3864fcf3ce44SJohn Forte 
3865fcf3ce44SJohn Forte 	default:
3866fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
3867fcf3ce44SJohn Forte 		    (CE_NOTE, "default msg type: %x", DB_TYPE(mp)));
3868fcf3ce44SJohn Forte 		freemsg(mp);
3869fcf3ce44SJohn Forte 		break;
3870fcf3ce44SJohn Forte 	}
3871fcf3ce44SJohn Forte 	return (0);
3872fcf3ce44SJohn Forte }
3873fcf3ce44SJohn Forte 
3874fcf3ce44SJohn Forte 
3875fcf3ce44SJohn Forte /*
3876fcf3ce44SJohn Forte  * Handle M_PROTO and M_PCPROTO messages
3877fcf3ce44SJohn Forte  */
3878fcf3ce44SJohn Forte /* ARGSUSED */
3879fcf3ce44SJohn Forte static void
3880fcf3ce44SJohn Forte fcip_proto(queue_t *wq, mblk_t *mp)
3881fcf3ce44SJohn Forte {
3882fcf3ce44SJohn Forte 	union DL_primitives	*dlp;
3883fcf3ce44SJohn Forte 	struct fcipstr		*slp;
3884fcf3ce44SJohn Forte 	t_uscalar_t		prim;
3885fcf3ce44SJohn Forte 
3886fcf3ce44SJohn Forte 	slp = (struct fcipstr *)wq->q_ptr;
3887fcf3ce44SJohn Forte 	dlp = (union DL_primitives *)mp->b_rptr;
3888fcf3ce44SJohn Forte 	prim = dlp->dl_primitive;		/* the DLPI command */
3889fcf3ce44SJohn Forte 
3890fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_5((fcip_proto, "fcip io", /* CSTYLED */,
3891fcf3ce44SJohn Forte 		tnf_string, msg, "enter",
3892fcf3ce44SJohn Forte 		tnf_opaque, wq, wq,
3893fcf3ce44SJohn Forte 		tnf_opaque, mp, mp,
3894fcf3ce44SJohn Forte 		tnf_opaque, MP_DB_TYPE, DB_TYPE(mp),
3895fcf3ce44SJohn Forte 		tnf_opaque, dl_primitive, dlp->dl_primitive));
3896fcf3ce44SJohn Forte 
3897fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_INIT, (CE_NOTE, "dl_primitve : %x", prim));
3898fcf3ce44SJohn Forte 
3899fcf3ce44SJohn Forte 	mutex_enter(&slp->sl_lock);
3900fcf3ce44SJohn Forte 
3901fcf3ce44SJohn Forte 	switch (prim) {
3902fcf3ce44SJohn Forte 	case DL_UNITDATA_REQ:
3903fcf3ce44SJohn Forte 		FCIP_TNF_PROBE_1((fcip_proto, "fcip io", /* CSTYLED */,
3904fcf3ce44SJohn Forte 			tnf_string, msg, "unit data request"));
3905fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_NOTE, "unit data request"));
3906fcf3ce44SJohn Forte 		fcip_udreq(wq, mp);
3907fcf3ce44SJohn Forte 		break;
3908fcf3ce44SJohn Forte 
3909fcf3ce44SJohn Forte 	case DL_ATTACH_REQ:
3910fcf3ce44SJohn Forte 		FCIP_TNF_PROBE_1((fcip_proto, "fcip io", /* CSTYLED */,
3911fcf3ce44SJohn Forte 			tnf_string, msg, "Attach request"));
3912fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_NOTE, "Attach request"));
3913fcf3ce44SJohn Forte 		fcip_areq(wq, mp);
3914fcf3ce44SJohn Forte 		break;
3915fcf3ce44SJohn Forte 
3916fcf3ce44SJohn Forte 	case DL_DETACH_REQ:
3917fcf3ce44SJohn Forte 		FCIP_TNF_PROBE_1((fcip_proto, "fcip io", /* CSTYLED */,
3918fcf3ce44SJohn Forte 			tnf_string, msg, "Detach request"));
3919fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_NOTE, "Detach request"));
3920fcf3ce44SJohn Forte 		fcip_dreq(wq, mp);
3921fcf3ce44SJohn Forte 		break;
3922fcf3ce44SJohn Forte 
3923fcf3ce44SJohn Forte 	case DL_BIND_REQ:
3924fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_NOTE, "Bind request"));
3925fcf3ce44SJohn Forte 		FCIP_TNF_PROBE_1((fcip_proto, "fcip io", /* CSTYLED */,
3926fcf3ce44SJohn Forte 			tnf_string, msg, "Bind request"));
3927fcf3ce44SJohn Forte 		fcip_breq(wq, mp);
3928fcf3ce44SJohn Forte 		break;
3929fcf3ce44SJohn Forte 
3930fcf3ce44SJohn Forte 	case DL_UNBIND_REQ:
3931fcf3ce44SJohn Forte 		FCIP_TNF_PROBE_1((fcip_proto, "fcip io", /* CSTYLED */,
3932fcf3ce44SJohn Forte 			tnf_string, msg, "unbind request"));
3933fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_NOTE, "unbind request"));
3934fcf3ce44SJohn Forte 		fcip_ubreq(wq, mp);
3935fcf3ce44SJohn Forte 		break;
3936fcf3ce44SJohn Forte 
3937fcf3ce44SJohn Forte 	case DL_INFO_REQ:
3938fcf3ce44SJohn Forte 		FCIP_TNF_PROBE_1((fcip_proto, "fcip io", /* CSTYLED */,
3939fcf3ce44SJohn Forte 			tnf_string, msg, "Info request"));
3940fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_NOTE, "Info request"));
3941fcf3ce44SJohn Forte 		fcip_ireq(wq, mp);
3942fcf3ce44SJohn Forte 		break;
3943fcf3ce44SJohn Forte 
3944fcf3ce44SJohn Forte 	case DL_SET_PHYS_ADDR_REQ:
3945fcf3ce44SJohn Forte 		FCIP_TNF_PROBE_1((fcip_proto, "fcip io", /* CSTYLED */,
3946fcf3ce44SJohn Forte 			tnf_string, msg, "set phy addr request"));
3947fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DLPI,
3948fcf3ce44SJohn Forte 		    (CE_NOTE, "set phy addr request"));
3949fcf3ce44SJohn Forte 		fcip_spareq(wq, mp);
3950fcf3ce44SJohn Forte 		break;
3951fcf3ce44SJohn Forte 
3952fcf3ce44SJohn Forte 	case DL_PHYS_ADDR_REQ:
3953fcf3ce44SJohn Forte 		FCIP_TNF_PROBE_1((fcip_proto, "fcip io", /* CSTYLED */,
3954fcf3ce44SJohn Forte 			tnf_string, msg, "phy addr request"));
3955fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_NOTE, "phy addr request"));
3956fcf3ce44SJohn Forte 		fcip_pareq(wq, mp);
3957fcf3ce44SJohn Forte 		break;
3958fcf3ce44SJohn Forte 
3959fcf3ce44SJohn Forte 	case DL_ENABMULTI_REQ:
3960fcf3ce44SJohn Forte 		FCIP_TNF_PROBE_1((fcip_proto, "fcip io", /* CSTYLED */,
3961fcf3ce44SJohn Forte 			tnf_string, msg, "Enable Multicast request"));
3962fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DLPI,
3963fcf3ce44SJohn Forte 		    (CE_NOTE, "Enable Multicast request"));
3964fcf3ce44SJohn Forte 		dlerrorack(wq, mp, prim, DL_UNSUPPORTED, 0);
3965fcf3ce44SJohn Forte 		break;
3966fcf3ce44SJohn Forte 
3967fcf3ce44SJohn Forte 	case DL_DISABMULTI_REQ:
3968fcf3ce44SJohn Forte 		FCIP_TNF_PROBE_1((fcip_proto, "fcip io", /* CSTYLED */,
3969fcf3ce44SJohn Forte 			tnf_string, msg, "Disable Multicast request"));
3970fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DLPI,
3971fcf3ce44SJohn Forte 		    (CE_NOTE, "Disable Multicast request"));
3972fcf3ce44SJohn Forte 		dlerrorack(wq, mp, prim, DL_UNSUPPORTED, 0);
3973fcf3ce44SJohn Forte 		break;
3974fcf3ce44SJohn Forte 
3975fcf3ce44SJohn Forte 	case DL_PROMISCON_REQ:
3976fcf3ce44SJohn Forte 		FCIP_TNF_PROBE_1((fcip_proto, "fcip io", /* CSTYLED */,
3977fcf3ce44SJohn Forte 			tnf_string, msg, "Promiscuous mode ON request"));
3978fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DLPI,
3979fcf3ce44SJohn Forte 		    (CE_NOTE, "Promiscuous mode ON request"));
3980fcf3ce44SJohn Forte 		dlerrorack(wq, mp, prim, DL_UNSUPPORTED, 0);
3981fcf3ce44SJohn Forte 		break;
3982fcf3ce44SJohn Forte 
3983fcf3ce44SJohn Forte 	case DL_PROMISCOFF_REQ:
3984fcf3ce44SJohn Forte 		FCIP_TNF_PROBE_1((fcip_proto, "fcip io", /* CSTYLED */,
3985fcf3ce44SJohn Forte 			tnf_string, msg, "Promiscuous mode OFF request"));
3986fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DLPI,
3987fcf3ce44SJohn Forte 		    (CE_NOTE, "Promiscuous mode OFF request"));
3988fcf3ce44SJohn Forte 		dlerrorack(wq, mp, prim, DL_UNSUPPORTED, 0);
3989fcf3ce44SJohn Forte 		break;
3990fcf3ce44SJohn Forte 
3991fcf3ce44SJohn Forte 	default:
3992fcf3ce44SJohn Forte 		FCIP_TNF_PROBE_1((fcip_proto, "fcip io", /* CSTYLED */,
3993fcf3ce44SJohn Forte 			tnf_string, msg, "Unsupported request"));
3994fcf3ce44SJohn Forte 		dlerrorack(wq, mp, prim, DL_UNSUPPORTED, 0);
3995fcf3ce44SJohn Forte 		break;
3996fcf3ce44SJohn Forte 	}
3997fcf3ce44SJohn Forte 	mutex_exit(&slp->sl_lock);
3998fcf3ce44SJohn Forte }
3999fcf3ce44SJohn Forte 
4000fcf3ce44SJohn Forte /*
4001fcf3ce44SJohn Forte  * Always enqueue M_PROTO and M_PCPROTO messages pn the wq and M_DATA
4002fcf3ce44SJohn Forte  * messages sometimes. Processing of M_PROTO and M_PCPROTO messages
4003fcf3ce44SJohn Forte  * require us to hold fcip's internal locks across (upstream) putnext
4004fcf3ce44SJohn Forte  * calls. Specifically fcip_intr could hold fcip_intrlock and fcipstruplock
4005fcf3ce44SJohn Forte  * when it calls putnext(). That thread could loop back around to call
4006fcf3ce44SJohn Forte  * fcip_wput and eventually fcip_init() to cause a recursive mutex panic
4007fcf3ce44SJohn Forte  *
4008fcf3ce44SJohn Forte  * M_DATA messages are enqueued only if we are out of xmit resources. Once
4009fcf3ce44SJohn Forte  * the transmit resources are available the service procedure is enabled
4010fcf3ce44SJohn Forte  * and an attempt is made to xmit all messages on the wq.
4011fcf3ce44SJohn Forte  */
4012fcf3ce44SJohn Forte /* ARGSUSED */
4013fcf3ce44SJohn Forte static int
4014fcf3ce44SJohn Forte fcip_wsrv(queue_t *wq)
4015fcf3ce44SJohn Forte {
4016fcf3ce44SJohn Forte 	mblk_t		*mp;
4017fcf3ce44SJohn Forte 	struct fcipstr	*slp;
4018fcf3ce44SJohn Forte 	struct fcip	*fptr;
4019fcf3ce44SJohn Forte 	struct fcip_dest *fdestp;
4020fcf3ce44SJohn Forte 	fcph_network_hdr_t *headerp;
4021fcf3ce44SJohn Forte 
4022fcf3ce44SJohn Forte 	slp = (struct fcipstr *)wq->q_ptr;
4023fcf3ce44SJohn Forte 	fptr = slp->sl_fcip;
4024fcf3ce44SJohn Forte 
4025fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_2((fcip_wsrv, "fcip io", /* CSTYLED */,
4026fcf3ce44SJohn Forte 		tnf_string, msg, "enter",
4027fcf3ce44SJohn Forte 		tnf_opaque, wq, wq));
4028fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM, (CE_NOTE, "fcip wsrv"));
4029fcf3ce44SJohn Forte 
4030fcf3ce44SJohn Forte 	while (mp = getq(wq)) {
4031fcf3ce44SJohn Forte 		switch (DB_TYPE(mp)) {
4032fcf3ce44SJohn Forte 		case M_DATA:
4033fcf3ce44SJohn Forte 			if (fptr && mp) {
4034fcf3ce44SJohn Forte 				headerp = (fcph_network_hdr_t *)mp->b_rptr;
4035fcf3ce44SJohn Forte 				fdestp = fcip_get_dest(fptr,
4036fcf3ce44SJohn Forte 				    &headerp->net_dest_addr);
4037fcf3ce44SJohn Forte 				if (fdestp == NULL) {
4038fcf3ce44SJohn Forte 					freemsg(mp);
4039fcf3ce44SJohn Forte 					goto done;
4040fcf3ce44SJohn Forte 				}
4041fcf3ce44SJohn Forte 				if (fcip_start(wq, mp, fptr, fdestp,
4042fcf3ce44SJohn Forte 				    KM_SLEEP)) {
4043fcf3ce44SJohn Forte 					goto done;
4044fcf3ce44SJohn Forte 				}
4045fcf3ce44SJohn Forte 			} else {
4046fcf3ce44SJohn Forte 				freemsg(mp);
4047fcf3ce44SJohn Forte 			}
4048fcf3ce44SJohn Forte 			break;
4049fcf3ce44SJohn Forte 
4050fcf3ce44SJohn Forte 		case M_PROTO:
4051fcf3ce44SJohn Forte 		case M_PCPROTO:
4052fcf3ce44SJohn Forte 			FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
4053fcf3ce44SJohn Forte 			    (CE_NOTE, "PROT msg in wsrv"));
4054fcf3ce44SJohn Forte 			fcip_proto(wq, mp);
4055fcf3ce44SJohn Forte 			break;
4056fcf3ce44SJohn Forte 		default:
4057fcf3ce44SJohn Forte 			break;
4058fcf3ce44SJohn Forte 		}
4059fcf3ce44SJohn Forte 	}
4060fcf3ce44SJohn Forte done:
4061fcf3ce44SJohn Forte 	return (0);
4062fcf3ce44SJohn Forte }
4063fcf3ce44SJohn Forte 
4064fcf3ce44SJohn Forte 
4065fcf3ce44SJohn Forte /*
4066fcf3ce44SJohn Forte  * This routine is called from fcip_wsrv to send a message downstream
4067fcf3ce44SJohn Forte  * on the fibre towards its destination. This routine performs the
4068fcf3ce44SJohn Forte  * actual WWN to D_ID mapping by looking up the routing and destination
4069fcf3ce44SJohn Forte  * tables.
4070fcf3ce44SJohn Forte  */
4071fcf3ce44SJohn Forte /* ARGSUSED */
4072fcf3ce44SJohn Forte static int
4073fcf3ce44SJohn Forte fcip_start(queue_t *wq, mblk_t *mp, struct fcip *fptr,
4074fcf3ce44SJohn Forte     struct fcip_dest *fdestp, int flags)
4075fcf3ce44SJohn Forte {
4076fcf3ce44SJohn Forte 	int			rval;
4077fcf3ce44SJohn Forte 	int			free;
4078fcf3ce44SJohn Forte 	fcip_pkt_t		*fcip_pkt;
4079fcf3ce44SJohn Forte 	fc_packet_t		*fc_pkt;
4080fcf3ce44SJohn Forte 	fcip_port_info_t	*fport = fptr->fcip_port_info;
4081fcf3ce44SJohn Forte 	size_t			datalen;
4082fcf3ce44SJohn Forte 
4083fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_4((fcip_start, "fcip io", /* CSTYLED */,
4084fcf3ce44SJohn Forte 	    tnf_string, msg, "enter", tnf_opaque, wq, wq,
4085fcf3ce44SJohn Forte 	    tnf_opaque, mp, mp,
4086fcf3ce44SJohn Forte 	    tnf_opaque, MP_DB_TYPE, DB_TYPE(mp)));
4087fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM, (CE_NOTE, "in fcipstart"));
4088fcf3ce44SJohn Forte 
4089fcf3ce44SJohn Forte 	ASSERT(fdestp != NULL);
4090fcf3ce44SJohn Forte 
4091fcf3ce44SJohn Forte 	/*
4092fcf3ce44SJohn Forte 	 * Only return if port has gone offline and not come back online
4093fcf3ce44SJohn Forte 	 * in a while
4094fcf3ce44SJohn Forte 	 */
4095fcf3ce44SJohn Forte 	if (fptr->fcip_flags & FCIP_LINK_DOWN) {
4096fcf3ce44SJohn Forte 		freemsg(mp);
4097fcf3ce44SJohn Forte 		return (0);
4098fcf3ce44SJohn Forte 	}
4099fcf3ce44SJohn Forte 
4100fcf3ce44SJohn Forte 	/*
4101fcf3ce44SJohn Forte 	 * The message block coming in here already has the network and
4102fcf3ce44SJohn Forte 	 * llc_snap hdr stuffed in
4103fcf3ce44SJohn Forte 	 */
4104fcf3ce44SJohn Forte 	/*
4105fcf3ce44SJohn Forte 	 * Traditionally ethernet drivers at sun handle 3 cases here -
4106fcf3ce44SJohn Forte 	 * 1. messages with one mblk
4107fcf3ce44SJohn Forte 	 * 2. messages with 2 mblks
4108fcf3ce44SJohn Forte 	 * 3. messages with >2 mblks
4109fcf3ce44SJohn Forte 	 * For now lets handle all the 3 cases in a single case where we
4110fcf3ce44SJohn Forte 	 * put them together in one mblk that has all the data
4111fcf3ce44SJohn Forte 	 */
4112fcf3ce44SJohn Forte 
4113fcf3ce44SJohn Forte 	if (mp->b_cont != NULL) {
4114fcf3ce44SJohn Forte 		if (!pullupmsg(mp, -1)) {
4115fcf3ce44SJohn Forte 			FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
4116fcf3ce44SJohn Forte 			    (CE_WARN, "failed to concat message"));
4117fcf3ce44SJohn Forte 			freemsg(mp);
4118fcf3ce44SJohn Forte 			return (1);
4119fcf3ce44SJohn Forte 		}
4120fcf3ce44SJohn Forte 	}
4121fcf3ce44SJohn Forte 
4122fcf3ce44SJohn Forte 	datalen = msgsize(mp);
4123fcf3ce44SJohn Forte 
4124fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM, (CE_NOTE,
4125fcf3ce44SJohn Forte 	    "msgsize with nhdr & llcsnap hdr in fcip_pkt_alloc 0x%lx",
4126fcf3ce44SJohn Forte 	    datalen));
4127fcf3ce44SJohn Forte 
4128fcf3ce44SJohn Forte 	/*
4129fcf3ce44SJohn Forte 	 * We cannot have requests larger than FCIPMTU+Headers
4130fcf3ce44SJohn Forte 	 */
4131fcf3ce44SJohn Forte 	if (datalen > (FCIPMTU + sizeof (llc_snap_hdr_t) +
4132fcf3ce44SJohn Forte 		sizeof (fcph_network_hdr_t))) {
4133fcf3ce44SJohn Forte 		freemsg(mp);
4134fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM, (CE_NOTE,
4135fcf3ce44SJohn Forte 		    "fcip_pkt_alloc: datalen is larger than "
4136fcf3ce44SJohn Forte 		    "max possible size."));
4137fcf3ce44SJohn Forte 		return (1);
4138fcf3ce44SJohn Forte 	}
4139fcf3ce44SJohn Forte 
4140fcf3ce44SJohn Forte 	fcip_pkt = fcip_pkt_alloc(fptr, mp, flags, datalen);
4141fcf3ce44SJohn Forte 	if (fcip_pkt == NULL) {
4142fcf3ce44SJohn Forte 		(void) putbq(wq, mp);
4143fcf3ce44SJohn Forte 		return (1);
4144fcf3ce44SJohn Forte 	}
4145fcf3ce44SJohn Forte 
4146fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_mp = mp;
4147fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_wq = wq;
4148fcf3ce44SJohn Forte 	fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
4149fcf3ce44SJohn Forte 
4150fcf3ce44SJohn Forte 	mutex_enter(&fdestp->fcipd_mutex);
4151fcf3ce44SJohn Forte 	/*
4152fcf3ce44SJohn Forte 	 * If the device dynamically disappeared, just fail the request.
4153fcf3ce44SJohn Forte 	 */
4154fcf3ce44SJohn Forte 	if (fdestp->fcipd_rtable == NULL) {
4155fcf3ce44SJohn Forte 		mutex_exit(&fdestp->fcipd_mutex);
4156fcf3ce44SJohn Forte 		fcip_pkt_free(fcip_pkt, 1);
4157fcf3ce44SJohn Forte 		return (1);
4158fcf3ce44SJohn Forte 	}
4159fcf3ce44SJohn Forte 
4160fcf3ce44SJohn Forte 	/*
4161fcf3ce44SJohn Forte 	 * Now that we've assigned pkt_pd, we can call fc_ulp_init_packet
4162fcf3ce44SJohn Forte 	 */
4163fcf3ce44SJohn Forte 
4164fcf3ce44SJohn Forte 	fc_pkt->pkt_pd = fdestp->fcipd_pd;
4165fcf3ce44SJohn Forte 
4166fcf3ce44SJohn Forte 	if (fc_ulp_init_packet((opaque_t)fport->fcipp_handle,
4167fcf3ce44SJohn Forte 	    fc_pkt, flags) != FC_SUCCESS) {
4168fcf3ce44SJohn Forte 		mutex_exit(&fdestp->fcipd_mutex);
4169fcf3ce44SJohn Forte 		fcip_pkt_free(fcip_pkt, 1);
4170fcf3ce44SJohn Forte 		return (1);
4171fcf3ce44SJohn Forte 	}
4172fcf3ce44SJohn Forte 
4173fcf3ce44SJohn Forte 	fcip_fdestp_enqueue_pkt(fdestp, fcip_pkt);
4174fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_dest = fdestp;
4175fcf3ce44SJohn Forte 	fc_pkt->pkt_fca_device = fdestp->fcipd_fca_dev;
4176fcf3ce44SJohn Forte 
4177fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM, (CE_NOTE,
4178fcf3ce44SJohn Forte 	    "setting cmdlen to 0x%x: rsp 0x%x : data 0x%x",
4179fcf3ce44SJohn Forte 	    fc_pkt->pkt_cmdlen, fc_pkt->pkt_rsplen, fc_pkt->pkt_datalen));
4180fcf3ce44SJohn Forte 
4181fcf3ce44SJohn Forte 	fcip_init_unicast_pkt(fcip_pkt, fport->fcipp_sid,
4182fcf3ce44SJohn Forte 	    fdestp->fcipd_did, fcip_pkt_callback);
4183fcf3ce44SJohn Forte 
4184fcf3ce44SJohn Forte 	fdestp->fcipd_ncmds++;
4185fcf3ce44SJohn Forte 
4186fcf3ce44SJohn Forte 	mutex_exit(&fdestp->fcipd_mutex);
4187fcf3ce44SJohn Forte 	if ((rval = fcip_transport(fcip_pkt)) == FC_SUCCESS) {
4188fcf3ce44SJohn Forte 		fptr->fcip_opackets++;
4189fcf3ce44SJohn Forte 		return (0);
4190fcf3ce44SJohn Forte 	}
4191fcf3ce44SJohn Forte 
4192fcf3ce44SJohn Forte 	free = (rval == FC_STATEC_BUSY || rval == FC_OFFLINE ||
4193fcf3ce44SJohn Forte 	    rval == FC_TRAN_BUSY) ? 0 : 1;
4194fcf3ce44SJohn Forte 
4195fcf3ce44SJohn Forte 	mutex_enter(&fdestp->fcipd_mutex);
4196fcf3ce44SJohn Forte 	rval = fcip_fdestp_dequeue_pkt(fdestp, fcip_pkt);
4197fcf3ce44SJohn Forte 
4198fcf3ce44SJohn Forte 	if (!rval) {
4199fcf3ce44SJohn Forte 		fcip_pkt = NULL;
4200fcf3ce44SJohn Forte 	} else {
4201fcf3ce44SJohn Forte 		fdestp->fcipd_ncmds--;
4202fcf3ce44SJohn Forte 	}
4203fcf3ce44SJohn Forte 	mutex_exit(&fdestp->fcipd_mutex);
4204fcf3ce44SJohn Forte 
4205fcf3ce44SJohn Forte 	if (fcip_pkt != NULL) {
4206fcf3ce44SJohn Forte 		fcip_pkt_free(fcip_pkt, free);
4207fcf3ce44SJohn Forte 	}
4208fcf3ce44SJohn Forte 
4209fcf3ce44SJohn Forte 	if (!free) {
4210fcf3ce44SJohn Forte 		(void) putbq(wq, mp);
4211fcf3ce44SJohn Forte 	}
4212fcf3ce44SJohn Forte 
4213fcf3ce44SJohn Forte 	return (1);
4214fcf3ce44SJohn Forte }
4215fcf3ce44SJohn Forte 
4216fcf3ce44SJohn Forte 
4217fcf3ce44SJohn Forte /*
4218fcf3ce44SJohn Forte  * This routine enqueus a packet marked to be issued to the
4219fcf3ce44SJohn Forte  * transport in the dest structure. This enables us to timeout any
4220fcf3ce44SJohn Forte  * request stuck with the FCA/transport for long periods of time
4221fcf3ce44SJohn Forte  * without a response. fcip_pkt_timeout will attempt to clean up
4222fcf3ce44SJohn Forte  * any packets hung in this state of limbo.
4223fcf3ce44SJohn Forte  */
4224fcf3ce44SJohn Forte static void
4225fcf3ce44SJohn Forte fcip_fdestp_enqueue_pkt(struct fcip_dest *fdestp, fcip_pkt_t *fcip_pkt)
4226fcf3ce44SJohn Forte {
4227fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&fdestp->fcipd_mutex));
4228fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_1((fcip_fdestp_enqueue_pkt, "fcip io", /* CSTYLED */,
4229fcf3ce44SJohn Forte 		tnf_string, msg, "destp enq pkt"));
4230fcf3ce44SJohn Forte 
4231fcf3ce44SJohn Forte 	/*
4232fcf3ce44SJohn Forte 	 * Just hang it off the head of packet list
4233fcf3ce44SJohn Forte 	 */
4234fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_next = fdestp->fcipd_head;
4235fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_prev = NULL;
4236fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_flags |= FCIP_PKT_IN_LIST;
4237fcf3ce44SJohn Forte 
4238fcf3ce44SJohn Forte 	if (fdestp->fcipd_head != NULL) {
4239fcf3ce44SJohn Forte 		ASSERT(fdestp->fcipd_head->fcip_pkt_prev == NULL);
4240fcf3ce44SJohn Forte 		fdestp->fcipd_head->fcip_pkt_prev = fcip_pkt;
4241fcf3ce44SJohn Forte 	}
4242fcf3ce44SJohn Forte 
4243fcf3ce44SJohn Forte 	fdestp->fcipd_head = fcip_pkt;
4244fcf3ce44SJohn Forte }
4245fcf3ce44SJohn Forte 
4246fcf3ce44SJohn Forte 
4247fcf3ce44SJohn Forte /*
4248fcf3ce44SJohn Forte  * dequeues any packets after the transport/FCA tells us it has
4249fcf3ce44SJohn Forte  * been successfully sent on its way. Ofcourse it doesn't mean that
4250fcf3ce44SJohn Forte  * the packet will actually reach its destination but its atleast
4251fcf3ce44SJohn Forte  * a step closer in that direction
4252fcf3ce44SJohn Forte  */
4253fcf3ce44SJohn Forte static int
4254fcf3ce44SJohn Forte fcip_fdestp_dequeue_pkt(struct fcip_dest *fdestp, fcip_pkt_t *fcip_pkt)
4255fcf3ce44SJohn Forte {
4256fcf3ce44SJohn Forte 	fcip_pkt_t	*fcipd_pkt;
4257fcf3ce44SJohn Forte 
4258fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&fdestp->fcipd_mutex));
4259fcf3ce44SJohn Forte 	if (fcip_pkt->fcip_pkt_flags & FCIP_PKT_IN_TIMEOUT) {
4260fcf3ce44SJohn Forte 		fcipd_pkt = fdestp->fcipd_head;
4261fcf3ce44SJohn Forte 		while (fcipd_pkt) {
4262fcf3ce44SJohn Forte 			if (fcipd_pkt == fcip_pkt) {
4263fcf3ce44SJohn Forte 				fcip_pkt_t	*pptr = NULL;
4264fcf3ce44SJohn Forte 
4265fcf3ce44SJohn Forte 				if (fcipd_pkt == fdestp->fcipd_head) {
4266fcf3ce44SJohn Forte 					ASSERT(fcipd_pkt->fcip_pkt_prev ==
4267fcf3ce44SJohn Forte 					    NULL);
4268fcf3ce44SJohn Forte 					fdestp->fcipd_head =
4269fcf3ce44SJohn Forte 					    fcipd_pkt->fcip_pkt_next;
4270fcf3ce44SJohn Forte 				} else {
4271fcf3ce44SJohn Forte 					pptr = fcipd_pkt->fcip_pkt_prev;
4272fcf3ce44SJohn Forte 					ASSERT(pptr != NULL);
4273fcf3ce44SJohn Forte 					pptr->fcip_pkt_next =
4274fcf3ce44SJohn Forte 					    fcipd_pkt->fcip_pkt_next;
4275fcf3ce44SJohn Forte 				}
4276fcf3ce44SJohn Forte 				if (fcipd_pkt->fcip_pkt_next) {
4277fcf3ce44SJohn Forte 					pptr = fcipd_pkt->fcip_pkt_next;
4278fcf3ce44SJohn Forte 					pptr->fcip_pkt_prev =
4279fcf3ce44SJohn Forte 					    fcipd_pkt->fcip_pkt_prev;
4280fcf3ce44SJohn Forte 				}
4281fcf3ce44SJohn Forte 				fcip_pkt->fcip_pkt_flags &= ~FCIP_PKT_IN_LIST;
4282fcf3ce44SJohn Forte 				break;
4283fcf3ce44SJohn Forte 			}
4284fcf3ce44SJohn Forte 			fcipd_pkt = fcipd_pkt->fcip_pkt_next;
4285fcf3ce44SJohn Forte 		}
4286fcf3ce44SJohn Forte 	} else {
4287fcf3ce44SJohn Forte 		if (fcip_pkt->fcip_pkt_prev == NULL) {
4288fcf3ce44SJohn Forte 			ASSERT(fdestp->fcipd_head == fcip_pkt);
4289fcf3ce44SJohn Forte 			fdestp->fcipd_head = fcip_pkt->fcip_pkt_next;
4290fcf3ce44SJohn Forte 		} else {
4291fcf3ce44SJohn Forte 			fcip_pkt->fcip_pkt_prev->fcip_pkt_next =
4292fcf3ce44SJohn Forte 			    fcip_pkt->fcip_pkt_next;
4293fcf3ce44SJohn Forte 		}
4294fcf3ce44SJohn Forte 
4295fcf3ce44SJohn Forte 		if (fcip_pkt->fcip_pkt_next) {
4296fcf3ce44SJohn Forte 			fcip_pkt->fcip_pkt_next->fcip_pkt_prev =
4297fcf3ce44SJohn Forte 			    fcip_pkt->fcip_pkt_prev;
4298fcf3ce44SJohn Forte 		}
4299fcf3ce44SJohn Forte 
4300fcf3ce44SJohn Forte 		fcipd_pkt = fcip_pkt;
4301fcf3ce44SJohn Forte 		fcip_pkt->fcip_pkt_flags &= ~FCIP_PKT_IN_LIST;
4302fcf3ce44SJohn Forte 	}
4303fcf3ce44SJohn Forte 
4304fcf3ce44SJohn Forte 	return (fcipd_pkt == fcip_pkt);
4305fcf3ce44SJohn Forte }
4306fcf3ce44SJohn Forte 
4307fcf3ce44SJohn Forte /*
4308fcf3ce44SJohn Forte  * The transport routine - this is the routine that actually calls
4309fcf3ce44SJohn Forte  * into the FCA driver (through the transport ofcourse) to transmit a
4310fcf3ce44SJohn Forte  * datagram on the fibre. The dest struct assoicated with the port to
4311fcf3ce44SJohn Forte  * which the data is intended is already bound to the packet, this routine
4312fcf3ce44SJohn Forte  * only takes care of marking the packet a broadcast packet if it is
4313fcf3ce44SJohn Forte  * intended to be a broadcast request. This permits the transport to send
4314fcf3ce44SJohn Forte  * the packet down on the wire even if it doesn't have an entry for the
4315fcf3ce44SJohn Forte  * D_ID in its d_id hash tables.
4316fcf3ce44SJohn Forte  */
4317fcf3ce44SJohn Forte static int
4318fcf3ce44SJohn Forte fcip_transport(fcip_pkt_t *fcip_pkt)
4319fcf3ce44SJohn Forte {
4320fcf3ce44SJohn Forte 	struct fcip		*fptr;
4321fcf3ce44SJohn Forte 	fc_packet_t		*fc_pkt;
4322fcf3ce44SJohn Forte 	fcip_port_info_t	*fport;
4323fcf3ce44SJohn Forte 	struct fcip_dest	*fdestp;
4324fcf3ce44SJohn Forte 	uint32_t		did;
4325fcf3ce44SJohn Forte 	int			rval = FC_FAILURE;
4326fcf3ce44SJohn Forte 	struct fcip_routing_table *frp = NULL;
4327fcf3ce44SJohn Forte 
4328fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_1((fcip_transport, "fcip io", /* CSTYLED */,
4329fcf3ce44SJohn Forte 		tnf_string, msg, "enter"));
4330fcf3ce44SJohn Forte 
4331fcf3ce44SJohn Forte 	fptr = fcip_pkt->fcip_pkt_fptr;
4332fcf3ce44SJohn Forte 	fport = fptr->fcip_port_info;
4333fcf3ce44SJohn Forte 	fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
4334fcf3ce44SJohn Forte 	fdestp = fcip_pkt->fcip_pkt_dest;
4335fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM, (CE_WARN, "fcip_transport called"));
4336fcf3ce44SJohn Forte 
4337fcf3ce44SJohn Forte 	did = fptr->fcip_broadcast_did;
4338fcf3ce44SJohn Forte 	if (fc_pkt->pkt_cmd_fhdr.d_id == did &&
4339fcf3ce44SJohn Forte 	    fc_pkt->pkt_tran_type != FC_PKT_BROADCAST) {
4340fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
4341fcf3ce44SJohn Forte 		    (CE_NOTE, "trantype set to BROADCAST"));
4342fcf3ce44SJohn Forte 		fc_pkt->pkt_tran_type = FC_PKT_BROADCAST;
4343fcf3ce44SJohn Forte 	}
4344fcf3ce44SJohn Forte 
4345fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_mutex);
4346fcf3ce44SJohn Forte 	if ((fc_pkt->pkt_tran_type != FC_PKT_BROADCAST) &&
4347fcf3ce44SJohn Forte 	    (fc_pkt->pkt_pd == NULL)) {
4348fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_mutex);
4349fcf3ce44SJohn Forte 		FCIP_TNF_PROBE_1((fcip_transport, "fcip io", /* CSTYLED */,
4350fcf3ce44SJohn Forte 		    tnf_string, msg, "fcip transport no pd"));
4351fcf3ce44SJohn Forte 		return (rval);
4352fcf3ce44SJohn Forte 	} else if (fptr->fcip_port_state == FCIP_PORT_OFFLINE) {
4353fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_mutex);
4354fcf3ce44SJohn Forte 		FCIP_TNF_PROBE_1((fcip_transport, "fcip io", /* CSTYLED */,
4355fcf3ce44SJohn Forte 		    tnf_string, msg, "fcip transport port offline"));
4356fcf3ce44SJohn Forte 		return (FC_TRAN_BUSY);
4357fcf3ce44SJohn Forte 	}
4358fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_mutex);
4359fcf3ce44SJohn Forte 
4360fcf3ce44SJohn Forte 	if (fdestp) {
4361fcf3ce44SJohn Forte 		struct fcip_routing_table 	*frp;
4362fcf3ce44SJohn Forte 
4363fcf3ce44SJohn Forte 		frp = fdestp->fcipd_rtable;
4364fcf3ce44SJohn Forte 		mutex_enter(&fptr->fcip_rt_mutex);
4365fcf3ce44SJohn Forte 		mutex_enter(&fdestp->fcipd_mutex);
4366fcf3ce44SJohn Forte 		if (fc_pkt->pkt_pd != NULL) {
4367fcf3ce44SJohn Forte 			if ((frp == NULL) ||
4368fcf3ce44SJohn Forte 			    (frp && FCIP_RTE_UNAVAIL(frp->fcipr_state))) {
4369fcf3ce44SJohn Forte 				mutex_exit(&fdestp->fcipd_mutex);
4370fcf3ce44SJohn Forte 				mutex_exit(&fptr->fcip_rt_mutex);
4371fcf3ce44SJohn Forte 				if (frp &&
4372fcf3ce44SJohn Forte 				    (frp->fcipr_state == FCIP_RT_INVALID)) {
4373fcf3ce44SJohn Forte 					FCIP_TNF_PROBE_1((fcip_transport,
4374fcf3ce44SJohn Forte 					    "fcip io", /* CSTYLED */,
4375fcf3ce44SJohn Forte 					    tnf_string, msg,
4376fcf3ce44SJohn Forte 					    "fcip transport - TRANBUSY"));
4377fcf3ce44SJohn Forte 					return (FC_TRAN_BUSY);
4378fcf3ce44SJohn Forte 				} else {
4379fcf3ce44SJohn Forte 					FCIP_TNF_PROBE_1((fcip_transport,
4380fcf3ce44SJohn Forte 					    "fcip io", /* CSTYLED */,
4381fcf3ce44SJohn Forte 					    tnf_string, msg,
4382fcf3ce44SJohn Forte 					    "fcip transport: frp unavailable"));
4383fcf3ce44SJohn Forte 					return (rval);
4384fcf3ce44SJohn Forte 				}
4385fcf3ce44SJohn Forte 			}
4386fcf3ce44SJohn Forte 		}
4387fcf3ce44SJohn Forte 		mutex_exit(&fdestp->fcipd_mutex);
4388fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_rt_mutex);
4389fcf3ce44SJohn Forte 		ASSERT(fcip_pkt->fcip_pkt_flags & FCIP_PKT_IN_LIST);
4390fcf3ce44SJohn Forte 	}
4391fcf3ce44SJohn Forte 
4392fcf3ce44SJohn Forte 	/* Explicitly invalidate this field till fcip decides to use it */
4393fcf3ce44SJohn Forte 	fc_pkt->pkt_ulp_rscn_infop = NULL;
4394fcf3ce44SJohn Forte 
4395fcf3ce44SJohn Forte 	rval = fc_ulp_transport(fport->fcipp_handle, fc_pkt);
4396fcf3ce44SJohn Forte 	if (rval == FC_STATEC_BUSY || rval == FC_OFFLINE) {
4397fcf3ce44SJohn Forte 		/*
4398fcf3ce44SJohn Forte 		 * Need to queue up the command for retry
4399fcf3ce44SJohn Forte 		 */
4400fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
4401fcf3ce44SJohn Forte 		    (CE_WARN, "ulp_transport failed: 0x%x", rval));
4402fcf3ce44SJohn Forte 	} else if (rval == FC_LOGINREQ && (frp != NULL)) {
4403fcf3ce44SJohn Forte 		(void) fcip_do_plogi(fptr, frp);
4404fcf3ce44SJohn Forte 	} else if (rval == FC_BADPACKET && (frp != NULL)) {
4405fcf3ce44SJohn Forte 		/*
4406fcf3ce44SJohn Forte 		 * There is a distinct possiblity in our scheme of things
4407fcf3ce44SJohn Forte 		 * that we have a routing table entry with a NULL pd struct.
4408fcf3ce44SJohn Forte 		 * Mark the routing table entry for removal if it is not a
4409fcf3ce44SJohn Forte 		 * broadcast entry
4410fcf3ce44SJohn Forte 		 */
4411fcf3ce44SJohn Forte 		if ((frp->fcipr_d_id.port_id != 0x0) &&
4412fcf3ce44SJohn Forte 		    (frp->fcipr_d_id.port_id != 0xffffff)) {
4413fcf3ce44SJohn Forte 			mutex_enter(&fptr->fcip_rt_mutex);
4414fcf3ce44SJohn Forte 			frp->fcipr_pd = NULL;
4415fcf3ce44SJohn Forte 			frp->fcipr_state = PORT_DEVICE_INVALID;
4416fcf3ce44SJohn Forte 			mutex_exit(&fptr->fcip_rt_mutex);
4417fcf3ce44SJohn Forte 		}
4418fcf3ce44SJohn Forte 	}
4419fcf3ce44SJohn Forte 
4420fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_1((fcip_transport, "fcip io", /* CSTYLED */,
4421fcf3ce44SJohn Forte 	    tnf_string, msg, "fcip transport done"));
4422fcf3ce44SJohn Forte 	return (rval);
4423fcf3ce44SJohn Forte }
4424fcf3ce44SJohn Forte 
4425fcf3ce44SJohn Forte /*
4426fcf3ce44SJohn Forte  * Call back routine. Called by the FCA/transport when the messages
4427fcf3ce44SJohn Forte  * has been put onto the wire towards its intended destination. We can
4428fcf3ce44SJohn Forte  * now free the fc_packet associated with the message
4429fcf3ce44SJohn Forte  */
4430fcf3ce44SJohn Forte static void
4431fcf3ce44SJohn Forte fcip_pkt_callback(fc_packet_t *fc_pkt)
4432fcf3ce44SJohn Forte {
4433fcf3ce44SJohn Forte 	int			rval;
4434fcf3ce44SJohn Forte 	fcip_pkt_t		*fcip_pkt;
4435fcf3ce44SJohn Forte 	struct fcip_dest	*fdestp;
4436fcf3ce44SJohn Forte 
4437fcf3ce44SJohn Forte 	fcip_pkt = (fcip_pkt_t *)fc_pkt->pkt_ulp_private;
4438fcf3ce44SJohn Forte 	fdestp = fcip_pkt->fcip_pkt_dest;
4439fcf3ce44SJohn Forte 
4440fcf3ce44SJohn Forte 	/*
4441fcf3ce44SJohn Forte 	 * take the lock early so that we don't have a race condition
4442fcf3ce44SJohn Forte 	 * with fcip_timeout
4443fcf3ce44SJohn Forte 	 *
4444fcf3ce44SJohn Forte 	 * fdestp->fcipd_mutex isn't really intended to lock per
4445fcf3ce44SJohn Forte 	 * packet struct - see bug 5105592 for permanent solution
4446fcf3ce44SJohn Forte 	 */
4447fcf3ce44SJohn Forte 	mutex_enter(&fdestp->fcipd_mutex);
4448fcf3ce44SJohn Forte 
4449fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_flags |= FCIP_PKT_RETURNED;
4450fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_flags &= ~FCIP_PKT_IN_ABORT;
4451fcf3ce44SJohn Forte 	if (fcip_pkt->fcip_pkt_flags & FCIP_PKT_IN_TIMEOUT) {
4452fcf3ce44SJohn Forte 		mutex_exit(&fdestp->fcipd_mutex);
4453fcf3ce44SJohn Forte 		return;
4454fcf3ce44SJohn Forte 	}
4455fcf3ce44SJohn Forte 
4456fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM, (CE_NOTE, "pkt callback"));
4457fcf3ce44SJohn Forte 
4458fcf3ce44SJohn Forte 	ASSERT(fdestp->fcipd_rtable != NULL);
4459fcf3ce44SJohn Forte 	ASSERT(fcip_pkt->fcip_pkt_flags & FCIP_PKT_IN_LIST);
4460fcf3ce44SJohn Forte 	rval = fcip_fdestp_dequeue_pkt(fdestp, fcip_pkt);
4461fcf3ce44SJohn Forte 	fdestp->fcipd_ncmds--;
4462fcf3ce44SJohn Forte 	mutex_exit(&fdestp->fcipd_mutex);
4463fcf3ce44SJohn Forte 
4464fcf3ce44SJohn Forte 	if (rval) {
4465fcf3ce44SJohn Forte 		fcip_pkt_free(fcip_pkt, 1);
4466fcf3ce44SJohn Forte 	}
4467fcf3ce44SJohn Forte 
4468fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_1((fcip_pkt_callback, "fcip io", /* CSTYLED */,
4469fcf3ce44SJohn Forte 		tnf_string, msg, "pkt callback done"));
4470fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM, (CE_NOTE, "pkt callback done"));
4471fcf3ce44SJohn Forte }
4472fcf3ce44SJohn Forte 
4473fcf3ce44SJohn Forte /*
4474fcf3ce44SJohn Forte  * Return 1 if the topology is supported, else return 0.
4475fcf3ce44SJohn Forte  * Topology support is consistent with what the whole
4476fcf3ce44SJohn Forte  * stack supports together.
4477fcf3ce44SJohn Forte  */
4478fcf3ce44SJohn Forte static int
4479fcf3ce44SJohn Forte fcip_is_supported_fc_topology(int fc_topology)
4480fcf3ce44SJohn Forte {
4481fcf3ce44SJohn Forte 	switch (fc_topology) {
4482fcf3ce44SJohn Forte 
4483fcf3ce44SJohn Forte 	case FC_TOP_PRIVATE_LOOP :
4484fcf3ce44SJohn Forte 	case FC_TOP_PUBLIC_LOOP :
4485fcf3ce44SJohn Forte 	case FC_TOP_FABRIC :
4486fcf3ce44SJohn Forte 	case FC_TOP_NO_NS :
4487fcf3ce44SJohn Forte 		return (1);
4488fcf3ce44SJohn Forte 	default :
4489fcf3ce44SJohn Forte 		return (0);
4490fcf3ce44SJohn Forte 	}
4491fcf3ce44SJohn Forte }
4492fcf3ce44SJohn Forte 
4493fcf3ce44SJohn Forte /*
4494fcf3ce44SJohn Forte  * handle any topology specific initializations here
4495fcf3ce44SJohn Forte  * this routine must be called while holding fcip_mutex
4496fcf3ce44SJohn Forte  */
4497fcf3ce44SJohn Forte /* ARGSUSED */
4498fcf3ce44SJohn Forte static void
4499fcf3ce44SJohn Forte fcip_handle_topology(struct fcip *fptr)
4500fcf3ce44SJohn Forte {
4501fcf3ce44SJohn Forte 
4502fcf3ce44SJohn Forte 	fcip_port_info_t	*fport = fptr->fcip_port_info;
4503fcf3ce44SJohn Forte 
4504fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&fptr->fcip_mutex));
4505fcf3ce44SJohn Forte 
4506fcf3ce44SJohn Forte 	/*
4507fcf3ce44SJohn Forte 	 * Since we know the port's topology - handle topology
4508fcf3ce44SJohn Forte 	 * specific details here. In Point to Point and Private Loop
4509fcf3ce44SJohn Forte 	 * topologies - we would probably not have a name server
4510fcf3ce44SJohn Forte 	 */
4511fcf3ce44SJohn Forte 
4512fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_3((fcip_handle_topology, "fcip io", /* CSTYLED */,
4513fcf3ce44SJohn Forte 		tnf_string, msg, "enter",
4514fcf3ce44SJohn Forte 		tnf_uint, port_state, fport->fcipp_pstate,
4515fcf3ce44SJohn Forte 		tnf_uint, topology, fport->fcipp_topology));
4516fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_INIT, (CE_NOTE, "port state: %x, topology %x",
4517fcf3ce44SJohn Forte 		fport->fcipp_pstate, fport->fcipp_topology));
4518fcf3ce44SJohn Forte 
4519fcf3ce44SJohn Forte 	fptr->fcip_broadcast_did = fcip_get_broadcast_did(fptr);
4520fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_mutex);
4521fcf3ce44SJohn Forte 	(void) fcip_dest_add_broadcast_entry(fptr, 0);
4522fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_mutex);
4523fcf3ce44SJohn Forte 
4524fcf3ce44SJohn Forte 	if (!fcip_is_supported_fc_topology(fport->fcipp_topology)) {
4525fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_INIT,
4526fcf3ce44SJohn Forte 		    (CE_WARN, "fcip(0x%x): Unsupported port topology (0x%x)",
4527fcf3ce44SJohn Forte 		    fptr->fcip_instance, fport->fcipp_topology));
4528fcf3ce44SJohn Forte 		return;
4529fcf3ce44SJohn Forte 	}
4530fcf3ce44SJohn Forte 
4531fcf3ce44SJohn Forte 	switch (fport->fcipp_topology) {
4532fcf3ce44SJohn Forte 	case FC_TOP_PRIVATE_LOOP: {
4533fcf3ce44SJohn Forte 
4534fcf3ce44SJohn Forte 		fc_portmap_t		*port_map;
4535fcf3ce44SJohn Forte 		uint32_t		listlen, alloclen;
4536fcf3ce44SJohn Forte 		/*
4537fcf3ce44SJohn Forte 		 * we may have to maintain routing. Get a list of
4538fcf3ce44SJohn Forte 		 * all devices on this port that the transport layer is
4539fcf3ce44SJohn Forte 		 * aware of. Check if any of them is a IS8802 type port,
4540fcf3ce44SJohn Forte 		 * if yes get its WWN and DID mapping and cache it in
4541fcf3ce44SJohn Forte 		 * the purport routing table. Since there is no
4542fcf3ce44SJohn Forte 		 * State Change notification for private loop/point_point
4543fcf3ce44SJohn Forte 		 * topologies - this table may not be accurate. The static
4544fcf3ce44SJohn Forte 		 * routing table is updated on a state change callback.
4545fcf3ce44SJohn Forte 		 */
4546fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_INIT, (CE_WARN, "port state valid!!"));
4547fcf3ce44SJohn Forte 		fptr->fcip_port_state = FCIP_PORT_ONLINE;
4548fcf3ce44SJohn Forte 		listlen = alloclen = FCIP_MAX_PORTS;
4549fcf3ce44SJohn Forte 		port_map = (fc_portmap_t *)
4550fcf3ce44SJohn Forte 		    kmem_zalloc((FCIP_MAX_PORTS * sizeof (fc_portmap_t)),
4551fcf3ce44SJohn Forte 		    KM_SLEEP);
4552fcf3ce44SJohn Forte 		if (fc_ulp_getportmap(fport->fcipp_handle, &port_map,
4553fcf3ce44SJohn Forte 		    &listlen, FC_ULP_PLOGI_PRESERVE) == FC_SUCCESS) {
4554fcf3ce44SJohn Forte 			mutex_exit(&fptr->fcip_mutex);
4555fcf3ce44SJohn Forte 			fcip_rt_update(fptr, port_map, listlen);
4556fcf3ce44SJohn Forte 			mutex_enter(&fptr->fcip_mutex);
4557fcf3ce44SJohn Forte 		}
4558fcf3ce44SJohn Forte 		if (listlen > alloclen) {
4559fcf3ce44SJohn Forte 			alloclen = listlen;
4560fcf3ce44SJohn Forte 		}
4561fcf3ce44SJohn Forte 		kmem_free(port_map, (alloclen * sizeof (fc_portmap_t)));
4562fcf3ce44SJohn Forte 		/*
4563fcf3ce44SJohn Forte 		 * Now fall through and register with the transport
4564fcf3ce44SJohn Forte 		 * that this port is IP capable
4565fcf3ce44SJohn Forte 		 */
4566fcf3ce44SJohn Forte 	}
4567fcf3ce44SJohn Forte 	/* FALLTHROUGH */
4568fcf3ce44SJohn Forte 	case FC_TOP_NO_NS:
4569fcf3ce44SJohn Forte 		/*
4570fcf3ce44SJohn Forte 		 * If we don't have a nameserver, lets wait until we
4571fcf3ce44SJohn Forte 		 * have to send out a packet to a remote port and then
4572fcf3ce44SJohn Forte 		 * try and discover the port using ARP/FARP.
4573fcf3ce44SJohn Forte 		 */
4574fcf3ce44SJohn Forte 	/* FALLTHROUGH */
4575fcf3ce44SJohn Forte 	case FC_TOP_PUBLIC_LOOP:
4576fcf3ce44SJohn Forte 	case FC_TOP_FABRIC: {
4577fcf3ce44SJohn Forte 		fc_portmap_t	*port_map;
4578fcf3ce44SJohn Forte 		uint32_t	listlen, alloclen;
4579fcf3ce44SJohn Forte 
4580fcf3ce44SJohn Forte 		/* FC_TYPE of 0x05 goes to word 0, LSB */
4581fcf3ce44SJohn Forte 		fptr->fcip_port_state = FCIP_PORT_ONLINE;
4582fcf3ce44SJohn Forte 
4583fcf3ce44SJohn Forte 		if (!(fptr->fcip_flags & FCIP_REG_INPROGRESS)) {
4584fcf3ce44SJohn Forte 			fptr->fcip_flags |= FCIP_REG_INPROGRESS;
4585fcf3ce44SJohn Forte 			if (taskq_dispatch(fptr->fcip_tq, fcip_port_ns,
4586*fc8ae2ecSToomas Soome 			    fptr, KM_NOSLEEP) == TASKQID_INVALID) {
4587fcf3ce44SJohn Forte 				fptr->fcip_flags &= ~FCIP_REG_INPROGRESS;
4588fcf3ce44SJohn Forte 			}
4589fcf3ce44SJohn Forte 		}
4590fcf3ce44SJohn Forte 
4591fcf3ce44SJohn Forte 		/*
4592fcf3ce44SJohn Forte 		 * If fcip_create_nodes_on_demand is overridden to force
4593fcf3ce44SJohn Forte 		 * discovery of all nodes in Fabric/Public loop topologies
4594fcf3ce44SJohn Forte 		 * we need to query for and obtain all nodes and log into
4595fcf3ce44SJohn Forte 		 * them as with private loop devices
4596fcf3ce44SJohn Forte 		 */
4597fcf3ce44SJohn Forte 		if (!fcip_create_nodes_on_demand) {
4598fcf3ce44SJohn Forte 			fptr->fcip_port_state = FCIP_PORT_ONLINE;
4599fcf3ce44SJohn Forte 			listlen = alloclen = FCIP_MAX_PORTS;
4600fcf3ce44SJohn Forte 			port_map = (fc_portmap_t *)
4601fcf3ce44SJohn Forte 			    kmem_zalloc((FCIP_MAX_PORTS *
4602fcf3ce44SJohn Forte 			    sizeof (fc_portmap_t)), KM_SLEEP);
4603fcf3ce44SJohn Forte 			if (fc_ulp_getportmap(fport->fcipp_handle, &port_map,
4604fcf3ce44SJohn Forte 			    &listlen, FC_ULP_PLOGI_PRESERVE) == FC_SUCCESS) {
4605fcf3ce44SJohn Forte 				mutex_exit(&fptr->fcip_mutex);
4606fcf3ce44SJohn Forte 				fcip_rt_update(fptr, port_map, listlen);
4607fcf3ce44SJohn Forte 				mutex_enter(&fptr->fcip_mutex);
4608fcf3ce44SJohn Forte 			}
4609fcf3ce44SJohn Forte 			if (listlen > alloclen) {
4610fcf3ce44SJohn Forte 				alloclen = listlen;
4611fcf3ce44SJohn Forte 			}
4612fcf3ce44SJohn Forte 			kmem_free(port_map,
4613fcf3ce44SJohn Forte 			    (alloclen * sizeof (fc_portmap_t)));
4614fcf3ce44SJohn Forte 		}
4615fcf3ce44SJohn Forte 		break;
4616fcf3ce44SJohn Forte 	}
4617fcf3ce44SJohn Forte 
4618fcf3ce44SJohn Forte 	default:
4619fcf3ce44SJohn Forte 		break;
4620fcf3ce44SJohn Forte 	}
4621fcf3ce44SJohn Forte }
4622fcf3ce44SJohn Forte 
4623fcf3ce44SJohn Forte static void
4624fcf3ce44SJohn Forte fcip_port_ns(void *arg)
4625fcf3ce44SJohn Forte {
4626fcf3ce44SJohn Forte 	struct	fcip		*fptr = (struct fcip *)arg;
4627fcf3ce44SJohn Forte 	fcip_port_info_t	*fport = fptr->fcip_port_info;
4628fcf3ce44SJohn Forte 	fc_ns_cmd_t		ns_cmd;
4629fcf3ce44SJohn Forte 	uint32_t		types[8];
4630fcf3ce44SJohn Forte 	ns_rfc_type_t		rfc;
4631fcf3ce44SJohn Forte 
4632fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_mutex);
4633fcf3ce44SJohn Forte 	if ((fptr->fcip_flags & (FCIP_DETACHING | FCIP_DETACHED)) ||
4634fcf3ce44SJohn Forte 	    (fptr->fcip_flags & (FCIP_SUSPENDED | FCIP_POWER_DOWN))) {
4635fcf3ce44SJohn Forte 		fptr->fcip_flags &= ~FCIP_REG_INPROGRESS;
4636fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_mutex);
4637fcf3ce44SJohn Forte 		return;
4638fcf3ce44SJohn Forte 	}
4639fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_mutex);
4640fcf3ce44SJohn Forte 
4641fcf3ce44SJohn Forte 	/*
4642fcf3ce44SJohn Forte 	 * Prepare the Name server structure to
4643fcf3ce44SJohn Forte 	 * register with the transport in case of
4644fcf3ce44SJohn Forte 	 * Fabric configuration.
4645fcf3ce44SJohn Forte 	 */
4646fcf3ce44SJohn Forte 	bzero(&rfc, sizeof (rfc));
4647fcf3ce44SJohn Forte 	bzero(types, sizeof (types));
4648fcf3ce44SJohn Forte 
4649fcf3ce44SJohn Forte 	types[FC4_TYPE_WORD_POS(FC_TYPE_IS8802_SNAP)] = (1 <<
4650fcf3ce44SJohn Forte 	    FC4_TYPE_BIT_POS(FC_TYPE_IS8802_SNAP));
4651fcf3ce44SJohn Forte 
4652fcf3ce44SJohn Forte 	rfc.rfc_port_id.port_id = fport->fcipp_sid.port_id;
4653fcf3ce44SJohn Forte 	bcopy(types, rfc.rfc_types, sizeof (types));
4654fcf3ce44SJohn Forte 
4655fcf3ce44SJohn Forte 	ns_cmd.ns_flags = 0;
4656fcf3ce44SJohn Forte 	ns_cmd.ns_cmd = NS_RFT_ID;
4657fcf3ce44SJohn Forte 	ns_cmd.ns_req_len = sizeof (rfc);
4658fcf3ce44SJohn Forte 	ns_cmd.ns_req_payload = (caddr_t)&rfc;
4659fcf3ce44SJohn Forte 	ns_cmd.ns_resp_len = 0;
4660fcf3ce44SJohn Forte 	ns_cmd.ns_resp_payload = NULL;
4661fcf3ce44SJohn Forte 
4662fcf3ce44SJohn Forte 	/*
4663fcf3ce44SJohn Forte 	 * Perform the Name Server Registration for FC IS8802_SNAP Type.
4664fcf3ce44SJohn Forte 	 * We don't expect a reply for registering port type
4665fcf3ce44SJohn Forte 	 */
4666fcf3ce44SJohn Forte 	(void) fc_ulp_port_ns(fptr->fcip_port_info->fcipp_handle,
4667fcf3ce44SJohn Forte 		(opaque_t)0, &ns_cmd);
4668fcf3ce44SJohn Forte 
4669fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_mutex);
4670fcf3ce44SJohn Forte 	fptr->fcip_flags &= ~FCIP_REG_INPROGRESS;
4671fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_mutex);
4672fcf3ce44SJohn Forte }
4673fcf3ce44SJohn Forte 
4674fcf3ce44SJohn Forte /*
4675fcf3ce44SJohn Forte  * setup this instance of fcip. This routine inits kstats, allocates
4676fcf3ce44SJohn Forte  * unsolicited buffers, determines' this port's siblings and handles
4677fcf3ce44SJohn Forte  * topology specific details which includes registering with the name
4678fcf3ce44SJohn Forte  * server and also setting up the routing table for this port for
4679fcf3ce44SJohn Forte  * private loops and point to point topologies
4680fcf3ce44SJohn Forte  */
4681fcf3ce44SJohn Forte static int
4682fcf3ce44SJohn Forte fcip_init_port(struct fcip *fptr)
4683fcf3ce44SJohn Forte {
4684fcf3ce44SJohn Forte 	int rval = FC_SUCCESS;
4685fcf3ce44SJohn Forte 	fcip_port_info_t	*fport = fptr->fcip_port_info;
4686fcf3ce44SJohn Forte 	static char buf[64];
4687af9e810cSToomas Soome 	size_t	tok_buf_size = 0;
4688fcf3ce44SJohn Forte 
4689fcf3ce44SJohn Forte 	ASSERT(fport != NULL);
4690fcf3ce44SJohn Forte 
4691fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_1((fcip_init_port, "fcip io", /* CSTYLED */,
4692fcf3ce44SJohn Forte 		tnf_string, msg, "enter"));
4693fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_mutex);
4694fcf3ce44SJohn Forte 
4695fcf3ce44SJohn Forte 	/*
4696fcf3ce44SJohn Forte 	 * setup mac address for this port. Don't be too worried if
4697fcf3ce44SJohn Forte 	 * the WWN is zero, there is probably nothing attached to
4698fcf3ce44SJohn Forte 	 * to the port. There is no point allocating unsolicited buffers
4699fcf3ce44SJohn Forte 	 * for an unused port so return success if we don't have a MAC
4700fcf3ce44SJohn Forte 	 * address. Do the port init on a state change notification.
4701fcf3ce44SJohn Forte 	 */
4702fcf3ce44SJohn Forte 	if (fcip_setup_mac_addr(fptr) == FCIP_INVALID_WWN) {
4703fcf3ce44SJohn Forte 		fptr->fcip_port_state = FCIP_PORT_OFFLINE;
4704fcf3ce44SJohn Forte 		rval = FC_SUCCESS;
4705fcf3ce44SJohn Forte 		goto done;
4706fcf3ce44SJohn Forte 	}
4707fcf3ce44SJohn Forte 
4708fcf3ce44SJohn Forte 	/*
4709fcf3ce44SJohn Forte 	 * clear routing table hash list for this port
4710fcf3ce44SJohn Forte 	 */
4711fcf3ce44SJohn Forte 	fcip_rt_flush(fptr);
4712fcf3ce44SJohn Forte 
4713fcf3ce44SJohn Forte 	/*
4714fcf3ce44SJohn Forte 	 * init kstats for this instance
4715fcf3ce44SJohn Forte 	 */
4716fcf3ce44SJohn Forte 	fcip_kstat_init(fptr);
4717fcf3ce44SJohn Forte 
4718fcf3ce44SJohn Forte 	/*
4719fcf3ce44SJohn Forte 	 * Allocate unsolicited buffers
4720fcf3ce44SJohn Forte 	 */
4721fcf3ce44SJohn Forte 	fptr->fcip_ub_nbufs = fcip_ub_nbufs;
4722fcf3ce44SJohn Forte 	tok_buf_size = sizeof (*fptr->fcip_ub_tokens) * fcip_ub_nbufs;
4723fcf3ce44SJohn Forte 
4724fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_2((fcip_init_port, "fcip io", /* CSTYLED */,
4725fcf3ce44SJohn Forte 		tnf_string, msg, "debug",
4726fcf3ce44SJohn Forte 		tnf_int, tokBufsize, tok_buf_size));
4727fcf3ce44SJohn Forte 
4728fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_INIT,
4729fcf3ce44SJohn Forte 	    (CE_WARN, "tokBufsize: 0x%lx", tok_buf_size));
4730fcf3ce44SJohn Forte 
4731fcf3ce44SJohn Forte 	fptr->fcip_ub_tokens = kmem_zalloc(tok_buf_size, KM_SLEEP);
4732fcf3ce44SJohn Forte 
4733fcf3ce44SJohn Forte 	if (fptr->fcip_ub_tokens == NULL) {
4734fcf3ce44SJohn Forte 		rval = FC_FAILURE;
4735fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_INIT,
4736fcf3ce44SJohn Forte 		    (CE_WARN, "fcip(%d): failed to allocate unsol buf",
4737fcf3ce44SJohn Forte 		    fptr->fcip_instance));
4738fcf3ce44SJohn Forte 		goto done;
4739fcf3ce44SJohn Forte 	}
4740fcf3ce44SJohn Forte 	rval = fc_ulp_uballoc(fport->fcipp_handle, &fptr->fcip_ub_nbufs,
4741fcf3ce44SJohn Forte 		fcip_ub_size, FC_TYPE_IS8802_SNAP, fptr->fcip_ub_tokens);
4742fcf3ce44SJohn Forte 
4743fcf3ce44SJohn Forte 	if (rval != FC_SUCCESS) {
4744fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_INIT,
4745fcf3ce44SJohn Forte 		    (CE_WARN, "fcip(%d): fc_ulp_uballoc failed with 0x%x!!",
4746fcf3ce44SJohn Forte 		    fptr->fcip_instance, rval));
4747fcf3ce44SJohn Forte 	}
4748fcf3ce44SJohn Forte 
4749fcf3ce44SJohn Forte 	switch (rval) {
4750fcf3ce44SJohn Forte 	case FC_SUCCESS:
4751fcf3ce44SJohn Forte 		break;
4752fcf3ce44SJohn Forte 
4753fcf3ce44SJohn Forte 	case FC_OFFLINE:
4754fcf3ce44SJohn Forte 		fptr->fcip_port_state = FCIP_PORT_OFFLINE;
4755fcf3ce44SJohn Forte 		rval = FC_FAILURE;
4756fcf3ce44SJohn Forte 		goto done;
4757fcf3ce44SJohn Forte 
4758fcf3ce44SJohn Forte 	case FC_UB_ERROR:
4759fcf3ce44SJohn Forte 		FCIP_TNF_PROBE_1((fcip_init_port, "fcip io", /* CSTYLED */,
4760fcf3ce44SJohn Forte 			tnf_string, msg, "invalid ub alloc request"));
4761fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_INIT,
4762fcf3ce44SJohn Forte 		    (CE_WARN, "invalid ub alloc request !!"));
4763fcf3ce44SJohn Forte 		rval = FC_FAILURE;
4764fcf3ce44SJohn Forte 		goto done;
4765fcf3ce44SJohn Forte 
4766fcf3ce44SJohn Forte 	case FC_FAILURE:
4767fcf3ce44SJohn Forte 		/*
4768fcf3ce44SJohn Forte 		 * requested bytes could not be alloced
4769fcf3ce44SJohn Forte 		 */
4770fcf3ce44SJohn Forte 		if (fptr->fcip_ub_nbufs != fcip_ub_nbufs) {
4771fcf3ce44SJohn Forte 			cmn_err(CE_WARN,
4772fcf3ce44SJohn Forte 			    "!fcip(0x%x): Failed to alloc unsolicited bufs",
4773fcf3ce44SJohn Forte 			    ddi_get_instance(fport->fcipp_dip));
4774fcf3ce44SJohn Forte 			rval = FC_FAILURE;
4775fcf3ce44SJohn Forte 			goto done;
4776fcf3ce44SJohn Forte 		}
4777fcf3ce44SJohn Forte 		break;
4778fcf3ce44SJohn Forte 
4779fcf3ce44SJohn Forte 	default:
4780fcf3ce44SJohn Forte 		rval = FC_FAILURE;
4781fcf3ce44SJohn Forte 		break;
4782fcf3ce44SJohn Forte 	}
4783fcf3ce44SJohn Forte 
4784fcf3ce44SJohn Forte 	/*
4785fcf3ce44SJohn Forte 	 * Preallocate a Cache of fcip packets for transmit and receive
4786fcf3ce44SJohn Forte 	 * We don't want to be holding on to unsolicited buffers while
4787fcf3ce44SJohn Forte 	 * we transmit the message upstream
4788fcf3ce44SJohn Forte 	 */
4789fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_INIT, (CE_NOTE, "allocating fcip_pkt cache"));
4790fcf3ce44SJohn Forte 
4791fcf3ce44SJohn Forte 	(void) sprintf(buf, "fcip%d_cache", fptr->fcip_instance);
4792fcf3ce44SJohn Forte 	fptr->fcip_xmit_cache = kmem_cache_create(buf,
4793fcf3ce44SJohn Forte 		(fport->fcipp_fca_pkt_size + sizeof (fcip_pkt_t)),
4794fcf3ce44SJohn Forte 		8, fcip_cache_constructor, fcip_cache_destructor,
4795fcf3ce44SJohn Forte 		NULL, (void *)fport, NULL, 0);
4796fcf3ce44SJohn Forte 
4797fcf3ce44SJohn Forte 	(void) sprintf(buf, "fcip%d_sendup_cache", fptr->fcip_instance);
4798fcf3ce44SJohn Forte 	fptr->fcip_sendup_cache = kmem_cache_create(buf,
4799fcf3ce44SJohn Forte 		sizeof (struct fcip_sendup_elem),
4800fcf3ce44SJohn Forte 		8, fcip_sendup_constructor, NULL, NULL, (void *)fport, NULL, 0);
4801fcf3ce44SJohn Forte 
4802fcf3ce44SJohn Forte 	if (fptr->fcip_xmit_cache == NULL) {
4803fcf3ce44SJohn Forte 		FCIP_TNF_PROBE_2((fcip_init_port, "fcip io", /* CSTYLED */,
4804fcf3ce44SJohn Forte 			tnf_string, msg, "unable to allocate xmit cache",
4805fcf3ce44SJohn Forte 			tnf_int, instance, fptr->fcip_instance));
4806fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_INIT,
4807fcf3ce44SJohn Forte 		    (CE_WARN, "fcip%d unable to allocate xmit cache",
4808fcf3ce44SJohn Forte 		    fptr->fcip_instance));
4809fcf3ce44SJohn Forte 		rval = FC_FAILURE;
4810fcf3ce44SJohn Forte 		goto done;
4811fcf3ce44SJohn Forte 	}
4812fcf3ce44SJohn Forte 
4813fcf3ce44SJohn Forte 	/*
4814fcf3ce44SJohn Forte 	 * We may need to handle routing tables for point to point and
4815fcf3ce44SJohn Forte 	 * fcal topologies and register with NameServer for Fabric
4816fcf3ce44SJohn Forte 	 * topologies.
4817fcf3ce44SJohn Forte 	 */
4818fcf3ce44SJohn Forte 	fcip_handle_topology(fptr);
4819fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_mutex);
4820fcf3ce44SJohn Forte 	if (fcip_dest_add_broadcast_entry(fptr, 1) != FC_SUCCESS) {
4821fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_INIT,
4822fcf3ce44SJohn Forte 		    (CE_WARN, "fcip(0x%x):add broadcast entry failed!!",
4823fcf3ce44SJohn Forte 		    fptr->fcip_instance));
4824fcf3ce44SJohn Forte 		mutex_enter(&fptr->fcip_mutex);
4825fcf3ce44SJohn Forte 		rval = FC_FAILURE;
4826fcf3ce44SJohn Forte 		goto done;
4827fcf3ce44SJohn Forte 	}
4828fcf3ce44SJohn Forte 
4829fcf3ce44SJohn Forte 	rval = FC_SUCCESS;
4830fcf3ce44SJohn Forte 	return (rval);
4831fcf3ce44SJohn Forte 
4832fcf3ce44SJohn Forte done:
4833fcf3ce44SJohn Forte 	/*
4834fcf3ce44SJohn Forte 	 * we don't always come here from port_attach - so cleanup
4835fcf3ce44SJohn Forte 	 * anything done in the init_port routine
4836fcf3ce44SJohn Forte 	 */
4837fcf3ce44SJohn Forte 	if (fptr->fcip_kstatp) {
4838fcf3ce44SJohn Forte 		kstat_delete(fptr->fcip_kstatp);
4839fcf3ce44SJohn Forte 		fptr->fcip_kstatp = NULL;
4840fcf3ce44SJohn Forte 	}
4841fcf3ce44SJohn Forte 
4842fcf3ce44SJohn Forte 	if (fptr->fcip_xmit_cache) {
4843fcf3ce44SJohn Forte 		kmem_cache_destroy(fptr->fcip_xmit_cache);
4844fcf3ce44SJohn Forte 		fptr->fcip_xmit_cache = NULL;
4845fcf3ce44SJohn Forte 	}
4846fcf3ce44SJohn Forte 
4847fcf3ce44SJohn Forte 	if (fptr->fcip_sendup_cache) {
4848fcf3ce44SJohn Forte 		kmem_cache_destroy(fptr->fcip_sendup_cache);
4849fcf3ce44SJohn Forte 		fptr->fcip_sendup_cache = NULL;
4850fcf3ce44SJohn Forte 	}
4851fcf3ce44SJohn Forte 
4852fcf3ce44SJohn Forte 	/* release unsolicited buffers */
4853fcf3ce44SJohn Forte 	if (fptr->fcip_ub_tokens) {
4854fcf3ce44SJohn Forte 		uint64_t	*tokens = fptr->fcip_ub_tokens;
4855fcf3ce44SJohn Forte 		fptr->fcip_ub_tokens = NULL;
4856fcf3ce44SJohn Forte 
4857fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_mutex);
4858fcf3ce44SJohn Forte 		(void) fc_ulp_ubfree(fport->fcipp_handle, fptr->fcip_ub_nbufs,
4859fcf3ce44SJohn Forte 			tokens);
4860fcf3ce44SJohn Forte 		kmem_free(tokens, tok_buf_size);
4861fcf3ce44SJohn Forte 
4862fcf3ce44SJohn Forte 	} else {
4863fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_mutex);
4864fcf3ce44SJohn Forte 	}
4865fcf3ce44SJohn Forte 
4866fcf3ce44SJohn Forte 	return (rval);
4867fcf3ce44SJohn Forte }
4868fcf3ce44SJohn Forte 
4869fcf3ce44SJohn Forte /*
4870fcf3ce44SJohn Forte  * Sets up a port's MAC address from its WWN
4871fcf3ce44SJohn Forte  */
4872fcf3ce44SJohn Forte static int
4873fcf3ce44SJohn Forte fcip_setup_mac_addr(struct fcip *fptr)
4874fcf3ce44SJohn Forte {
4875fcf3ce44SJohn Forte 	fcip_port_info_t	*fport = fptr->fcip_port_info;
4876fcf3ce44SJohn Forte 
4877fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&fptr->fcip_mutex));
4878fcf3ce44SJohn Forte 
4879fcf3ce44SJohn Forte 	fptr->fcip_addrflags = 0;
4880fcf3ce44SJohn Forte 
4881fcf3ce44SJohn Forte 	/*
4882fcf3ce44SJohn Forte 	 * we cannot choose a MAC address for our interface - we have
4883fcf3ce44SJohn Forte 	 * to live with whatever node WWN we get (minus the top two
4884fcf3ce44SJohn Forte 	 * MSbytes for the MAC address) from the transport layer. We will
4885fcf3ce44SJohn Forte 	 * treat the WWN as our factory MAC address.
4886fcf3ce44SJohn Forte 	 */
4887fcf3ce44SJohn Forte 
4888fcf3ce44SJohn Forte 	if ((fport->fcipp_nwwn.w.wwn_hi != 0) ||
4889fcf3ce44SJohn Forte 	    (fport->fcipp_nwwn.w.wwn_lo != 0)) {
4890fcf3ce44SJohn Forte 		char		etherstr[ETHERSTRL];
4891fcf3ce44SJohn Forte 
4892fcf3ce44SJohn Forte 		wwn_to_ether(&fport->fcipp_nwwn, &fptr->fcip_macaddr);
4893fcf3ce44SJohn Forte 		fcip_ether_to_str(&fptr->fcip_macaddr, etherstr);
4894fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_INIT,
4895fcf3ce44SJohn Forte 		    (CE_NOTE, "setupmacaddr ouraddr %s", etherstr));
4896fcf3ce44SJohn Forte 
4897fcf3ce44SJohn Forte 		fptr->fcip_addrflags = (FCIP_FACTADDR_PRESENT |
4898fcf3ce44SJohn Forte 						FCIP_FACTADDR_USE);
4899fcf3ce44SJohn Forte 	} else {
4900fcf3ce44SJohn Forte 		/*
4901fcf3ce44SJohn Forte 		 * No WWN - just return failure - there's not much
4902fcf3ce44SJohn Forte 		 * we can do since we cannot set the WWN.
4903fcf3ce44SJohn Forte 		 */
4904fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_INIT,
4905fcf3ce44SJohn Forte 		    (CE_WARN, "Port does not have a valid WWN"));
4906fcf3ce44SJohn Forte 		return (FCIP_INVALID_WWN);
4907fcf3ce44SJohn Forte 	}
4908fcf3ce44SJohn Forte 	return (FC_SUCCESS);
4909fcf3ce44SJohn Forte }
4910fcf3ce44SJohn Forte 
4911fcf3ce44SJohn Forte 
4912fcf3ce44SJohn Forte /*
4913fcf3ce44SJohn Forte  * flush routing table entries
4914fcf3ce44SJohn Forte  */
4915fcf3ce44SJohn Forte static void
4916fcf3ce44SJohn Forte fcip_rt_flush(struct fcip *fptr)
4917fcf3ce44SJohn Forte {
4918fcf3ce44SJohn Forte 	int index;
4919fcf3ce44SJohn Forte 
4920fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_rt_mutex);
4921fcf3ce44SJohn Forte 	for (index = 0; index < FCIP_RT_HASH_ELEMS; index++) {
4922fcf3ce44SJohn Forte 		struct fcip_routing_table 	*frtp, *frtp_next;
4923fcf3ce44SJohn Forte 		frtp = fptr->fcip_rtable[index];
4924fcf3ce44SJohn Forte 		while (frtp) {
4925fcf3ce44SJohn Forte 			frtp_next = frtp->fcipr_next;
4926fcf3ce44SJohn Forte 			kmem_free(frtp, sizeof (struct fcip_routing_table));
4927fcf3ce44SJohn Forte 			frtp = frtp_next;
4928fcf3ce44SJohn Forte 		}
4929fcf3ce44SJohn Forte 		fptr->fcip_rtable[index] = NULL;
4930fcf3ce44SJohn Forte 	}
4931fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_rt_mutex);
4932fcf3ce44SJohn Forte }
4933fcf3ce44SJohn Forte 
4934fcf3ce44SJohn Forte /*
4935fcf3ce44SJohn Forte  * Free up the fcip softstate and all allocated resources for the
4936fcf3ce44SJohn Forte  * fcip instance assoicated with a given port driver instance
4937fcf3ce44SJohn Forte  *
4938fcf3ce44SJohn Forte  * Given that the list of structures pointed to by fcip_port_head,
4939fcf3ce44SJohn Forte  * this function is called from multiple sources, and the
4940fcf3ce44SJohn Forte  * fcip_global_mutex that protects fcip_port_head must be dropped,
4941fcf3ce44SJohn Forte  * our best solution is to return a value that indicates the next
4942fcf3ce44SJohn Forte  * port in the list.  This way the caller doesn't need to worry
494348bbca81SDaniel Hoffman  * about the race condition where it saves off a pointer to the
4944fcf3ce44SJohn Forte  * next structure in the list and by the time this routine returns,
4945fcf3ce44SJohn Forte  * that next structure has already been freed.
4946fcf3ce44SJohn Forte  */
4947fcf3ce44SJohn Forte static fcip_port_info_t *
4948fcf3ce44SJohn Forte fcip_softstate_free(fcip_port_info_t *fport)
4949fcf3ce44SJohn Forte {
4950fcf3ce44SJohn Forte 	struct fcip		*fptr = NULL;
4951fcf3ce44SJohn Forte 	int 			instance;
4952fcf3ce44SJohn Forte 	timeout_id_t		tid;
4953fcf3ce44SJohn Forte 	opaque_t		phandle = NULL;
4954fcf3ce44SJohn Forte 	fcip_port_info_t	*prev_fport, *cur_fport, *next_fport = NULL;
4955fcf3ce44SJohn Forte 
4956fcf3ce44SJohn Forte 	ASSERT(MUTEX_HELD(&fcip_global_mutex));
4957fcf3ce44SJohn Forte 
4958fcf3ce44SJohn Forte 	if (fport) {
4959fcf3ce44SJohn Forte 		phandle = fport->fcipp_handle;
4960fcf3ce44SJohn Forte 		fptr = fport->fcipp_fcip;
4961fcf3ce44SJohn Forte 	} else {
4962fcf3ce44SJohn Forte 		return (next_fport);
4963fcf3ce44SJohn Forte 	}
4964fcf3ce44SJohn Forte 
4965fcf3ce44SJohn Forte 	if (fptr) {
4966fcf3ce44SJohn Forte 		mutex_enter(&fptr->fcip_mutex);
4967fcf3ce44SJohn Forte 		instance = ddi_get_instance(fptr->fcip_dip);
4968fcf3ce44SJohn Forte 
4969fcf3ce44SJohn Forte 		/*
4970fcf3ce44SJohn Forte 		 * dismantle timeout thread for this instance of fcip
4971fcf3ce44SJohn Forte 		 */
4972fcf3ce44SJohn Forte 		tid = fptr->fcip_timeout_id;
4973fcf3ce44SJohn Forte 		fptr->fcip_timeout_id = NULL;
4974fcf3ce44SJohn Forte 
4975fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_mutex);
4976fcf3ce44SJohn Forte 		(void) untimeout(tid);
4977fcf3ce44SJohn Forte 		mutex_enter(&fptr->fcip_mutex);
4978fcf3ce44SJohn Forte 
4979fcf3ce44SJohn Forte 		ASSERT(fcip_num_instances >= 0);
4980fcf3ce44SJohn Forte 		fcip_num_instances--;
4981fcf3ce44SJohn Forte 
4982fcf3ce44SJohn Forte 		/*
4983fcf3ce44SJohn Forte 		 * stop sendup thread
4984fcf3ce44SJohn Forte 		 */
4985fcf3ce44SJohn Forte 		mutex_enter(&fptr->fcip_sendup_mutex);
4986fcf3ce44SJohn Forte 		if (fptr->fcip_sendup_thr_initted) {
4987fcf3ce44SJohn Forte 			fptr->fcip_sendup_thr_initted = 0;
4988fcf3ce44SJohn Forte 			cv_signal(&fptr->fcip_sendup_cv);
4989fcf3ce44SJohn Forte 			cv_wait(&fptr->fcip_sendup_cv,
4990fcf3ce44SJohn Forte 			    &fptr->fcip_sendup_mutex);
4991fcf3ce44SJohn Forte 		}
4992fcf3ce44SJohn Forte 		ASSERT(fptr->fcip_sendup_head == NULL);
4993fcf3ce44SJohn Forte 		fptr->fcip_sendup_head = fptr->fcip_sendup_tail = NULL;
4994fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_sendup_mutex);
4995fcf3ce44SJohn Forte 
4996fcf3ce44SJohn Forte 		/*
4997fcf3ce44SJohn Forte 		 * dismantle taskq
4998fcf3ce44SJohn Forte 		 */
4999fcf3ce44SJohn Forte 		if (fptr->fcip_tq) {
5000fcf3ce44SJohn Forte 			taskq_t	*tq = fptr->fcip_tq;
5001fcf3ce44SJohn Forte 
5002fcf3ce44SJohn Forte 			fptr->fcip_tq = NULL;
5003fcf3ce44SJohn Forte 
5004fcf3ce44SJohn Forte 			mutex_exit(&fptr->fcip_mutex);
5005fcf3ce44SJohn Forte 			taskq_destroy(tq);
5006fcf3ce44SJohn Forte 			mutex_enter(&fptr->fcip_mutex);
5007fcf3ce44SJohn Forte 		}
5008fcf3ce44SJohn Forte 
5009fcf3ce44SJohn Forte 		if (fptr->fcip_kstatp) {
5010fcf3ce44SJohn Forte 			kstat_delete(fptr->fcip_kstatp);
5011fcf3ce44SJohn Forte 			fptr->fcip_kstatp = NULL;
5012fcf3ce44SJohn Forte 		}
5013fcf3ce44SJohn Forte 
5014fcf3ce44SJohn Forte 		/* flush the routing table entries */
5015fcf3ce44SJohn Forte 		fcip_rt_flush(fptr);
5016fcf3ce44SJohn Forte 
5017fcf3ce44SJohn Forte 		if (fptr->fcip_xmit_cache) {
5018fcf3ce44SJohn Forte 			kmem_cache_destroy(fptr->fcip_xmit_cache);
5019fcf3ce44SJohn Forte 			fptr->fcip_xmit_cache = NULL;
5020fcf3ce44SJohn Forte 		}
5021fcf3ce44SJohn Forte 
5022fcf3ce44SJohn Forte 		if (fptr->fcip_sendup_cache) {
5023fcf3ce44SJohn Forte 			kmem_cache_destroy(fptr->fcip_sendup_cache);
5024fcf3ce44SJohn Forte 			fptr->fcip_sendup_cache = NULL;
5025fcf3ce44SJohn Forte 		}
5026fcf3ce44SJohn Forte 
5027fcf3ce44SJohn Forte 		fcip_cleanup_dest(fptr);
5028fcf3ce44SJohn Forte 
5029fcf3ce44SJohn Forte 		/* release unsolicited buffers */
5030fcf3ce44SJohn Forte 		if (fptr->fcip_ub_tokens) {
5031fcf3ce44SJohn Forte 			uint64_t	*tokens = fptr->fcip_ub_tokens;
5032fcf3ce44SJohn Forte 
5033fcf3ce44SJohn Forte 			fptr->fcip_ub_tokens = NULL;
5034fcf3ce44SJohn Forte 			mutex_exit(&fptr->fcip_mutex);
5035fcf3ce44SJohn Forte 			if (phandle) {
5036fcf3ce44SJohn Forte 				/*
5037fcf3ce44SJohn Forte 				 * release the global mutex here to
5038fcf3ce44SJohn Forte 				 * permit any data pending callbacks to
5039fcf3ce44SJohn Forte 				 * complete. Else we will deadlock in the
5040fcf3ce44SJohn Forte 				 * FCA waiting for all unsol buffers to be
5041fcf3ce44SJohn Forte 				 * returned.
5042fcf3ce44SJohn Forte 				 */
5043fcf3ce44SJohn Forte 				mutex_exit(&fcip_global_mutex);
5044fcf3ce44SJohn Forte 				(void) fc_ulp_ubfree(phandle,
5045fcf3ce44SJohn Forte 				    fptr->fcip_ub_nbufs, tokens);
5046fcf3ce44SJohn Forte 				mutex_enter(&fcip_global_mutex);
5047fcf3ce44SJohn Forte 			}
5048fcf3ce44SJohn Forte 			kmem_free(tokens, (sizeof (*tokens) * fcip_ub_nbufs));
5049fcf3ce44SJohn Forte 		} else {
5050fcf3ce44SJohn Forte 			mutex_exit(&fptr->fcip_mutex);
5051fcf3ce44SJohn Forte 		}
5052fcf3ce44SJohn Forte 
5053fcf3ce44SJohn Forte 		mutex_destroy(&fptr->fcip_mutex);
5054fcf3ce44SJohn Forte 		mutex_destroy(&fptr->fcip_ub_mutex);
5055fcf3ce44SJohn Forte 		mutex_destroy(&fptr->fcip_rt_mutex);
5056fcf3ce44SJohn Forte 		mutex_destroy(&fptr->fcip_dest_mutex);
5057fcf3ce44SJohn Forte 		mutex_destroy(&fptr->fcip_sendup_mutex);
5058fcf3ce44SJohn Forte 		cv_destroy(&fptr->fcip_farp_cv);
5059fcf3ce44SJohn Forte 		cv_destroy(&fptr->fcip_sendup_cv);
5060fcf3ce44SJohn Forte 		cv_destroy(&fptr->fcip_ub_cv);
5061fcf3ce44SJohn Forte 
5062fcf3ce44SJohn Forte 		ddi_soft_state_free(fcip_softp, instance);
5063fcf3ce44SJohn Forte 	}
5064fcf3ce44SJohn Forte 
5065fcf3ce44SJohn Forte 	/*
5066fcf3ce44SJohn Forte 	 * Now dequeue the fcip_port_info from the port list
5067fcf3ce44SJohn Forte 	 */
5068fcf3ce44SJohn Forte 	cur_fport = fcip_port_head;
5069fcf3ce44SJohn Forte 	prev_fport = NULL;
5070fcf3ce44SJohn Forte 	while (cur_fport != NULL) {
5071fcf3ce44SJohn Forte 		if (cur_fport == fport) {
5072fcf3ce44SJohn Forte 			break;
5073fcf3ce44SJohn Forte 		}
5074fcf3ce44SJohn Forte 		prev_fport = cur_fport;
5075fcf3ce44SJohn Forte 		cur_fport = cur_fport->fcipp_next;
5076fcf3ce44SJohn Forte 	}
5077fcf3ce44SJohn Forte 
5078fcf3ce44SJohn Forte 	/*
5079fcf3ce44SJohn Forte 	 * Assert that we found a port in our port list
5080fcf3ce44SJohn Forte 	 */
5081fcf3ce44SJohn Forte 	ASSERT(cur_fport == fport);
5082fcf3ce44SJohn Forte 
5083fcf3ce44SJohn Forte 	if (prev_fport) {
5084fcf3ce44SJohn Forte 		/*
5085fcf3ce44SJohn Forte 		 * Not the first port in the port list
5086fcf3ce44SJohn Forte 		 */
5087fcf3ce44SJohn Forte 		prev_fport->fcipp_next = fport->fcipp_next;
5088fcf3ce44SJohn Forte 	} else {
5089fcf3ce44SJohn Forte 		/*
5090fcf3ce44SJohn Forte 		 * first port
5091fcf3ce44SJohn Forte 		 */
5092fcf3ce44SJohn Forte 		fcip_port_head = fport->fcipp_next;
5093fcf3ce44SJohn Forte 	}
5094fcf3ce44SJohn Forte 	next_fport = fport->fcipp_next;
5095fcf3ce44SJohn Forte 	kmem_free(fport, sizeof (fcip_port_info_t));
5096fcf3ce44SJohn Forte 
5097fcf3ce44SJohn Forte 	return (next_fport);
5098fcf3ce44SJohn Forte }
5099fcf3ce44SJohn Forte 
5100fcf3ce44SJohn Forte 
5101fcf3ce44SJohn Forte /*
5102fcf3ce44SJohn Forte  * This is called by transport for any ioctl operations performed
5103fcf3ce44SJohn Forte  * on the devctl or other transport minor nodes. It is currently
5104fcf3ce44SJohn Forte  * unused for fcip
5105fcf3ce44SJohn Forte  */
5106fcf3ce44SJohn Forte /* ARGSUSED */
5107fcf3ce44SJohn Forte static int
5108fcf3ce44SJohn Forte fcip_port_ioctl(opaque_t ulp_handle,  opaque_t port_handle, dev_t dev,
5109fcf3ce44SJohn Forte 	int cmd, intptr_t data, int mode, cred_t *credp, int *rval,
5110fcf3ce44SJohn Forte 	uint32_t claimed)
5111fcf3ce44SJohn Forte {
5112fcf3ce44SJohn Forte 	return (FC_UNCLAIMED);
5113fcf3ce44SJohn Forte }
5114fcf3ce44SJohn Forte 
5115fcf3ce44SJohn Forte /*
5116fcf3ce44SJohn Forte  * DL_INFO_REQ - returns information about the DLPI stream to the DLS user
5117fcf3ce44SJohn Forte  * requesting information about this interface
5118fcf3ce44SJohn Forte  */
5119fcf3ce44SJohn Forte static void
5120fcf3ce44SJohn Forte fcip_ireq(queue_t *wq, mblk_t *mp)
5121fcf3ce44SJohn Forte {
5122fcf3ce44SJohn Forte 	struct fcipstr		*slp;
5123fcf3ce44SJohn Forte 	struct fcip		*fptr;
5124fcf3ce44SJohn Forte 	dl_info_ack_t		*dlip;
5125fcf3ce44SJohn Forte 	struct fcipdladdr	*dlap;
5126fcf3ce44SJohn Forte 	la_wwn_t		*ep;
5127fcf3ce44SJohn Forte 	int 			size;
5128fcf3ce44SJohn Forte 	char			etherstr[ETHERSTRL];
5129fcf3ce44SJohn Forte 
5130fcf3ce44SJohn Forte 	slp = (struct fcipstr *)wq->q_ptr;
5131fcf3ce44SJohn Forte 
5132fcf3ce44SJohn Forte 	fptr = slp->sl_fcip;
5133fcf3ce44SJohn Forte 
5134fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_DLPI,
5135fcf3ce44SJohn Forte 	    (CE_NOTE, "fcip_ireq: info request req rcvd"));
5136fcf3ce44SJohn Forte 
5137fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_1((fcip_ireq, "fcip io", /* CSTYLED */,
5138fcf3ce44SJohn Forte 	    tnf_string, msg, "fcip ireq entered"));
5139fcf3ce44SJohn Forte 
5140fcf3ce44SJohn Forte 	if (MBLKL(mp) < DL_INFO_REQ_SIZE) {
5141fcf3ce44SJohn Forte 		dlerrorack(wq, mp, DL_INFO_REQ, DL_BADPRIM, 0);
5142fcf3ce44SJohn Forte 		return;
5143fcf3ce44SJohn Forte 	}
5144fcf3ce44SJohn Forte 
5145fcf3ce44SJohn Forte 	/*
5146fcf3ce44SJohn Forte 	 * Exchange current message for a DL_INFO_ACK
5147fcf3ce44SJohn Forte 	 */
5148fcf3ce44SJohn Forte 	size = sizeof (dl_info_ack_t) + FCIPADDRL + ETHERADDRL;
5149fcf3ce44SJohn Forte 	if ((mp = mexchange(wq, mp, size, M_PCPROTO, DL_INFO_ACK)) == NULL) {
5150fcf3ce44SJohn Forte 		return;
5151fcf3ce44SJohn Forte 	}
5152fcf3ce44SJohn Forte 
5153fcf3ce44SJohn Forte 	/*
5154fcf3ce44SJohn Forte 	 * FILL in the DL_INFO_ACK fields and reply
5155fcf3ce44SJohn Forte 	 */
5156fcf3ce44SJohn Forte 	dlip = (dl_info_ack_t *)mp->b_rptr;
5157fcf3ce44SJohn Forte 	*dlip = fcip_infoack;
5158fcf3ce44SJohn Forte 	dlip->dl_current_state = slp->sl_state;
5159fcf3ce44SJohn Forte 	dlap = (struct fcipdladdr *)(mp->b_rptr + dlip->dl_addr_offset);
5160fcf3ce44SJohn Forte 	dlap->dl_sap = slp->sl_sap;
5161fcf3ce44SJohn Forte 
5162fcf3ce44SJohn Forte 
5163fcf3ce44SJohn Forte 	if (fptr) {
5164fcf3ce44SJohn Forte 		fcip_ether_to_str(&fptr->fcip_macaddr, etherstr);
5165fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DLPI,
5166fcf3ce44SJohn Forte 		    (CE_NOTE, "ireq - our mac: %s", etherstr));
5167fcf3ce44SJohn Forte 		ether_bcopy(&fptr->fcip_macaddr, &dlap->dl_phys);
5168fcf3ce44SJohn Forte 	} else {
5169fcf3ce44SJohn Forte 		bzero((caddr_t)&dlap->dl_phys, ETHERADDRL);
5170fcf3ce44SJohn Forte 	}
5171fcf3ce44SJohn Forte 
5172fcf3ce44SJohn Forte 	ep = (la_wwn_t *)(mp->b_rptr + dlip->dl_brdcst_addr_offset);
5173fcf3ce44SJohn Forte 	ether_bcopy(&fcip_arpbroadcast_addr, ep);
5174fcf3ce44SJohn Forte 
5175fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_NOTE, "sending back info req.."));
5176fcf3ce44SJohn Forte 	qreply(wq, mp);
5177fcf3ce44SJohn Forte }
5178fcf3ce44SJohn Forte 
5179fcf3ce44SJohn Forte 
5180fcf3ce44SJohn Forte /*
5181fcf3ce44SJohn Forte  * To handle DL_UNITDATA_REQ requests.
5182fcf3ce44SJohn Forte  */
5183fcf3ce44SJohn Forte 
5184fcf3ce44SJohn Forte static void
5185fcf3ce44SJohn Forte fcip_udreq(queue_t *wq, mblk_t *mp)
5186fcf3ce44SJohn Forte {
5187fcf3ce44SJohn Forte 	struct fcipstr		*slp;
5188fcf3ce44SJohn Forte 	struct fcip		*fptr;
5189fcf3ce44SJohn Forte 	fcip_port_info_t	*fport;
5190fcf3ce44SJohn Forte 	dl_unitdata_req_t	*dludp;
5191fcf3ce44SJohn Forte 	mblk_t			*nmp;
5192fcf3ce44SJohn Forte 	struct fcipdladdr	*dlap;
5193fcf3ce44SJohn Forte 	fcph_network_hdr_t 	*headerp;
5194fcf3ce44SJohn Forte 	llc_snap_hdr_t		*lsnap;
5195fcf3ce44SJohn Forte 	t_uscalar_t		off, len;
5196fcf3ce44SJohn Forte 	struct fcip_dest	*fdestp;
5197fcf3ce44SJohn Forte 	la_wwn_t		wwn;
5198fcf3ce44SJohn Forte 	int			hdr_size;
5199fcf3ce44SJohn Forte 
5200fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_NOTE, "inside fcip_udreq"));
5201fcf3ce44SJohn Forte 
5202fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_1((fcip_udreq, "fcip io", /* CSTYLED */,
5203fcf3ce44SJohn Forte 	    tnf_string, msg, "fcip udreq entered"));
5204fcf3ce44SJohn Forte 
5205fcf3ce44SJohn Forte 	slp = (struct fcipstr *)wq->q_ptr;
5206fcf3ce44SJohn Forte 
5207fcf3ce44SJohn Forte 	if (slp->sl_state != DL_IDLE) {
5208fcf3ce44SJohn Forte 		dlerrorack(wq, mp, DL_UNITDATA_REQ, DL_OUTSTATE, 0);
5209fcf3ce44SJohn Forte 		return;
5210fcf3ce44SJohn Forte 	}
5211fcf3ce44SJohn Forte 
5212fcf3ce44SJohn Forte 	fptr = slp->sl_fcip;
5213fcf3ce44SJohn Forte 
5214fcf3ce44SJohn Forte 	if (fptr == NULL) {
5215fcf3ce44SJohn Forte 		dlerrorack(wq, mp, DL_UNITDATA_REQ, DL_OUTSTATE, 0);
5216fcf3ce44SJohn Forte 		return;
5217fcf3ce44SJohn Forte 	}
5218fcf3ce44SJohn Forte 
5219fcf3ce44SJohn Forte 	fport = fptr->fcip_port_info;
5220fcf3ce44SJohn Forte 
5221fcf3ce44SJohn Forte 	dludp = (dl_unitdata_req_t *)mp->b_rptr;
5222fcf3ce44SJohn Forte 	off = dludp->dl_dest_addr_offset;
5223fcf3ce44SJohn Forte 	len = dludp->dl_dest_addr_length;
5224fcf3ce44SJohn Forte 
5225fcf3ce44SJohn Forte 	/*
5226fcf3ce44SJohn Forte 	 * Validate destination address format
5227fcf3ce44SJohn Forte 	 */
5228fcf3ce44SJohn Forte 	if (!MBLKIN(mp, off, len) || (len != FCIPADDRL)) {
5229fcf3ce44SJohn Forte 		dluderrorind(wq, mp, (mp->b_rptr + off), len, DL_BADADDR, 0);
5230fcf3ce44SJohn Forte 		return;
5231fcf3ce44SJohn Forte 	}
5232fcf3ce44SJohn Forte 
5233fcf3ce44SJohn Forte 	/*
5234fcf3ce44SJohn Forte 	 * Error if no M_DATA follows
5235fcf3ce44SJohn Forte 	 */
5236fcf3ce44SJohn Forte 	nmp = mp->b_cont;
5237fcf3ce44SJohn Forte 	if (nmp == NULL) {
5238fcf3ce44SJohn Forte 		dluderrorind(wq, mp, (mp->b_rptr + off), len, DL_BADDATA, 0);
5239fcf3ce44SJohn Forte 		return;
5240fcf3ce44SJohn Forte 	}
5241fcf3ce44SJohn Forte 	dlap = (struct fcipdladdr *)(mp->b_rptr + off);
5242fcf3ce44SJohn Forte 
5243fcf3ce44SJohn Forte 	/*
5244fcf3ce44SJohn Forte 	 * Now get the destination structure for the remote NPORT
5245fcf3ce44SJohn Forte 	 */
5246fcf3ce44SJohn Forte 	ether_to_wwn(&dlap->dl_phys, &wwn);
5247fcf3ce44SJohn Forte 	fdestp = fcip_get_dest(fptr, &wwn);
5248fcf3ce44SJohn Forte 
5249fcf3ce44SJohn Forte 	if (fdestp == NULL) {
5250fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_NOTE,
5251b664061fSToomas Soome 		    "udreq - couldn't find dest struct for remote port"));
5252b664061fSToomas Soome 		dluderrorind(wq, mp, (mp->b_rptr + off), len, DL_BADDATA, 0);
5253fcf3ce44SJohn Forte 		return;
5254fcf3ce44SJohn Forte 	}
5255fcf3ce44SJohn Forte 
5256fcf3ce44SJohn Forte 	/*
5257fcf3ce44SJohn Forte 	 * Network header + SAP
5258fcf3ce44SJohn Forte 	 */
5259fcf3ce44SJohn Forte 	hdr_size = sizeof (fcph_network_hdr_t) + sizeof (llc_snap_hdr_t);
5260fcf3ce44SJohn Forte 
5261fcf3ce44SJohn Forte 	/* DB_REF gives the no. of msgs pointing to this block */
5262fcf3ce44SJohn Forte 	if ((DB_REF(nmp) == 1) &&
5263fcf3ce44SJohn Forte 	    (MBLKHEAD(nmp) >= hdr_size) &&
5264fcf3ce44SJohn Forte 	    (((uintptr_t)mp->b_rptr & 0x1) == 0)) {
5265fcf3ce44SJohn Forte 		la_wwn_t wwn;
5266fcf3ce44SJohn Forte 		nmp->b_rptr -= hdr_size;
5267fcf3ce44SJohn Forte 
5268fcf3ce44SJohn Forte 		/* first put the network header */
5269fcf3ce44SJohn Forte 		headerp = (fcph_network_hdr_t *)nmp->b_rptr;
5270fcf3ce44SJohn Forte 		if (ether_cmp(&dlap->dl_phys, &fcip_arpbroadcast_addr) == 0) {
5271fcf3ce44SJohn Forte 			ether_to_wwn(&fcipnhbroadcastaddr, &wwn);
5272fcf3ce44SJohn Forte 		} else {
5273fcf3ce44SJohn Forte 			ether_to_wwn(&dlap->dl_phys, &wwn);
5274fcf3ce44SJohn Forte 		}
5275fcf3ce44SJohn Forte 		bcopy(&wwn, &headerp->net_dest_addr, sizeof (la_wwn_t));
5276fcf3ce44SJohn Forte 		ether_to_wwn(&fptr->fcip_macaddr, &wwn);
5277fcf3ce44SJohn Forte 		bcopy(&wwn, &headerp->net_src_addr, sizeof (la_wwn_t));
5278fcf3ce44SJohn Forte 
5279fcf3ce44SJohn Forte 		/* Now the snap header */
5280fcf3ce44SJohn Forte 		lsnap = (llc_snap_hdr_t *)(nmp->b_rptr +
5281fcf3ce44SJohn Forte 		    sizeof (fcph_network_hdr_t));
5282fcf3ce44SJohn Forte 		lsnap->dsap = 0xAA;
5283fcf3ce44SJohn Forte 		lsnap->ssap = 0xAA;
5284fcf3ce44SJohn Forte 		lsnap->ctrl = 0x03;
5285fcf3ce44SJohn Forte 		lsnap->oui[0] = 0x00;
5286fcf3ce44SJohn Forte 		lsnap->oui[1] = 0x00; 	/* 80 */
5287fcf3ce44SJohn Forte 		lsnap->oui[2] = 0x00;	/* C2 */
5288fcf3ce44SJohn Forte 		lsnap->pid = BE_16((dlap->dl_sap));
5289fcf3ce44SJohn Forte 
5290fcf3ce44SJohn Forte 		freeb(mp);
5291fcf3ce44SJohn Forte 		mp = nmp;
5292fcf3ce44SJohn Forte 
5293fcf3ce44SJohn Forte 	} else {
5294fcf3ce44SJohn Forte 		la_wwn_t wwn;
5295fcf3ce44SJohn Forte 
5296fcf3ce44SJohn Forte 		DB_TYPE(mp) = M_DATA;
5297fcf3ce44SJohn Forte 		headerp = (fcph_network_hdr_t *)mp->b_rptr;
5298fcf3ce44SJohn Forte 
5299fcf3ce44SJohn Forte 		/*
5300fcf3ce44SJohn Forte 		 * Only fill in the low 48bits of WWN for now - we can
5301fcf3ce44SJohn Forte 		 * fill in the NAA_ID after we find the port in the
5302fcf3ce44SJohn Forte 		 * routing tables
5303fcf3ce44SJohn Forte 		 */
5304fcf3ce44SJohn Forte 		if (ether_cmp(&dlap->dl_phys, &fcip_arpbroadcast_addr) == 0) {
5305fcf3ce44SJohn Forte 			ether_to_wwn(&fcipnhbroadcastaddr, &wwn);
5306fcf3ce44SJohn Forte 		} else {
5307fcf3ce44SJohn Forte 			ether_to_wwn(&dlap->dl_phys, &wwn);
5308fcf3ce44SJohn Forte 		}
5309fcf3ce44SJohn Forte 		bcopy(&wwn, &headerp->net_dest_addr, sizeof (la_wwn_t));
5310fcf3ce44SJohn Forte 		/* need to send our PWWN */
5311fcf3ce44SJohn Forte 		bcopy(&fport->fcipp_pwwn, &headerp->net_src_addr,
5312fcf3ce44SJohn Forte 		    sizeof (la_wwn_t));
5313fcf3ce44SJohn Forte 
5314fcf3ce44SJohn Forte 		lsnap = (llc_snap_hdr_t *)(nmp->b_rptr +
5315fcf3ce44SJohn Forte 		    sizeof (fcph_network_hdr_t));
5316fcf3ce44SJohn Forte 		lsnap->dsap = 0xAA;
5317fcf3ce44SJohn Forte 		lsnap->ssap = 0xAA;
5318fcf3ce44SJohn Forte 		lsnap->ctrl = 0x03;
5319fcf3ce44SJohn Forte 		lsnap->oui[0] = 0x00;
5320fcf3ce44SJohn Forte 		lsnap->oui[1] = 0x00;
5321fcf3ce44SJohn Forte 		lsnap->oui[2] = 0x00;
5322fcf3ce44SJohn Forte 		lsnap->pid = BE_16(dlap->dl_sap);
5323fcf3ce44SJohn Forte 
5324fcf3ce44SJohn Forte 		mp->b_wptr = mp->b_rptr + hdr_size;
5325fcf3ce44SJohn Forte 	}
5326fcf3ce44SJohn Forte 
5327fcf3ce44SJohn Forte 	/*
5328fcf3ce44SJohn Forte 	 * Ethernet drivers have a lot of gunk here to put the Type
5329fcf3ce44SJohn Forte 	 * information (for Ethernet encapsulation (RFC 894) or the
5330fcf3ce44SJohn Forte 	 * Length (for 802.2/802.3) - I guess we'll just ignore that
5331fcf3ce44SJohn Forte 	 * here.
5332fcf3ce44SJohn Forte 	 */
5333fcf3ce44SJohn Forte 
5334fcf3ce44SJohn Forte 	/*
5335fcf3ce44SJohn Forte 	 * Start the I/O on this port. If fcip_start failed for some reason
5336fcf3ce44SJohn Forte 	 * we call putbq in fcip_start so we don't need to check the
5337fcf3ce44SJohn Forte 	 * return value from fcip_start
5338fcf3ce44SJohn Forte 	 */
5339fcf3ce44SJohn Forte 	(void) fcip_start(wq, mp, fptr, fdestp, KM_SLEEP);
5340fcf3ce44SJohn Forte }
5341fcf3ce44SJohn Forte 
5342fcf3ce44SJohn Forte /*
5343fcf3ce44SJohn Forte  * DL_ATTACH_REQ: attaches a PPA with a stream. ATTACH requets are needed
5344fcf3ce44SJohn Forte  * for style 2 DLS providers to identify the physical medium through which
5345fcf3ce44SJohn Forte  * the streams communication will happen
5346fcf3ce44SJohn Forte  */
5347fcf3ce44SJohn Forte static void
5348fcf3ce44SJohn Forte fcip_areq(queue_t *wq, mblk_t *mp)
5349fcf3ce44SJohn Forte {
5350fcf3ce44SJohn Forte 	struct fcipstr		*slp;
5351fcf3ce44SJohn Forte 	union DL_primitives	*dlp;
5352fcf3ce44SJohn Forte 	fcip_port_info_t	*fport;
5353fcf3ce44SJohn Forte 	struct fcip		*fptr;
5354fcf3ce44SJohn Forte 	int			ppa;
5355fcf3ce44SJohn Forte 
5356fcf3ce44SJohn Forte 	slp = (struct fcipstr *)wq->q_ptr;
5357fcf3ce44SJohn Forte 	dlp = (union DL_primitives *)mp->b_rptr;
5358fcf3ce44SJohn Forte 
5359fcf3ce44SJohn Forte 	if (MBLKL(mp) < DL_ATTACH_REQ_SIZE) {
5360fcf3ce44SJohn Forte 		dlerrorack(wq, mp, DL_ATTACH_REQ, DL_BADPRIM, 0);
5361fcf3ce44SJohn Forte 		return;
5362fcf3ce44SJohn Forte 	}
5363fcf3ce44SJohn Forte 
5364fcf3ce44SJohn Forte 	if (slp->sl_state != DL_UNATTACHED) {
5365fcf3ce44SJohn Forte 		dlerrorack(wq, mp, DL_ATTACH_REQ, DL_OUTSTATE, 0);
5366fcf3ce44SJohn Forte 		return;
5367fcf3ce44SJohn Forte 	}
5368fcf3ce44SJohn Forte 
5369fcf3ce44SJohn Forte 	ppa = dlp->attach_req.dl_ppa;
5370fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_NOTE, "attach req: ppa %x", ppa));
5371fcf3ce44SJohn Forte 
5372fcf3ce44SJohn Forte 	/*
5373fcf3ce44SJohn Forte 	 * check if the PPA is valid
5374fcf3ce44SJohn Forte 	 */
5375fcf3ce44SJohn Forte 
5376fcf3ce44SJohn Forte 	mutex_enter(&fcip_global_mutex);
5377fcf3ce44SJohn Forte 
5378fcf3ce44SJohn Forte 	for (fport = fcip_port_head; fport; fport = fport->fcipp_next) {
5379fcf3ce44SJohn Forte 		if ((fptr = fport->fcipp_fcip) == NULL) {
5380fcf3ce44SJohn Forte 			continue;
5381fcf3ce44SJohn Forte 		}
5382fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_NOTE, "ppa %x, inst %x", ppa,
5383fcf3ce44SJohn Forte 		    ddi_get_instance(fptr->fcip_dip)));
5384fcf3ce44SJohn Forte 
5385fcf3ce44SJohn Forte 		if (ppa == ddi_get_instance(fptr->fcip_dip)) {
5386fcf3ce44SJohn Forte 			FCIP_DEBUG(FCIP_DEBUG_DLPI,
5387fcf3ce44SJohn Forte 			    (CE_NOTE, "ppa found %x", ppa));
5388fcf3ce44SJohn Forte 			break;
5389fcf3ce44SJohn Forte 		}
5390fcf3ce44SJohn Forte 	}
5391fcf3ce44SJohn Forte 
5392fcf3ce44SJohn Forte 	if (fport == NULL) {
5393fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DLPI,
5394fcf3ce44SJohn Forte 		    (CE_NOTE, "dlerrorack coz fport==NULL"));
5395fcf3ce44SJohn Forte 
5396fcf3ce44SJohn Forte 		mutex_exit(&fcip_global_mutex);
5397fcf3ce44SJohn Forte 
5398fcf3ce44SJohn Forte 		if (fc_ulp_get_port_handle(ppa) == NULL) {
5399fcf3ce44SJohn Forte 			dlerrorack(wq, mp, DL_ATTACH_REQ, DL_BADPPA, 0);
5400fcf3ce44SJohn Forte 			return;
5401fcf3ce44SJohn Forte 		}
5402fcf3ce44SJohn Forte 
5403fcf3ce44SJohn Forte 		/*
5404fcf3ce44SJohn Forte 		 * Wait for Port attach callback to trigger.  If port_detach
5405fcf3ce44SJohn Forte 		 * got in while we were waiting, then ddi_get_soft_state
5406fcf3ce44SJohn Forte 		 * will return NULL, and we'll return error.
5407fcf3ce44SJohn Forte 		 */
5408fcf3ce44SJohn Forte 
5409fcf3ce44SJohn Forte 		delay(drv_usectohz(FCIP_INIT_DELAY));
5410fcf3ce44SJohn Forte 		mutex_enter(&fcip_global_mutex);
5411fcf3ce44SJohn Forte 
5412fcf3ce44SJohn Forte 		fptr = ddi_get_soft_state(fcip_softp, ppa);
5413fcf3ce44SJohn Forte 		if (fptr == NULL) {
5414fcf3ce44SJohn Forte 			mutex_exit(&fcip_global_mutex);
5415fcf3ce44SJohn Forte 			dlerrorack(wq, mp, DL_ATTACH_REQ, DL_BADPPA, 0);
5416fcf3ce44SJohn Forte 			return;
5417fcf3ce44SJohn Forte 		}
5418fcf3ce44SJohn Forte 	}
5419fcf3ce44SJohn Forte 
5420fcf3ce44SJohn Forte 	/*
5421fcf3ce44SJohn Forte 	 * set link to device and update our state
5422fcf3ce44SJohn Forte 	 */
5423fcf3ce44SJohn Forte 	slp->sl_fcip = fptr;
5424fcf3ce44SJohn Forte 	slp->sl_state = DL_UNBOUND;
5425fcf3ce44SJohn Forte 
5426fcf3ce44SJohn Forte 	mutex_exit(&fcip_global_mutex);
5427fcf3ce44SJohn Forte 
5428fcf3ce44SJohn Forte #ifdef DEBUG
5429fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_mutex);
5430fcf3ce44SJohn Forte 	if (fptr->fcip_flags & FCIP_LINK_DOWN) {
5431fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_WARN, "port not online yet"));
5432fcf3ce44SJohn Forte 	}
5433fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_mutex);
5434fcf3ce44SJohn Forte #endif
5435fcf3ce44SJohn Forte 
5436fcf3ce44SJohn Forte 	dlokack(wq, mp, DL_ATTACH_REQ);
5437fcf3ce44SJohn Forte }
5438fcf3ce44SJohn Forte 
5439fcf3ce44SJohn Forte 
5440fcf3ce44SJohn Forte /*
5441fcf3ce44SJohn Forte  * DL_DETACH request - detaches a PPA from a stream
5442fcf3ce44SJohn Forte  */
5443fcf3ce44SJohn Forte static void
5444fcf3ce44SJohn Forte fcip_dreq(queue_t *wq, mblk_t *mp)
5445fcf3ce44SJohn Forte {
5446fcf3ce44SJohn Forte 	struct fcipstr		*slp;
5447fcf3ce44SJohn Forte 
5448fcf3ce44SJohn Forte 	slp = (struct fcipstr *)wq->q_ptr;
5449fcf3ce44SJohn Forte 
5450fcf3ce44SJohn Forte 	if (MBLKL(mp) < DL_DETACH_REQ_SIZE) {
5451fcf3ce44SJohn Forte 		dlerrorack(wq, mp, DL_DETACH_REQ, DL_BADPRIM, 0);
5452fcf3ce44SJohn Forte 		return;
5453fcf3ce44SJohn Forte 	}
5454fcf3ce44SJohn Forte 
5455fcf3ce44SJohn Forte 	if (slp->sl_state != DL_UNBOUND) {
5456fcf3ce44SJohn Forte 		dlerrorack(wq, mp, DL_DETACH_REQ, DL_OUTSTATE, 0);
5457fcf3ce44SJohn Forte 		return;
5458fcf3ce44SJohn Forte 	}
5459fcf3ce44SJohn Forte 
5460fcf3ce44SJohn Forte 	fcip_dodetach(slp);
5461fcf3ce44SJohn Forte 	dlokack(wq, mp, DL_DETACH_REQ);
5462fcf3ce44SJohn Forte }
5463fcf3ce44SJohn Forte 
5464fcf3ce44SJohn Forte /*
5465fcf3ce44SJohn Forte  * DL_BIND request: requests a DLS provider to bind a DLSAP to the stream.
5466fcf3ce44SJohn Forte  * DLS users communicate with a physical interface through DLSAPs. Multiple
5467fcf3ce44SJohn Forte  * DLSAPs can be bound to the same stream (PPA)
5468fcf3ce44SJohn Forte  */
5469fcf3ce44SJohn Forte static void
5470fcf3ce44SJohn Forte fcip_breq(queue_t *wq, mblk_t *mp)
5471fcf3ce44SJohn Forte {
5472fcf3ce44SJohn Forte 	struct fcipstr		*slp;
5473fcf3ce44SJohn Forte 	union DL_primitives	*dlp;
5474fcf3ce44SJohn Forte 	struct fcip		*fptr;
5475fcf3ce44SJohn Forte 	struct fcipdladdr	fcipaddr;
5476fcf3ce44SJohn Forte 	t_uscalar_t		sap;
5477fcf3ce44SJohn Forte 	int			xidtest;
5478fcf3ce44SJohn Forte 
5479fcf3ce44SJohn Forte 	slp = (struct fcipstr *)wq->q_ptr;
5480fcf3ce44SJohn Forte 
5481fcf3ce44SJohn Forte 	if (MBLKL(mp) < DL_BIND_REQ_SIZE) {
5482fcf3ce44SJohn Forte 		dlerrorack(wq, mp, DL_BIND_REQ, DL_BADPRIM, 0);
5483fcf3ce44SJohn Forte 		return;
5484fcf3ce44SJohn Forte 	}
5485fcf3ce44SJohn Forte 
5486fcf3ce44SJohn Forte 	if (slp->sl_state != DL_UNBOUND) {
5487fcf3ce44SJohn Forte 		dlerrorack(wq, mp, DL_BIND_REQ, DL_OUTSTATE, 0);
5488fcf3ce44SJohn Forte 		return;
5489fcf3ce44SJohn Forte 	}
5490fcf3ce44SJohn Forte 
5491fcf3ce44SJohn Forte 	dlp = (union DL_primitives *)mp->b_rptr;
5492fcf3ce44SJohn Forte 	fptr = slp->sl_fcip;
5493fcf3ce44SJohn Forte 
5494fcf3ce44SJohn Forte 	if (fptr == NULL) {
5495fcf3ce44SJohn Forte 		dlerrorack(wq, mp, DL_BIND_REQ, DL_OUTSTATE, 0);
5496fcf3ce44SJohn Forte 		return;
5497fcf3ce44SJohn Forte 	}
5498fcf3ce44SJohn Forte 
5499fcf3ce44SJohn Forte 	sap = dlp->bind_req.dl_sap;
5500fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_NOTE, "fcip_breq - sap: %x", sap));
5501fcf3ce44SJohn Forte 	xidtest = dlp->bind_req.dl_xidtest_flg;
5502fcf3ce44SJohn Forte 
5503fcf3ce44SJohn Forte 	if (xidtest) {
5504fcf3ce44SJohn Forte 		dlerrorack(wq, mp, DL_BIND_REQ, DL_NOAUTO, 0);
5505fcf3ce44SJohn Forte 		return;
5506fcf3ce44SJohn Forte 	}
5507fcf3ce44SJohn Forte 
5508fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_NOTE, "DLBIND: sap : %x", sap));
5509fcf3ce44SJohn Forte 
5510fcf3ce44SJohn Forte 	if (sap > ETHERTYPE_MAX) {
5511fcf3ce44SJohn Forte 		dlerrorack(wq, mp, dlp->dl_primitive, DL_BADSAP, 0);
5512fcf3ce44SJohn Forte 		return;
5513fcf3ce44SJohn Forte 	}
5514fcf3ce44SJohn Forte 	/*
5515fcf3ce44SJohn Forte 	 * save SAP for this stream and change the link state
5516fcf3ce44SJohn Forte 	 */
5517fcf3ce44SJohn Forte 	slp->sl_sap = sap;
5518fcf3ce44SJohn Forte 	slp->sl_state = DL_IDLE;
5519fcf3ce44SJohn Forte 
5520fcf3ce44SJohn Forte 	fcipaddr.dl_sap = sap;
5521fcf3ce44SJohn Forte 	ether_bcopy(&fptr->fcip_macaddr, &fcipaddr.dl_phys);
5522fcf3ce44SJohn Forte 	dlbindack(wq, mp, sap, &fcipaddr, FCIPADDRL, 0, 0);
5523fcf3ce44SJohn Forte 
5524fcf3ce44SJohn Forte 	fcip_setipq(fptr);
5525fcf3ce44SJohn Forte }
5526fcf3ce44SJohn Forte 
5527fcf3ce44SJohn Forte /*
5528fcf3ce44SJohn Forte  * DL_UNBIND request to unbind a previously bound DLSAP, from this stream
5529fcf3ce44SJohn Forte  */
5530fcf3ce44SJohn Forte static void
5531fcf3ce44SJohn Forte fcip_ubreq(queue_t *wq, mblk_t *mp)
5532fcf3ce44SJohn Forte {
5533fcf3ce44SJohn Forte 	struct fcipstr	*slp;
5534fcf3ce44SJohn Forte 
5535fcf3ce44SJohn Forte 	slp = (struct fcipstr *)wq->q_ptr;
5536fcf3ce44SJohn Forte 
5537fcf3ce44SJohn Forte 	if (MBLKL(mp) < DL_UNBIND_REQ_SIZE) {
5538fcf3ce44SJohn Forte 		dlerrorack(wq, mp, DL_UNBIND_REQ, DL_BADPRIM, 0);
5539fcf3ce44SJohn Forte 		return;
5540fcf3ce44SJohn Forte 	}
5541fcf3ce44SJohn Forte 
5542fcf3ce44SJohn Forte 	if (slp->sl_state != DL_IDLE) {
5543fcf3ce44SJohn Forte 		dlerrorack(wq, mp, DL_UNBIND_REQ, DL_OUTSTATE, 0);
5544fcf3ce44SJohn Forte 		return;
5545fcf3ce44SJohn Forte 	}
5546fcf3ce44SJohn Forte 
5547fcf3ce44SJohn Forte 	slp->sl_state = DL_UNBOUND;
5548fcf3ce44SJohn Forte 	slp->sl_sap = 0;
5549fcf3ce44SJohn Forte 
5550fcf3ce44SJohn Forte 	(void) putnextctl1(RD(wq), M_FLUSH, FLUSHRW);
5551fcf3ce44SJohn Forte 	dlokack(wq, mp, DL_UNBIND_REQ);
5552fcf3ce44SJohn Forte 
5553fcf3ce44SJohn Forte 	fcip_setipq(slp->sl_fcip);
5554fcf3ce44SJohn Forte }
5555fcf3ce44SJohn Forte 
5556fcf3ce44SJohn Forte /*
5557fcf3ce44SJohn Forte  * Return our physical address
5558fcf3ce44SJohn Forte  */
5559fcf3ce44SJohn Forte static void
5560fcf3ce44SJohn Forte fcip_pareq(queue_t *wq, mblk_t *mp)
5561fcf3ce44SJohn Forte {
5562fcf3ce44SJohn Forte 	struct fcipstr 		*slp;
5563fcf3ce44SJohn Forte 	union DL_primitives	*dlp;
5564fcf3ce44SJohn Forte 	int			type;
5565fcf3ce44SJohn Forte 	struct fcip		*fptr;
5566fcf3ce44SJohn Forte 	fcip_port_info_t	*fport;
5567fcf3ce44SJohn Forte 	struct ether_addr	addr;
5568fcf3ce44SJohn Forte 
5569fcf3ce44SJohn Forte 	slp = (struct fcipstr *)wq->q_ptr;
5570fcf3ce44SJohn Forte 
5571fcf3ce44SJohn Forte 	if (MBLKL(mp) < DL_PHYS_ADDR_REQ_SIZE) {
5572fcf3ce44SJohn Forte 		dlerrorack(wq, mp, DL_PHYS_ADDR_REQ, DL_BADPRIM, 0);
5573fcf3ce44SJohn Forte 		return;
5574fcf3ce44SJohn Forte 	}
5575fcf3ce44SJohn Forte 
5576fcf3ce44SJohn Forte 	dlp = (union DL_primitives *)mp->b_rptr;
5577fcf3ce44SJohn Forte 	type = dlp->physaddr_req.dl_addr_type;
5578fcf3ce44SJohn Forte 	fptr = slp->sl_fcip;
5579fcf3ce44SJohn Forte 
5580fcf3ce44SJohn Forte 	if (fptr == NULL) {
5581fcf3ce44SJohn Forte 		dlerrorack(wq, mp, DL_PHYS_ADDR_REQ, DL_OUTSTATE, 0);
5582fcf3ce44SJohn Forte 		return;
5583fcf3ce44SJohn Forte 	}
5584fcf3ce44SJohn Forte 
5585fcf3ce44SJohn Forte 	fport = fptr->fcip_port_info;
5586fcf3ce44SJohn Forte 
5587fcf3ce44SJohn Forte 	switch (type) {
5588fcf3ce44SJohn Forte 	case DL_FACT_PHYS_ADDR:
5589fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DLPI,
5590fcf3ce44SJohn Forte 		    (CE_NOTE, "returning factory phys addr"));
5591fcf3ce44SJohn Forte 		wwn_to_ether(&fport->fcipp_pwwn, &addr);
5592fcf3ce44SJohn Forte 		break;
5593fcf3ce44SJohn Forte 
5594fcf3ce44SJohn Forte 	case DL_CURR_PHYS_ADDR:
5595fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DLPI,
5596fcf3ce44SJohn Forte 		    (CE_NOTE, "returning current phys addr"));
5597fcf3ce44SJohn Forte 		ether_bcopy(&fptr->fcip_macaddr, &addr);
5598fcf3ce44SJohn Forte 		break;
5599fcf3ce44SJohn Forte 
5600fcf3ce44SJohn Forte 	default:
5601fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DLPI,
5602fcf3ce44SJohn Forte 		    (CE_NOTE, "Not known cmd type in phys addr"));
5603fcf3ce44SJohn Forte 		dlerrorack(wq, mp, DL_PHYS_ADDR_REQ, DL_NOTSUPPORTED, 0);
5604fcf3ce44SJohn Forte 		return;
5605fcf3ce44SJohn Forte 	}
5606fcf3ce44SJohn Forte 	dlphysaddrack(wq, mp, &addr, ETHERADDRL);
5607fcf3ce44SJohn Forte }
5608fcf3ce44SJohn Forte 
5609fcf3ce44SJohn Forte /*
5610fcf3ce44SJohn Forte  * Set physical address DLPI request
5611fcf3ce44SJohn Forte  */
5612fcf3ce44SJohn Forte static void
5613fcf3ce44SJohn Forte fcip_spareq(queue_t *wq, mblk_t *mp)
5614fcf3ce44SJohn Forte {
5615fcf3ce44SJohn Forte 	struct fcipstr		*slp;
5616fcf3ce44SJohn Forte 	union DL_primitives	*dlp;
5617fcf3ce44SJohn Forte 	t_uscalar_t		off, len;
5618fcf3ce44SJohn Forte 	struct ether_addr	*addrp;
5619fcf3ce44SJohn Forte 	la_wwn_t		wwn;
5620fcf3ce44SJohn Forte 	struct fcip		*fptr;
5621fcf3ce44SJohn Forte 	fc_ns_cmd_t		fcip_ns_cmd;
5622fcf3ce44SJohn Forte 
5623fcf3ce44SJohn Forte 	slp = (struct fcipstr *)wq->q_ptr;
5624fcf3ce44SJohn Forte 
5625fcf3ce44SJohn Forte 	if (MBLKL(mp) < DL_SET_PHYS_ADDR_REQ_SIZE) {
5626fcf3ce44SJohn Forte 		dlerrorack(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADPRIM, 0);
5627fcf3ce44SJohn Forte 		return;
5628fcf3ce44SJohn Forte 	}
5629fcf3ce44SJohn Forte 
5630fcf3ce44SJohn Forte 	dlp = (union DL_primitives *)mp->b_rptr;
5631fcf3ce44SJohn Forte 	len = dlp->set_physaddr_req.dl_addr_length;
5632fcf3ce44SJohn Forte 	off = dlp->set_physaddr_req.dl_addr_offset;
5633fcf3ce44SJohn Forte 
5634fcf3ce44SJohn Forte 	if (!MBLKIN(mp, off, len)) {
5635fcf3ce44SJohn Forte 		dlerrorack(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADPRIM, 0);
5636fcf3ce44SJohn Forte 		return;
5637fcf3ce44SJohn Forte 	}
5638fcf3ce44SJohn Forte 
5639fcf3ce44SJohn Forte 	addrp = (struct ether_addr *)(mp->b_rptr + off);
5640fcf3ce44SJohn Forte 
5641fcf3ce44SJohn Forte 	/*
5642fcf3ce44SJohn Forte 	 * If the length of physical address is not correct or address
5643fcf3ce44SJohn Forte 	 * specified is a broadcast address or multicast addr -
5644fcf3ce44SJohn Forte 	 * return an error.
5645fcf3ce44SJohn Forte 	 */
5646fcf3ce44SJohn Forte 	if ((len != ETHERADDRL) ||
5647fcf3ce44SJohn Forte 	    ((addrp->ether_addr_octet[0] & 01) == 1) ||
5648fcf3ce44SJohn Forte 	    (ether_cmp(addrp, &fcip_arpbroadcast_addr) == 0)) {
5649fcf3ce44SJohn Forte 		dlerrorack(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADADDR, 0);
5650fcf3ce44SJohn Forte 		return;
5651fcf3ce44SJohn Forte 	}
5652fcf3ce44SJohn Forte 
5653fcf3ce44SJohn Forte 	/*
5654fcf3ce44SJohn Forte 	 * check if a stream is attached to this device. Else return an error
5655fcf3ce44SJohn Forte 	 */
5656fcf3ce44SJohn Forte 	if ((fptr = slp->sl_fcip) == NULL) {
5657fcf3ce44SJohn Forte 		dlerrorack(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_OUTSTATE, 0);
5658fcf3ce44SJohn Forte 		return;
5659fcf3ce44SJohn Forte 	}
5660fcf3ce44SJohn Forte 
5661fcf3ce44SJohn Forte 	/*
5662fcf3ce44SJohn Forte 	 * set the new interface local address. We request the transport
5663fcf3ce44SJohn Forte 	 * layer to change the Port WWN for this device - return an error
5664fcf3ce44SJohn Forte 	 * if we don't succeed.
5665fcf3ce44SJohn Forte 	 */
5666fcf3ce44SJohn Forte 
5667fcf3ce44SJohn Forte 	ether_to_wwn(addrp, &wwn);
5668fcf3ce44SJohn Forte 	if (fcip_set_wwn(&wwn) == FC_SUCCESS) {
5669fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DLPI,
5670fcf3ce44SJohn Forte 		    (CE_WARN, "WWN changed in spareq"));
5671fcf3ce44SJohn Forte 	} else {
5672fcf3ce44SJohn Forte 		dlerrorack(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADADDR, 0);
5673fcf3ce44SJohn Forte 	}
5674fcf3ce44SJohn Forte 
5675fcf3ce44SJohn Forte 	/*
5676fcf3ce44SJohn Forte 	 * register The new Port WWN and Node WWN with the transport
5677fcf3ce44SJohn Forte 	 * and Nameserver. Hope the transport ensures all current I/O
5678fcf3ce44SJohn Forte 	 * has stopped before actually attempting to register a new
5679fcf3ce44SJohn Forte 	 * port and Node WWN else we are hosed. Maybe a Link reset
5680fcf3ce44SJohn Forte 	 * will get everyone's attention.
5681fcf3ce44SJohn Forte 	 */
5682fcf3ce44SJohn Forte 	fcip_ns_cmd.ns_flags = 0;
5683fcf3ce44SJohn Forte 	fcip_ns_cmd.ns_cmd = NS_RPN_ID;
5684fcf3ce44SJohn Forte 	fcip_ns_cmd.ns_req_len = sizeof (la_wwn_t);
5685fcf3ce44SJohn Forte 	fcip_ns_cmd.ns_req_payload = (caddr_t)&wwn.raw_wwn[0];
5686fcf3ce44SJohn Forte 	fcip_ns_cmd.ns_resp_len = 0;
5687fcf3ce44SJohn Forte 	fcip_ns_cmd.ns_resp_payload = (caddr_t)0;
5688fcf3ce44SJohn Forte 	if (fc_ulp_port_ns(fptr->fcip_port_info->fcipp_handle,
5689fcf3ce44SJohn Forte 	    (opaque_t)0, &fcip_ns_cmd) != FC_SUCCESS) {
5690fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DLPI,
5691fcf3ce44SJohn Forte 		    (CE_WARN, "setting Port WWN failed"));
5692fcf3ce44SJohn Forte 		dlerrorack(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADPRIM, 0);
5693fcf3ce44SJohn Forte 		return;
5694fcf3ce44SJohn Forte 	}
5695fcf3ce44SJohn Forte 
5696fcf3ce44SJohn Forte 	dlokack(wq, mp, DL_SET_PHYS_ADDR_REQ);
5697fcf3ce44SJohn Forte }
5698fcf3ce44SJohn Forte 
5699fcf3ce44SJohn Forte /*
5700fcf3ce44SJohn Forte  * change our port's WWN if permitted by hardware
5701fcf3ce44SJohn Forte  */
5702fcf3ce44SJohn Forte /* ARGSUSED */
5703fcf3ce44SJohn Forte static int
5704fcf3ce44SJohn Forte fcip_set_wwn(la_wwn_t *pwwn)
5705fcf3ce44SJohn Forte {
5706fcf3ce44SJohn Forte 	/*
5707fcf3ce44SJohn Forte 	 * We're usually not allowed to change the WWN of adapters
5708fcf3ce44SJohn Forte 	 * but some adapters do permit us to change the WWN - don't
5709fcf3ce44SJohn Forte 	 * permit setting of WWNs (yet?) - This behavior could be
5710fcf3ce44SJohn Forte 	 * modified if needed
5711fcf3ce44SJohn Forte 	 */
5712fcf3ce44SJohn Forte 	return (FC_FAILURE);
5713fcf3ce44SJohn Forte }
5714fcf3ce44SJohn Forte 
5715fcf3ce44SJohn Forte 
5716fcf3ce44SJohn Forte /*
5717fcf3ce44SJohn Forte  * This routine fills in the header for fastpath data requests. What this
5718fcf3ce44SJohn Forte  * does in simple terms is, instead of sending all data through the Unitdata
5719fcf3ce44SJohn Forte  * request dlpi code paths (which will then append the protocol specific
5720fcf3ce44SJohn Forte  * header - network and snap headers in our case), the upper layers issue
5721fcf3ce44SJohn Forte  * a M_IOCTL with a DL_IOC_HDR_INFO request and ask the streams endpoint
5722fcf3ce44SJohn Forte  * driver to give the header it needs appended and the upper layer
5723fcf3ce44SJohn Forte  * allocates and fills in the header and calls our put routine
5724fcf3ce44SJohn Forte  */
5725fcf3ce44SJohn Forte static void
5726fcf3ce44SJohn Forte fcip_dl_ioc_hdr_info(queue_t *wq, mblk_t *mp)
5727fcf3ce44SJohn Forte {
5728fcf3ce44SJohn Forte 	mblk_t			*nmp;
5729fcf3ce44SJohn Forte 	struct fcipstr		*slp;
5730fcf3ce44SJohn Forte 	struct fcipdladdr	*dlap;
5731fcf3ce44SJohn Forte 	dl_unitdata_req_t	*dlup;
5732fcf3ce44SJohn Forte 	fcph_network_hdr_t	*headerp;
5733fcf3ce44SJohn Forte 	la_wwn_t		wwn;
5734fcf3ce44SJohn Forte 	llc_snap_hdr_t		*lsnap;
5735fcf3ce44SJohn Forte 	struct fcip		*fptr;
5736fcf3ce44SJohn Forte 	fcip_port_info_t	*fport;
5737fcf3ce44SJohn Forte 	t_uscalar_t		off, len;
5738fcf3ce44SJohn Forte 	size_t			hdrlen;
5739fcf3ce44SJohn Forte 	int 			error;
5740fcf3ce44SJohn Forte 
5741fcf3ce44SJohn Forte 	slp = (struct fcipstr *)wq->q_ptr;
5742fcf3ce44SJohn Forte 	fptr = slp->sl_fcip;
5743fcf3ce44SJohn Forte 	if (fptr == NULL) {
5744fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
5745fcf3ce44SJohn Forte 		    (CE_NOTE, "dliochdr : returns EINVAL1"));
5746fcf3ce44SJohn Forte 		miocnak(wq, mp, 0, EINVAL);
5747fcf3ce44SJohn Forte 		return;
5748fcf3ce44SJohn Forte 	}
5749fcf3ce44SJohn Forte 
5750fcf3ce44SJohn Forte 	error = miocpullup(mp, sizeof (dl_unitdata_req_t) + FCIPADDRL);
5751fcf3ce44SJohn Forte 	if (error != 0) {
5752fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
5753fcf3ce44SJohn Forte 		    (CE_NOTE, "dliochdr : returns %d", error));
5754fcf3ce44SJohn Forte 		miocnak(wq, mp, 0, error);
5755fcf3ce44SJohn Forte 		return;
5756fcf3ce44SJohn Forte 	}
5757fcf3ce44SJohn Forte 
5758fcf3ce44SJohn Forte 	fport = fptr->fcip_port_info;
5759fcf3ce44SJohn Forte 
5760fcf3ce44SJohn Forte 	/*
5761fcf3ce44SJohn Forte 	 * check if the DL_UNITDATA_REQ destination addr has valid offset
5762fcf3ce44SJohn Forte 	 * and length values
5763fcf3ce44SJohn Forte 	 */
5764fcf3ce44SJohn Forte 	dlup = (dl_unitdata_req_t *)mp->b_cont->b_rptr;
5765fcf3ce44SJohn Forte 	off = dlup->dl_dest_addr_offset;
5766fcf3ce44SJohn Forte 	len = dlup->dl_dest_addr_length;
5767fcf3ce44SJohn Forte 	if (dlup->dl_primitive != DL_UNITDATA_REQ ||
5768fcf3ce44SJohn Forte 	    !MBLKIN(mp->b_cont, off, len) || (len != FCIPADDRL)) {
5769fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
5770fcf3ce44SJohn Forte 		    (CE_NOTE, "dliochdr : returns EINVAL2"));
5771fcf3ce44SJohn Forte 		miocnak(wq, mp, 0, EINVAL);
5772fcf3ce44SJohn Forte 		return;
5773fcf3ce44SJohn Forte 	}
5774fcf3ce44SJohn Forte 
5775fcf3ce44SJohn Forte 	dlap = (struct fcipdladdr *)(mp->b_cont->b_rptr + off);
5776fcf3ce44SJohn Forte 
5777fcf3ce44SJohn Forte 	/*
5778fcf3ce44SJohn Forte 	 * Allocate a new mblk to hold the ether header
5779fcf3ce44SJohn Forte 	 */
5780fcf3ce44SJohn Forte 
5781fcf3ce44SJohn Forte 	/*
5782fcf3ce44SJohn Forte 	 * setup space for network header
5783fcf3ce44SJohn Forte 	 */
5784fcf3ce44SJohn Forte 	hdrlen = (sizeof (llc_snap_hdr_t) + sizeof (fcph_network_hdr_t));
5785fcf3ce44SJohn Forte 	if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL) {
5786fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
5787fcf3ce44SJohn Forte 		    (CE_NOTE, "dliochdr : returns ENOMEM"));
5788fcf3ce44SJohn Forte 		miocnak(wq, mp, 0, ENOMEM);
5789fcf3ce44SJohn Forte 		return;
5790fcf3ce44SJohn Forte 	}
5791fcf3ce44SJohn Forte 	nmp->b_wptr += hdrlen;
5792fcf3ce44SJohn Forte 
5793fcf3ce44SJohn Forte 	/*
5794fcf3ce44SJohn Forte 	 * Fill in the Network Hdr and LLC SNAP header;
5795fcf3ce44SJohn Forte 	 */
5796fcf3ce44SJohn Forte 	headerp = (fcph_network_hdr_t *)nmp->b_rptr;
5797fcf3ce44SJohn Forte 	/*
5798fcf3ce44SJohn Forte 	 * just fill in the Node WWN here - we can fill in the NAA_ID when
5799fcf3ce44SJohn Forte 	 * we search the routing table
5800fcf3ce44SJohn Forte 	 */
5801fcf3ce44SJohn Forte 	if (ether_cmp(&dlap->dl_phys, &fcip_arpbroadcast_addr) == 0) {
5802fcf3ce44SJohn Forte 		ether_to_wwn(&fcipnhbroadcastaddr, &wwn);
5803fcf3ce44SJohn Forte 	} else {
5804fcf3ce44SJohn Forte 		ether_to_wwn(&dlap->dl_phys, &wwn);
5805fcf3ce44SJohn Forte 	}
5806fcf3ce44SJohn Forte 	bcopy(&wwn, &headerp->net_dest_addr, sizeof (la_wwn_t));
5807fcf3ce44SJohn Forte 	bcopy(&fport->fcipp_pwwn, &headerp->net_src_addr, sizeof (la_wwn_t));
5808fcf3ce44SJohn Forte 	lsnap = (llc_snap_hdr_t *)(nmp->b_rptr + sizeof (fcph_network_hdr_t));
5809fcf3ce44SJohn Forte 	lsnap->dsap = 0xAA;
5810fcf3ce44SJohn Forte 	lsnap->ssap = 0xAA;
5811fcf3ce44SJohn Forte 	lsnap->ctrl = 0x03;
5812fcf3ce44SJohn Forte 	lsnap->oui[0] = 0x00;
5813fcf3ce44SJohn Forte 	lsnap->oui[1] = 0x00;
5814fcf3ce44SJohn Forte 	lsnap->oui[2] = 0x00;
5815fcf3ce44SJohn Forte 	lsnap->pid = BE_16(dlap->dl_sap);
5816fcf3ce44SJohn Forte 
5817fcf3ce44SJohn Forte 	/*
5818fcf3ce44SJohn Forte 	 * Link new mblk in after the "request" mblks.
5819fcf3ce44SJohn Forte 	 */
5820fcf3ce44SJohn Forte 	linkb(mp, nmp);
5821fcf3ce44SJohn Forte 
5822fcf3ce44SJohn Forte 	slp->sl_flags |= FCIP_SLFAST;
5823fcf3ce44SJohn Forte 
5824fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
5825fcf3ce44SJohn Forte 	    (CE_NOTE, "dliochdr : returns success "));
5826fcf3ce44SJohn Forte 	miocack(wq, mp, msgsize(mp->b_cont), 0);
5827fcf3ce44SJohn Forte }
5828fcf3ce44SJohn Forte 
5829fcf3ce44SJohn Forte 
5830fcf3ce44SJohn Forte /*
5831fcf3ce44SJohn Forte  * Establish a kmem cache for fcip packets
5832fcf3ce44SJohn Forte  */
5833fcf3ce44SJohn Forte static int
5834fcf3ce44SJohn Forte fcip_cache_constructor(void *buf, void *arg, int flags)
5835fcf3ce44SJohn Forte {
5836fcf3ce44SJohn Forte 	fcip_pkt_t		*fcip_pkt = buf;
5837fcf3ce44SJohn Forte 	fc_packet_t		*fc_pkt;
5838fcf3ce44SJohn Forte 	fcip_port_info_t	*fport = (fcip_port_info_t *)arg;
5839fcf3ce44SJohn Forte 	int			(*cb) (caddr_t);
5840fcf3ce44SJohn Forte 	struct fcip		*fptr;
5841fcf3ce44SJohn Forte 
5842fcf3ce44SJohn Forte 	cb = (flags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT;
5843fcf3ce44SJohn Forte 
5844fcf3ce44SJohn Forte 	ASSERT(fport != NULL);
5845fcf3ce44SJohn Forte 
5846fcf3ce44SJohn Forte 	fptr = fport->fcipp_fcip;
5847fcf3ce44SJohn Forte 
5848fcf3ce44SJohn Forte 	/*
5849fcf3ce44SJohn Forte 	 * we allocated space for our private area at the end of the
5850fcf3ce44SJohn Forte 	 * fc packet. Make sure we point to it correctly. Ideally we
5851fcf3ce44SJohn Forte 	 * should just push fc_packet_private to the beginning or end
5852fcf3ce44SJohn Forte 	 * of the fc_packet structure
5853fcf3ce44SJohn Forte 	 */
5854fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_next = NULL;
5855fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_prev = NULL;
5856fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_dest = NULL;
5857fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_state = 0;
5858fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_reason = 0;
5859fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_flags = 0;
5860fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_fptr = fptr;
5861fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_dma_flags = 0;
5862fcf3ce44SJohn Forte 
5863fcf3ce44SJohn Forte 	fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
5864fcf3ce44SJohn Forte 	fc_pkt->pkt_ulp_rscn_infop = NULL;
5865fcf3ce44SJohn Forte 
5866fcf3ce44SJohn Forte 	/*
5867fcf3ce44SJohn Forte 	 * We use pkt_cmd_dma for OUTBOUND requests. We don't expect
5868fcf3ce44SJohn Forte 	 * any responses for outbound IP data so no need to setup
5869fcf3ce44SJohn Forte 	 * response or data dma handles.
5870fcf3ce44SJohn Forte 	 */
5871fcf3ce44SJohn Forte 	if (ddi_dma_alloc_handle(fport->fcipp_dip,
5872fcf3ce44SJohn Forte 	    &fport->fcipp_cmd_dma_attr, cb, NULL,
5873fcf3ce44SJohn Forte 	    &fc_pkt->pkt_cmd_dma) != DDI_SUCCESS) {
5874fcf3ce44SJohn Forte 		return (FCIP_FAILURE);
5875fcf3ce44SJohn Forte 	}
5876fcf3ce44SJohn Forte 
5877fcf3ce44SJohn Forte 	fc_pkt->pkt_cmd_acc = fc_pkt->pkt_resp_acc = NULL;
5878fcf3ce44SJohn Forte 	fc_pkt->pkt_fca_private = (opaque_t)((caddr_t)buf +
5879fcf3ce44SJohn Forte 	    sizeof (fcip_pkt_t));
5880fcf3ce44SJohn Forte 	fc_pkt->pkt_ulp_private = (opaque_t)fcip_pkt;
5881fcf3ce44SJohn Forte 
5882fcf3ce44SJohn Forte 	fc_pkt->pkt_cmd_cookie_cnt = fc_pkt->pkt_resp_cookie_cnt =
5883fcf3ce44SJohn Forte 	    fc_pkt->pkt_data_cookie_cnt = 0;
5884fcf3ce44SJohn Forte 	fc_pkt->pkt_cmd_cookie = fc_pkt->pkt_resp_cookie =
5885fcf3ce44SJohn Forte 	    fc_pkt->pkt_data_cookie = NULL;
5886fcf3ce44SJohn Forte 
5887fcf3ce44SJohn Forte 	return (FCIP_SUCCESS);
5888fcf3ce44SJohn Forte }
5889fcf3ce44SJohn Forte 
5890fcf3ce44SJohn Forte /*
5891fcf3ce44SJohn Forte  * destroy the fcip kmem cache
5892fcf3ce44SJohn Forte  */
5893fcf3ce44SJohn Forte static void
5894fcf3ce44SJohn Forte fcip_cache_destructor(void *buf, void *arg)
5895fcf3ce44SJohn Forte {
5896fcf3ce44SJohn Forte 	fcip_pkt_t		*fcip_pkt = (fcip_pkt_t *)buf;
5897fcf3ce44SJohn Forte 	fc_packet_t		*fc_pkt;
5898fcf3ce44SJohn Forte 	fcip_port_info_t	*fport = (fcip_port_info_t *)arg;
5899fcf3ce44SJohn Forte 	struct fcip		*fptr;
5900fcf3ce44SJohn Forte 
5901fcf3ce44SJohn Forte 	ASSERT(fport != NULL);
5902fcf3ce44SJohn Forte 
5903fcf3ce44SJohn Forte 	fptr = fport->fcipp_fcip;
5904fcf3ce44SJohn Forte 
5905fcf3ce44SJohn Forte 	ASSERT(fptr == fcip_pkt->fcip_pkt_fptr);
5906fcf3ce44SJohn Forte 	fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
5907fcf3ce44SJohn Forte 
5908fcf3ce44SJohn Forte 	if (fc_pkt->pkt_cmd_dma) {
5909fcf3ce44SJohn Forte 		ddi_dma_free_handle(&fc_pkt->pkt_cmd_dma);
5910fcf3ce44SJohn Forte 	}
5911fcf3ce44SJohn Forte }
5912fcf3ce44SJohn Forte 
5913fcf3ce44SJohn Forte /*
5914fcf3ce44SJohn Forte  * the fcip destination structure is hashed on Node WWN assuming
5915fcf3ce44SJohn Forte  * a  NAA_ID of 0x1 (IEEE)
5916fcf3ce44SJohn Forte  */
5917fcf3ce44SJohn Forte static struct fcip_dest *
5918fcf3ce44SJohn Forte fcip_get_dest(struct fcip *fptr, la_wwn_t *pwwn)
5919fcf3ce44SJohn Forte {
5920fcf3ce44SJohn Forte 	struct fcip_dest	*fdestp = NULL;
5921fcf3ce44SJohn Forte 	fcip_port_info_t	*fport;
5922fcf3ce44SJohn Forte 	int			hash_bucket;
5923fcf3ce44SJohn Forte 	opaque_t		pd;
5924fcf3ce44SJohn Forte 	int			rval;
5925fcf3ce44SJohn Forte 	struct fcip_routing_table *frp;
5926fcf3ce44SJohn Forte 	la_wwn_t		twwn;
5927fcf3ce44SJohn Forte 	uint32_t		*twwnp = (uint32_t *)&twwn;
5928fcf3ce44SJohn Forte 
5929fcf3ce44SJohn Forte 	hash_bucket = FCIP_DEST_HASH(pwwn->raw_wwn);
5930fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
5931fcf3ce44SJohn Forte 	    (CE_NOTE, "get dest hashbucket : 0x%x", hash_bucket));
5932fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
5933fcf3ce44SJohn Forte 	    (CE_NOTE, "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
5934fcf3ce44SJohn Forte 	    pwwn->raw_wwn[2], pwwn->raw_wwn[3], pwwn->raw_wwn[4],
5935fcf3ce44SJohn Forte 	    pwwn->raw_wwn[5], pwwn->raw_wwn[6], pwwn->raw_wwn[7]));
5936fcf3ce44SJohn Forte 
5937fcf3ce44SJohn Forte 	ASSERT(hash_bucket < FCIP_DEST_HASH_ELEMS);
5938fcf3ce44SJohn Forte 
5939fcf3ce44SJohn Forte 	if (fcip_check_port_exists(fptr)) {
5940fcf3ce44SJohn Forte 		/* fptr is stale, return fdestp */
5941fcf3ce44SJohn Forte 		return (fdestp);
5942fcf3ce44SJohn Forte 	}
5943fcf3ce44SJohn Forte 	fport = fptr->fcip_port_info;
5944fcf3ce44SJohn Forte 
5945fcf3ce44SJohn Forte 	/*
5946fcf3ce44SJohn Forte 	 * First check if we have active I/Os going on with the
5947fcf3ce44SJohn Forte 	 * destination port (an entry would exist in fcip_dest hash table)
5948fcf3ce44SJohn Forte 	 */
5949fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_dest_mutex);
5950fcf3ce44SJohn Forte 	fdestp = fptr->fcip_dest[hash_bucket];
5951fcf3ce44SJohn Forte 	while (fdestp != NULL) {
5952fcf3ce44SJohn Forte 		mutex_enter(&fdestp->fcipd_mutex);
5953fcf3ce44SJohn Forte 		if (fdestp->fcipd_rtable) {
5954fcf3ce44SJohn Forte 			if (fcip_wwn_compare(pwwn, &fdestp->fcipd_pwwn,
5955fcf3ce44SJohn Forte 			    FCIP_COMPARE_NWWN) == 0) {
5956fcf3ce44SJohn Forte 				FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
5957fcf3ce44SJohn Forte 				    (CE_NOTE, "found fdestp"));
5958fcf3ce44SJohn Forte 				mutex_exit(&fdestp->fcipd_mutex);
5959fcf3ce44SJohn Forte 				mutex_exit(&fptr->fcip_dest_mutex);
5960fcf3ce44SJohn Forte 				return (fdestp);
5961fcf3ce44SJohn Forte 			}
5962fcf3ce44SJohn Forte 		}
5963fcf3ce44SJohn Forte 		mutex_exit(&fdestp->fcipd_mutex);
5964fcf3ce44SJohn Forte 		fdestp = fdestp->fcipd_next;
5965fcf3ce44SJohn Forte 	}
5966fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_dest_mutex);
5967fcf3ce44SJohn Forte 
5968fcf3ce44SJohn Forte 	/*
5969fcf3ce44SJohn Forte 	 * We did not find the destination port information in our
5970fcf3ce44SJohn Forte 	 * active port list so search for an entry in our routing
5971fcf3ce44SJohn Forte 	 * table.
5972fcf3ce44SJohn Forte 	 */
5973fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_rt_mutex);
5974fcf3ce44SJohn Forte 	frp = fcip_lookup_rtable(fptr, pwwn, FCIP_COMPARE_NWWN);
5975fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_rt_mutex);
5976fcf3ce44SJohn Forte 
5977fcf3ce44SJohn Forte 	if (frp == NULL || (frp && (!FCIP_RTE_UNAVAIL(frp->fcipr_state)) &&
5978fcf3ce44SJohn Forte 	    frp->fcipr_state != PORT_DEVICE_LOGGED_IN) ||
5979fcf3ce44SJohn Forte 	    (frp && frp->fcipr_pd == NULL)) {
5980fcf3ce44SJohn Forte 		/*
5981fcf3ce44SJohn Forte 		 * No entry for the destination port in our routing
5982fcf3ce44SJohn Forte 		 * table too. First query the transport to see if it
5983fcf3ce44SJohn Forte 		 * already has structures for the destination port in
5984fcf3ce44SJohn Forte 		 * its hash tables. This must be done for all topologies
5985fcf3ce44SJohn Forte 		 * since we could have retired entries in the hash tables
5986fcf3ce44SJohn Forte 		 * which may have to be re-added without a statechange
5987fcf3ce44SJohn Forte 		 * callback happening. Its better to try and get an entry
5988fcf3ce44SJohn Forte 		 * for the destination port rather than simply failing a
5989fcf3ce44SJohn Forte 		 * request though it may be an overkill in private loop
5990fcf3ce44SJohn Forte 		 * topologies.
5991fcf3ce44SJohn Forte 		 * If a entry for the remote port exists in the transport's
5992fcf3ce44SJohn Forte 		 * hash tables, we are fine and can add the entry to our
5993fcf3ce44SJohn Forte 		 * routing and dest hash lists, Else for fabric configs we
5994fcf3ce44SJohn Forte 		 * query the nameserver if one exists or issue FARP ELS.
5995fcf3ce44SJohn Forte 		 */
5996fcf3ce44SJohn Forte 
5997fcf3ce44SJohn Forte 		/*
5998fcf3ce44SJohn Forte 		 * We need to do a PortName based Nameserver
5999fcf3ce44SJohn Forte 		 * query operation. So get the right PortWWN
6000fcf3ce44SJohn Forte 		 * for the adapter.
6001fcf3ce44SJohn Forte 		 */
6002fcf3ce44SJohn Forte 		bcopy(pwwn, &twwn, sizeof (la_wwn_t));
6003fcf3ce44SJohn Forte 
6004fcf3ce44SJohn Forte 		/*
6005fcf3ce44SJohn Forte 		 * Try IEEE Name (Format 1) first, this is the default and
6006fcf3ce44SJohn Forte 		 * Emulex uses this format.
6007fcf3ce44SJohn Forte 		 */
6008fcf3ce44SJohn Forte 		pd = fc_ulp_get_remote_port(fport->fcipp_handle,
6009fcf3ce44SJohn Forte 					    &twwn, &rval, 1);
6010fcf3ce44SJohn Forte 
6011fcf3ce44SJohn Forte 		if (rval != FC_SUCCESS) {
6012fcf3ce44SJohn Forte 			/*
6013fcf3ce44SJohn Forte 			 * If IEEE Name (Format 1) query failed, try IEEE
6014fcf3ce44SJohn Forte 			 * Extended Name (Format 2) which Qlogic uses.
6015fcf3ce44SJohn Forte 			 * And try port 1 on Qlogic FC-HBA first.
6016fcf3ce44SJohn Forte 			 * Note: On x86, we need to byte swap the 32-bit
6017fcf3ce44SJohn Forte 			 * word first, after the modification, swap it back.
6018fcf3ce44SJohn Forte 			 */
6019fcf3ce44SJohn Forte 			*twwnp = BE_32(*twwnp);
6020fcf3ce44SJohn Forte 			twwn.w.nport_id = QLC_PORT_1_ID_BITS;
6021fcf3ce44SJohn Forte 			twwn.w.naa_id = QLC_PORT_NAA;
6022fcf3ce44SJohn Forte 			*twwnp = BE_32(*twwnp);
6023fcf3ce44SJohn Forte 			pd = fc_ulp_get_remote_port(fport->fcipp_handle,
6024fcf3ce44SJohn Forte 						    &twwn, &rval, 1);
6025fcf3ce44SJohn Forte 		}
6026fcf3ce44SJohn Forte 
6027fcf3ce44SJohn Forte 		if (rval != FC_SUCCESS) {
6028fcf3ce44SJohn Forte 			/* If still failed, try port 2 on Qlogic FC-HBA. */
6029fcf3ce44SJohn Forte 			*twwnp = BE_32(*twwnp);
6030fcf3ce44SJohn Forte 			twwn.w.nport_id = QLC_PORT_2_ID_BITS;
6031fcf3ce44SJohn Forte 			*twwnp = BE_32(*twwnp);
6032fcf3ce44SJohn Forte 			pd = fc_ulp_get_remote_port(fport->fcipp_handle,
6033fcf3ce44SJohn Forte 						    &twwn, &rval, 1);
6034fcf3ce44SJohn Forte 		}
6035fcf3ce44SJohn Forte 
6036fcf3ce44SJohn Forte 		if (rval == FC_SUCCESS) {
6037fcf3ce44SJohn Forte 			fc_portmap_t	map;
6038fcf3ce44SJohn Forte 			/*
6039fcf3ce44SJohn Forte 			 * Add the newly found destination structure
6040fcf3ce44SJohn Forte 			 * to our routing table. Create a map with
6041fcf3ce44SJohn Forte 			 * the device we found. We could ask the
6042fcf3ce44SJohn Forte 			 * transport to give us the list of all
6043fcf3ce44SJohn Forte 			 * devices connected to our port but we
6044fcf3ce44SJohn Forte 			 * probably don't need to know all the devices
6045fcf3ce44SJohn Forte 			 * so let us just constuct a list with only
6046fcf3ce44SJohn Forte 			 * one device instead.
6047fcf3ce44SJohn Forte 			 */
6048fcf3ce44SJohn Forte 
6049fcf3ce44SJohn Forte 			fc_ulp_copy_portmap(&map, pd);
6050fcf3ce44SJohn Forte 			fcip_rt_update(fptr, &map, 1);
6051fcf3ce44SJohn Forte 
6052fcf3ce44SJohn Forte 			mutex_enter(&fptr->fcip_rt_mutex);
6053fcf3ce44SJohn Forte 			frp = fcip_lookup_rtable(fptr, pwwn,
6054fcf3ce44SJohn Forte 			    FCIP_COMPARE_NWWN);
6055fcf3ce44SJohn Forte 			mutex_exit(&fptr->fcip_rt_mutex);
6056fcf3ce44SJohn Forte 
6057fcf3ce44SJohn Forte 			fdestp = fcip_add_dest(fptr, frp);
6058fcf3ce44SJohn Forte 		} else if (fcip_farp_supported &&
6059fcf3ce44SJohn Forte 			(FC_TOP_EXTERNAL(fport->fcipp_topology) ||
6060fcf3ce44SJohn Forte 			(fport->fcipp_topology == FC_TOP_PT_PT))) {
6061fcf3ce44SJohn Forte 			/*
6062fcf3ce44SJohn Forte 			 * The Name server request failed so
6063fcf3ce44SJohn Forte 			 * issue an FARP
6064fcf3ce44SJohn Forte 			 */
6065fcf3ce44SJohn Forte 			fdestp = fcip_do_farp(fptr, pwwn, NULL,
6066fcf3ce44SJohn Forte 				0, 0);
6067fcf3ce44SJohn Forte 		} else {
6068fcf3ce44SJohn Forte 		    fdestp = NULL;
6069fcf3ce44SJohn Forte 		}
6070fcf3ce44SJohn Forte 	} else if (frp && frp->fcipr_state == PORT_DEVICE_LOGGED_IN) {
6071fcf3ce44SJohn Forte 		/*
6072fcf3ce44SJohn Forte 		 * Prepare a dest structure to return to caller
6073fcf3ce44SJohn Forte 		 */
6074fcf3ce44SJohn Forte 		fdestp = fcip_add_dest(fptr, frp);
6075fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
6076fcf3ce44SJohn Forte 		    (CE_NOTE, "in fcip get dest non fabric"));
6077fcf3ce44SJohn Forte 	}
6078fcf3ce44SJohn Forte 	return (fdestp);
6079fcf3ce44SJohn Forte }
6080fcf3ce44SJohn Forte 
6081fcf3ce44SJohn Forte 
6082fcf3ce44SJohn Forte /*
6083fcf3ce44SJohn Forte  * Endian clean WWN compare.
6084fcf3ce44SJohn Forte  * Returns 0 if they compare OK, else return non zero value.
6085fcf3ce44SJohn Forte  * flag can be bitwise OR of FCIP_COMPARE_NWWN, FCIP_COMPARE_PWWN,
6086fcf3ce44SJohn Forte  * FCIP_COMPARE_BROADCAST.
6087fcf3ce44SJohn Forte  */
6088fcf3ce44SJohn Forte static int
6089fcf3ce44SJohn Forte fcip_wwn_compare(la_wwn_t *wwn1, la_wwn_t *wwn2, int flag)
6090fcf3ce44SJohn Forte {
6091fcf3ce44SJohn Forte 	int rval = 0;
6092fcf3ce44SJohn Forte 	if ((wwn1->raw_wwn[2] != wwn2->raw_wwn[2]) ||
6093fcf3ce44SJohn Forte 	    (wwn1->raw_wwn[3] != wwn2->raw_wwn[3]) ||
6094fcf3ce44SJohn Forte 	    (wwn1->raw_wwn[4] != wwn2->raw_wwn[4]) ||
6095fcf3ce44SJohn Forte 	    (wwn1->raw_wwn[5] != wwn2->raw_wwn[5]) ||
6096fcf3ce44SJohn Forte 	    (wwn1->raw_wwn[6] != wwn2->raw_wwn[6]) ||
6097fcf3ce44SJohn Forte 	    (wwn1->raw_wwn[7] != wwn2->raw_wwn[7])) {
6098fcf3ce44SJohn Forte 		rval = 1;
6099fcf3ce44SJohn Forte 	} else if ((flag == FCIP_COMPARE_PWWN) &&
6100fcf3ce44SJohn Forte 	    (((wwn1->raw_wwn[0] & 0xf0) != (wwn2->raw_wwn[0] & 0xf0)) ||
6101fcf3ce44SJohn Forte 	    (wwn1->raw_wwn[1] != wwn2->raw_wwn[1]))) {
6102fcf3ce44SJohn Forte 		rval = 1;
6103fcf3ce44SJohn Forte 	}
6104fcf3ce44SJohn Forte 	return (rval);
6105fcf3ce44SJohn Forte }
6106fcf3ce44SJohn Forte 
6107fcf3ce44SJohn Forte 
6108fcf3ce44SJohn Forte /*
6109fcf3ce44SJohn Forte  * Add an entry for a remote port in the dest hash table. Dest hash table
6110fcf3ce44SJohn Forte  * has entries for ports in the routing hash table with which we decide
6111fcf3ce44SJohn Forte  * to establish IP communication with. The no. of entries in the dest hash
6112fcf3ce44SJohn Forte  * table must always be less than or equal to the entries in the routing
6113fcf3ce44SJohn Forte  * hash table. Every entry in the dest hash table ofcourse must have a
6114fcf3ce44SJohn Forte  * corresponding entry in the routing hash table
6115fcf3ce44SJohn Forte  */
6116fcf3ce44SJohn Forte static struct fcip_dest *
6117fcf3ce44SJohn Forte fcip_add_dest(struct fcip *fptr, struct fcip_routing_table *frp)
6118fcf3ce44SJohn Forte {
6119fcf3ce44SJohn Forte 	struct fcip_dest *fdestp = NULL;
6120fcf3ce44SJohn Forte 	la_wwn_t	*pwwn;
6121fcf3ce44SJohn Forte 	int hash_bucket;
6122fcf3ce44SJohn Forte 	struct fcip_dest *fdest_new;
6123fcf3ce44SJohn Forte 
6124fcf3ce44SJohn Forte 	if (frp == NULL) {
6125fcf3ce44SJohn Forte 		return (fdestp);
6126fcf3ce44SJohn Forte 	}
6127fcf3ce44SJohn Forte 
6128fcf3ce44SJohn Forte 	pwwn = &frp->fcipr_pwwn;
6129fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_dest_mutex);
6130fcf3ce44SJohn Forte 	hash_bucket = FCIP_DEST_HASH(pwwn->raw_wwn);
6131fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
6132fcf3ce44SJohn Forte 	    (CE_NOTE, "add dest hash_bucket: 0x%x", hash_bucket));
6133fcf3ce44SJohn Forte 
6134fcf3ce44SJohn Forte 	ASSERT(hash_bucket < FCIP_DEST_HASH_ELEMS);
6135fcf3ce44SJohn Forte 
6136fcf3ce44SJohn Forte 	fdestp = fptr->fcip_dest[hash_bucket];
6137fcf3ce44SJohn Forte 	while (fdestp != NULL) {
6138fcf3ce44SJohn Forte 		mutex_enter(&fdestp->fcipd_mutex);
6139fcf3ce44SJohn Forte 		if (fdestp->fcipd_rtable) {
6140fcf3ce44SJohn Forte 			if (fcip_wwn_compare(pwwn, &fdestp->fcipd_pwwn,
6141fcf3ce44SJohn Forte 			    FCIP_COMPARE_PWWN) == 0) {
6142fcf3ce44SJohn Forte 				mutex_exit(&fdestp->fcipd_mutex);
6143fcf3ce44SJohn Forte 				mutex_exit(&fptr->fcip_dest_mutex);
6144fcf3ce44SJohn Forte 				return (fdestp);
6145fcf3ce44SJohn Forte 			}
6146fcf3ce44SJohn Forte 		}
6147fcf3ce44SJohn Forte 		mutex_exit(&fdestp->fcipd_mutex);
6148fcf3ce44SJohn Forte 		fdestp = fdestp->fcipd_next;
6149fcf3ce44SJohn Forte 	}
6150fcf3ce44SJohn Forte 
6151fcf3ce44SJohn Forte 	ASSERT(fdestp == NULL);
6152fcf3ce44SJohn Forte 
6153fcf3ce44SJohn Forte 	fdest_new = (struct fcip_dest *)
6154fcf3ce44SJohn Forte 			kmem_zalloc(sizeof (struct fcip_dest), KM_SLEEP);
6155fcf3ce44SJohn Forte 
6156fcf3ce44SJohn Forte 	mutex_init(&fdest_new->fcipd_mutex, NULL, MUTEX_DRIVER, NULL);
6157fcf3ce44SJohn Forte 	fdest_new->fcipd_next = fptr->fcip_dest[hash_bucket];
6158fcf3ce44SJohn Forte 	fdest_new->fcipd_refcnt = 0;
6159fcf3ce44SJohn Forte 	fdest_new->fcipd_rtable = frp;
6160fcf3ce44SJohn Forte 	fdest_new->fcipd_ncmds = 0;
6161fcf3ce44SJohn Forte 	fptr->fcip_dest[hash_bucket] = fdest_new;
6162fcf3ce44SJohn Forte 	fdest_new->fcipd_flags = FCIP_PORT_NOTLOGGED;
6163fcf3ce44SJohn Forte 
6164fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_dest_mutex);
6165fcf3ce44SJohn Forte 	return (fdest_new);
6166fcf3ce44SJohn Forte }
6167fcf3ce44SJohn Forte 
6168fcf3ce44SJohn Forte /*
6169fcf3ce44SJohn Forte  * Cleanup the dest hash table and remove all entries
6170fcf3ce44SJohn Forte  */
6171fcf3ce44SJohn Forte static void
6172fcf3ce44SJohn Forte fcip_cleanup_dest(struct fcip *fptr)
6173fcf3ce44SJohn Forte {
6174fcf3ce44SJohn Forte 	struct fcip_dest *fdestp = NULL;
6175fcf3ce44SJohn Forte 	struct fcip_dest *fdest_delp = NULL;
6176fcf3ce44SJohn Forte 	int i;
6177fcf3ce44SJohn Forte 
6178fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_dest_mutex);
6179fcf3ce44SJohn Forte 
6180fcf3ce44SJohn Forte 	for (i = 0; i < FCIP_DEST_HASH_ELEMS; i++) {
6181fcf3ce44SJohn Forte 		fdestp = fptr->fcip_dest[i];
6182fcf3ce44SJohn Forte 		while (fdestp != NULL) {
6183fcf3ce44SJohn Forte 			mutex_destroy(&fdestp->fcipd_mutex);
6184fcf3ce44SJohn Forte 			fdest_delp = fdestp;
6185fcf3ce44SJohn Forte 			fdestp = fdestp->fcipd_next;
6186fcf3ce44SJohn Forte 			kmem_free(fdest_delp, sizeof (struct fcip_dest));
6187fcf3ce44SJohn Forte 			fptr->fcip_dest[i] = NULL;
6188fcf3ce44SJohn Forte 		}
6189fcf3ce44SJohn Forte 	}
6190fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_dest_mutex);
6191fcf3ce44SJohn Forte }
6192fcf3ce44SJohn Forte 
6193fcf3ce44SJohn Forte 
6194fcf3ce44SJohn Forte /*
6195fcf3ce44SJohn Forte  * Send FARP requests for Fabric ports when we don't have the port
6196fcf3ce44SJohn Forte  * we wish to talk to in our routing hash table. FARP is specially required
6197fcf3ce44SJohn Forte  * to talk to FC switches for inband switch management. Most FC switches
6198fcf3ce44SJohn Forte  * today have a switch FC IP address for IP over FC inband switch management
6199fcf3ce44SJohn Forte  * but the WWN and Port_ID for this traffic is not available through the
6200fcf3ce44SJohn Forte  * Nameservers since the switch themeselves are transparent.
6201fcf3ce44SJohn Forte  */
6202fcf3ce44SJohn Forte /* ARGSUSED */
6203fcf3ce44SJohn Forte static struct fcip_dest *
6204fcf3ce44SJohn Forte fcip_do_farp(struct fcip *fptr, la_wwn_t *pwwn, char *ip_addr,
6205fcf3ce44SJohn Forte     size_t ip_addr_len, int flags)
6206fcf3ce44SJohn Forte {
6207fcf3ce44SJohn Forte 	fcip_pkt_t		*fcip_pkt;
6208fcf3ce44SJohn Forte 	fc_packet_t		*fc_pkt;
6209fcf3ce44SJohn Forte 	fcip_port_info_t	*fport = fptr->fcip_port_info;
6210fcf3ce44SJohn Forte 	la_els_farp_t		farp_cmd;
6211fcf3ce44SJohn Forte 	la_els_farp_t		*fcmd;
6212fcf3ce44SJohn Forte 	struct fcip_dest	*fdestp = NULL;
6213fcf3ce44SJohn Forte 	int			rval;
6214fcf3ce44SJohn Forte 	clock_t			farp_lbolt;
6215fcf3ce44SJohn Forte 	la_wwn_t		broadcast_wwn;
6216fcf3ce44SJohn Forte 	struct fcip_dest	*bdestp;
6217fcf3ce44SJohn Forte 	struct fcip_routing_table 	*frp;
6218fcf3ce44SJohn Forte 
6219fcf3ce44SJohn Forte 	bdestp = fcip_get_dest(fptr, &broadcast_wwn);
6220fcf3ce44SJohn Forte 
6221fcf3ce44SJohn Forte 	if (bdestp == NULL) {
6222fcf3ce44SJohn Forte 		return (fdestp);
6223fcf3ce44SJohn Forte 	}
6224fcf3ce44SJohn Forte 
6225fcf3ce44SJohn Forte 	fcip_pkt = fcip_ipkt_alloc(fptr, sizeof (la_els_farp_t),
6226fcf3ce44SJohn Forte 	    sizeof (la_els_farp_t), bdestp->fcipd_pd, KM_SLEEP);
6227fcf3ce44SJohn Forte 
6228fcf3ce44SJohn Forte 	if (fcip_pkt == NULL) {
6229fcf3ce44SJohn Forte 		return (fdestp);
6230fcf3ce44SJohn Forte 	}
6231fcf3ce44SJohn Forte 
6232fcf3ce44SJohn Forte 	fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
6233fcf3ce44SJohn Forte 	ether_to_wwn(&fcip_arpbroadcast_addr, &broadcast_wwn);
6234fcf3ce44SJohn Forte 
6235fcf3ce44SJohn Forte 	mutex_enter(&bdestp->fcipd_mutex);
6236fcf3ce44SJohn Forte 	if (bdestp->fcipd_rtable == NULL) {
6237fcf3ce44SJohn Forte 		mutex_exit(&bdestp->fcipd_mutex);
6238fcf3ce44SJohn Forte 		fcip_ipkt_free(fcip_pkt);
6239fcf3ce44SJohn Forte 		return (fdestp);
6240fcf3ce44SJohn Forte 	}
6241fcf3ce44SJohn Forte 
6242fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_dest = bdestp;
6243fcf3ce44SJohn Forte 	fc_pkt->pkt_fca_device = bdestp->fcipd_fca_dev;
6244fcf3ce44SJohn Forte 
6245fcf3ce44SJohn Forte 	bdestp->fcipd_ncmds++;
6246fcf3ce44SJohn Forte 	mutex_exit(&bdestp->fcipd_mutex);
6247fcf3ce44SJohn Forte 
6248fcf3ce44SJohn Forte 	fcip_init_broadcast_pkt(fcip_pkt, NULL, 1);
6249fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_flags |= FCIP_PKT_IN_LIST;
6250fcf3ce44SJohn Forte 
6251fcf3ce44SJohn Forte 	/*
6252fcf3ce44SJohn Forte 	 * Now initialize the FARP payload itself
6253fcf3ce44SJohn Forte 	 */
6254fcf3ce44SJohn Forte 	fcmd = &farp_cmd;
6255fcf3ce44SJohn Forte 	fcmd->ls_code.ls_code = LA_ELS_FARP_REQ;
6256fcf3ce44SJohn Forte 	fcmd->ls_code.mbz = 0;
6257fcf3ce44SJohn Forte 	/*
6258fcf3ce44SJohn Forte 	 * for now just match the Port WWN since the other match addr
6259fcf3ce44SJohn Forte 	 * code points are optional. We can explore matching the IP address
6260fcf3ce44SJohn Forte 	 * if needed
6261fcf3ce44SJohn Forte 	 */
6262fcf3ce44SJohn Forte 	if (ip_addr) {
6263fcf3ce44SJohn Forte 		fcmd->match_addr = FARP_MATCH_WW_PN_IPv4;
6264fcf3ce44SJohn Forte 	} else {
6265fcf3ce44SJohn Forte 		fcmd->match_addr = FARP_MATCH_WW_PN;
6266fcf3ce44SJohn Forte 	}
6267fcf3ce44SJohn Forte 
6268fcf3ce44SJohn Forte 	/*
6269fcf3ce44SJohn Forte 	 * Request the responder port to log into us - that way
6270fcf3ce44SJohn Forte 	 * the Transport is aware of the remote port when we create
6271fcf3ce44SJohn Forte 	 * an entry for it in our tables
6272fcf3ce44SJohn Forte 	 */
6273fcf3ce44SJohn Forte 	fcmd->resp_flags = FARP_INIT_REPLY | FARP_INIT_P_LOGI;
6274fcf3ce44SJohn Forte 	fcmd->req_id = fport->fcipp_sid;
6275fcf3ce44SJohn Forte 	fcmd->dest_id.port_id = fc_pkt->pkt_cmd_fhdr.d_id;
6276fcf3ce44SJohn Forte 	bcopy(&fport->fcipp_pwwn, &fcmd->req_pwwn, sizeof (la_wwn_t));
6277fcf3ce44SJohn Forte 	bcopy(&fport->fcipp_nwwn, &fcmd->req_nwwn, sizeof (la_wwn_t));
6278fcf3ce44SJohn Forte 	bcopy(pwwn, &fcmd->resp_pwwn, sizeof (la_wwn_t));
6279fcf3ce44SJohn Forte 	/*
6280fcf3ce44SJohn Forte 	 * copy in source IP address if we get to know it
6281fcf3ce44SJohn Forte 	 */
6282fcf3ce44SJohn Forte 	if (ip_addr) {
6283fcf3ce44SJohn Forte 		bcopy(ip_addr, fcmd->resp_ip, ip_addr_len);
6284fcf3ce44SJohn Forte 	}
6285fcf3ce44SJohn Forte 
6286fcf3ce44SJohn Forte 	fc_pkt->pkt_cmdlen = sizeof (la_els_farp_t);
6287fcf3ce44SJohn Forte 	fc_pkt->pkt_rsplen = sizeof (la_els_farp_t);
6288fcf3ce44SJohn Forte 	fc_pkt->pkt_tran_type = FC_PKT_EXCHANGE;
6289fcf3ce44SJohn Forte 	fc_pkt->pkt_ulp_private = (opaque_t)fcip_pkt;
6290fcf3ce44SJohn Forte 
6291fcf3ce44SJohn Forte 	/*
6292fcf3ce44SJohn Forte 	 * Endian safe copy
6293fcf3ce44SJohn Forte 	 */
6294fcf3ce44SJohn Forte 	FCIP_CP_OUT(fcmd, fc_pkt->pkt_cmd, fc_pkt->pkt_cmd_acc,
6295fcf3ce44SJohn Forte 	    sizeof (la_els_farp_t));
6296fcf3ce44SJohn Forte 
6297fcf3ce44SJohn Forte 	/*
6298fcf3ce44SJohn Forte 	 * send the packet in polled mode.
6299fcf3ce44SJohn Forte 	 */
6300fcf3ce44SJohn Forte 	rval = fc_ulp_issue_els(fport->fcipp_handle, fc_pkt);
6301fcf3ce44SJohn Forte 	if (rval != FC_SUCCESS) {
6302fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM, (CE_WARN,
6303fcf3ce44SJohn Forte 		    "fcip_transport of farp pkt failed 0x%x", rval));
6304fcf3ce44SJohn Forte 		fcip_pkt->fcip_pkt_flags &= ~FCIP_PKT_IN_LIST;
6305fcf3ce44SJohn Forte 		fcip_ipkt_free(fcip_pkt);
6306fcf3ce44SJohn Forte 
6307fcf3ce44SJohn Forte 		mutex_enter(&bdestp->fcipd_mutex);
6308fcf3ce44SJohn Forte 		bdestp->fcipd_ncmds--;
6309fcf3ce44SJohn Forte 		mutex_exit(&bdestp->fcipd_mutex);
6310fcf3ce44SJohn Forte 
6311fcf3ce44SJohn Forte 		return (fdestp);
6312fcf3ce44SJohn Forte 	}
6313fcf3ce44SJohn Forte 
6314fcf3ce44SJohn Forte 	farp_lbolt = ddi_get_lbolt();
6315fcf3ce44SJohn Forte 	farp_lbolt += drv_usectohz(FCIP_FARP_TIMEOUT);
6316fcf3ce44SJohn Forte 
6317fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_mutex);
6318fcf3ce44SJohn Forte 	fptr->fcip_farp_rsp_flag = 0;
6319fcf3ce44SJohn Forte 	while (!fptr->fcip_farp_rsp_flag) {
6320fcf3ce44SJohn Forte 		if (cv_timedwait(&fptr->fcip_farp_cv, &fptr->fcip_mutex,
6321fcf3ce44SJohn Forte 		    farp_lbolt) == -1) {
6322fcf3ce44SJohn Forte 			/*
6323fcf3ce44SJohn Forte 			 * No FARP response from any destination port
6324fcf3ce44SJohn Forte 			 * so bail out.
6325fcf3ce44SJohn Forte 			 */
6326fcf3ce44SJohn Forte 			fptr->fcip_farp_rsp_flag = 1;
6327fcf3ce44SJohn Forte 		} else {
6328fcf3ce44SJohn Forte 			/*
6329fcf3ce44SJohn Forte 			 * We received a FARP response - check to see if the
6330fcf3ce44SJohn Forte 			 * response was in reply to our FARP request.
6331fcf3ce44SJohn Forte 			 */
6332fcf3ce44SJohn Forte 
6333fcf3ce44SJohn Forte 			mutex_enter(&fptr->fcip_rt_mutex);
6334fcf3ce44SJohn Forte 			frp = fcip_lookup_rtable(fptr, pwwn, FCIP_COMPARE_NWWN);
6335fcf3ce44SJohn Forte 			mutex_exit(&fptr->fcip_rt_mutex);
6336fcf3ce44SJohn Forte 
6337fcf3ce44SJohn Forte 			if ((frp != NULL) &&
6338fcf3ce44SJohn Forte 			    !FCIP_RTE_UNAVAIL(frp->fcipr_state)) {
6339fcf3ce44SJohn Forte 				fdestp = fcip_get_dest(fptr, pwwn);
6340fcf3ce44SJohn Forte 			} else {
6341fcf3ce44SJohn Forte 				/*
6342fcf3ce44SJohn Forte 				 * Not our FARP response so go back and wait
6343fcf3ce44SJohn Forte 				 * again till FARP_TIMEOUT expires
6344fcf3ce44SJohn Forte 				 */
6345fcf3ce44SJohn Forte 				fptr->fcip_farp_rsp_flag = 0;
6346fcf3ce44SJohn Forte 			}
6347fcf3ce44SJohn Forte 		}
6348fcf3ce44SJohn Forte 	}
6349fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_mutex);
6350fcf3ce44SJohn Forte 
6351fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_flags |= FCIP_PKT_IN_LIST;
6352fcf3ce44SJohn Forte 	fcip_ipkt_free(fcip_pkt);
6353fcf3ce44SJohn Forte 	mutex_enter(&bdestp->fcipd_mutex);
6354fcf3ce44SJohn Forte 	bdestp->fcipd_ncmds--;
6355fcf3ce44SJohn Forte 	mutex_exit(&bdestp->fcipd_mutex);
6356fcf3ce44SJohn Forte 	return (fdestp);
6357fcf3ce44SJohn Forte }
6358fcf3ce44SJohn Forte 
6359fcf3ce44SJohn Forte 
6360fcf3ce44SJohn Forte 
6361fcf3ce44SJohn Forte /*
6362fcf3ce44SJohn Forte  * Helper routine to PLOGI to a remote port we wish to talk to.
6363fcf3ce44SJohn Forte  * This may not be required since the port driver does logins anyway,
6364fcf3ce44SJohn Forte  * but this can be required in fabric cases since FARP requests/responses
6365fcf3ce44SJohn Forte  * don't require you to be logged in?
6366fcf3ce44SJohn Forte  */
6367fcf3ce44SJohn Forte 
6368fcf3ce44SJohn Forte /* ARGSUSED */
6369fcf3ce44SJohn Forte static int
6370fcf3ce44SJohn Forte fcip_do_plogi(struct fcip *fptr, struct fcip_routing_table *frp)
6371fcf3ce44SJohn Forte {
6372fcf3ce44SJohn Forte 	fcip_pkt_t		*fcip_pkt;
6373fcf3ce44SJohn Forte 	fc_packet_t		*fc_pkt;
6374fcf3ce44SJohn Forte 	fcip_port_info_t	*fport = fptr->fcip_port_info;
6375fcf3ce44SJohn Forte 	la_els_logi_t		logi;
6376fcf3ce44SJohn Forte 	int			rval;
6377fcf3ce44SJohn Forte 	fc_frame_hdr_t		*fr_hdr;
6378fcf3ce44SJohn Forte 
6379fcf3ce44SJohn Forte 	/*
6380fcf3ce44SJohn Forte 	 * Don't bother to login for broadcast RTE entries
6381fcf3ce44SJohn Forte 	 */
6382fcf3ce44SJohn Forte 	if ((frp->fcipr_d_id.port_id == 0x0) ||
6383fcf3ce44SJohn Forte 	    (frp->fcipr_d_id.port_id == 0xffffff)) {
6384fcf3ce44SJohn Forte 		return (FC_FAILURE);
6385fcf3ce44SJohn Forte 	}
6386fcf3ce44SJohn Forte 
6387fcf3ce44SJohn Forte 	/*
6388fcf3ce44SJohn Forte 	 * We shouldn't pound in too many logins here
6389fcf3ce44SJohn Forte 	 *
6390fcf3ce44SJohn Forte 	 */
6391fcf3ce44SJohn Forte 	if (frp->fcipr_state == FCIP_RT_LOGIN_PROGRESS ||
6392fcf3ce44SJohn Forte 	    frp->fcipr_state == PORT_DEVICE_LOGGED_IN) {
6393fcf3ce44SJohn Forte 		return (FC_SUCCESS);
6394fcf3ce44SJohn Forte 	}
6395fcf3ce44SJohn Forte 
6396fcf3ce44SJohn Forte 	fcip_pkt = fcip_ipkt_alloc(fptr, sizeof (la_els_logi_t),
6397fcf3ce44SJohn Forte 	    sizeof (la_els_logi_t), frp->fcipr_pd, KM_SLEEP);
6398fcf3ce44SJohn Forte 
6399fcf3ce44SJohn Forte 	if (fcip_pkt == NULL) {
6400fcf3ce44SJohn Forte 		return (FC_FAILURE);
6401fcf3ce44SJohn Forte 	}
6402fcf3ce44SJohn Forte 
6403fcf3ce44SJohn Forte 	/*
6404fcf3ce44SJohn Forte 	 * Update back pointer for login state update
6405fcf3ce44SJohn Forte 	 */
6406fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_frp = frp;
6407fcf3ce44SJohn Forte 	frp->fcipr_state = FCIP_RT_LOGIN_PROGRESS;
6408fcf3ce44SJohn Forte 
6409fcf3ce44SJohn Forte 	fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
6410fcf3ce44SJohn Forte 
6411fcf3ce44SJohn Forte 	/*
6412fcf3ce44SJohn Forte 	 * Initialize frame header for ELS
6413fcf3ce44SJohn Forte 	 */
6414fcf3ce44SJohn Forte 	fr_hdr = &fc_pkt->pkt_cmd_fhdr;
6415fcf3ce44SJohn Forte 	fr_hdr->r_ctl = R_CTL_ELS_REQ;
6416fcf3ce44SJohn Forte 	fr_hdr->type = FC_TYPE_EXTENDED_LS;
6417fcf3ce44SJohn Forte 	fr_hdr->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
6418fcf3ce44SJohn Forte 	fr_hdr->df_ctl = 0;
6419fcf3ce44SJohn Forte 	fr_hdr->s_id = fport->fcipp_sid.port_id;
6420fcf3ce44SJohn Forte 	fr_hdr->d_id = frp->fcipr_d_id.port_id;
6421fcf3ce44SJohn Forte 	fr_hdr->seq_cnt = 0;
6422fcf3ce44SJohn Forte 	fr_hdr->ox_id = 0xffff;
6423fcf3ce44SJohn Forte 	fr_hdr->rx_id = 0xffff;
6424fcf3ce44SJohn Forte 	fr_hdr->ro = 0;
6425fcf3ce44SJohn Forte 
6426fcf3ce44SJohn Forte 	fc_pkt->pkt_rsplen = sizeof (la_els_logi_t);
6427fcf3ce44SJohn Forte 	fc_pkt->pkt_comp = fcip_ipkt_callback;
6428fcf3ce44SJohn Forte 	fc_pkt->pkt_tran_type = FC_PKT_EXCHANGE;
6429fcf3ce44SJohn Forte 	fc_pkt->pkt_timeout = 10;	/* 10 seconds */
6430fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_ttl = fptr->fcip_timeout_ticks + fc_pkt->pkt_timeout;
6431fcf3ce44SJohn Forte 	fc_pkt->pkt_ulp_private = (opaque_t)fcip_pkt;
6432fcf3ce44SJohn Forte 
6433fcf3ce44SJohn Forte 	/*
6434fcf3ce44SJohn Forte 	 * Everybody does class 3, so let's just set it.  If the transport
6435fcf3ce44SJohn Forte 	 * knows better, it will deal with the class appropriately.
6436fcf3ce44SJohn Forte 	 */
6437fcf3ce44SJohn Forte 
6438fcf3ce44SJohn Forte 	fc_pkt->pkt_tran_flags = FC_TRAN_INTR | FC_TRAN_CLASS3;
6439fcf3ce44SJohn Forte 
6440fcf3ce44SJohn Forte 	/*
6441fcf3ce44SJohn Forte 	 * we need only fill in the ls_code and the cmd frame header
6442fcf3ce44SJohn Forte 	 */
6443fcf3ce44SJohn Forte 	bzero((void *)&logi, sizeof (la_els_logi_t));
6444fcf3ce44SJohn Forte 	logi.ls_code.ls_code = LA_ELS_PLOGI;
6445fcf3ce44SJohn Forte 	logi.ls_code.mbz = 0;
6446fcf3ce44SJohn Forte 
6447fcf3ce44SJohn Forte 	FCIP_CP_OUT((uint8_t *)&logi, fc_pkt->pkt_cmd, fc_pkt->pkt_cmd_acc,
6448fcf3ce44SJohn Forte 	    sizeof (la_els_logi_t));
6449fcf3ce44SJohn Forte 
6450fcf3ce44SJohn Forte 	rval = fc_ulp_login(fport->fcipp_handle, &fc_pkt, 1);
6451fcf3ce44SJohn Forte 	if (rval != FC_SUCCESS) {
6452fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
6453fcf3ce44SJohn Forte 		    "!fc_ulp_login failed for d_id: 0x%x, rval: 0x%x",
6454fcf3ce44SJohn Forte 		    frp->fcipr_d_id.port_id, rval);
6455fcf3ce44SJohn Forte 		fcip_ipkt_free(fcip_pkt);
6456fcf3ce44SJohn Forte 	}
6457fcf3ce44SJohn Forte 	return (rval);
6458fcf3ce44SJohn Forte }
6459fcf3ce44SJohn Forte 
6460fcf3ce44SJohn Forte /*
6461fcf3ce44SJohn Forte  * The packet callback routine - called from the transport/FCA after
6462fcf3ce44SJohn Forte  * it is done DMA'ing/sending out the packet contents on the wire so
6463fcf3ce44SJohn Forte  * that the alloc'ed packet can be freed
6464fcf3ce44SJohn Forte  */
6465fcf3ce44SJohn Forte static void
6466fcf3ce44SJohn Forte fcip_ipkt_callback(fc_packet_t *fc_pkt)
6467fcf3ce44SJohn Forte {
6468fcf3ce44SJohn Forte 	ls_code_t			logi_req;
6469fcf3ce44SJohn Forte 	ls_code_t			logi_resp;
6470fcf3ce44SJohn Forte 	fcip_pkt_t			*fcip_pkt;
6471fcf3ce44SJohn Forte 	fc_frame_hdr_t			*fr_hdr;
6472fcf3ce44SJohn Forte 	struct fcip 			*fptr;
6473fcf3ce44SJohn Forte 	fcip_port_info_t		*fport;
6474fcf3ce44SJohn Forte 	struct fcip_routing_table	*frp;
6475fcf3ce44SJohn Forte 
6476fcf3ce44SJohn Forte 	fr_hdr = &fc_pkt->pkt_cmd_fhdr;
6477fcf3ce44SJohn Forte 
6478fcf3ce44SJohn Forte 	FCIP_CP_IN(fc_pkt->pkt_resp, (uint8_t *)&logi_resp,
6479fcf3ce44SJohn Forte 	    fc_pkt->pkt_resp_acc, sizeof (logi_resp));
6480fcf3ce44SJohn Forte 
6481fcf3ce44SJohn Forte 	FCIP_CP_IN(fc_pkt->pkt_cmd, (uint8_t *)&logi_req, fc_pkt->pkt_cmd_acc,
6482fcf3ce44SJohn Forte 	    sizeof (logi_req));
6483fcf3ce44SJohn Forte 
6484fcf3ce44SJohn Forte 	fcip_pkt = (fcip_pkt_t *)fc_pkt->pkt_ulp_private;
6485fcf3ce44SJohn Forte 	frp = fcip_pkt->fcip_pkt_frp;
6486fcf3ce44SJohn Forte 	fptr = fcip_pkt->fcip_pkt_fptr;
6487fcf3ce44SJohn Forte 	fport = fptr->fcip_port_info;
6488fcf3ce44SJohn Forte 
6489fcf3ce44SJohn Forte 	ASSERT(logi_req.ls_code == LA_ELS_PLOGI);
6490fcf3ce44SJohn Forte 
6491fcf3ce44SJohn Forte 	if (fc_pkt->pkt_state != FC_PKT_SUCCESS ||
6492fcf3ce44SJohn Forte 	    logi_resp.ls_code != LA_ELS_ACC) {
6493fcf3ce44SJohn Forte 		/* EMPTY */
6494fcf3ce44SJohn Forte 
6495fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM, (CE_WARN,
6496fcf3ce44SJohn Forte 		    "opcode : 0x%x to d_id: 0x%x failed",
6497fcf3ce44SJohn Forte 		    logi_req.ls_code, fr_hdr->d_id));
6498fcf3ce44SJohn Forte 
6499fcf3ce44SJohn Forte 		mutex_enter(&fptr->fcip_rt_mutex);
6500fcf3ce44SJohn Forte 		frp->fcipr_state = PORT_DEVICE_INVALID;
6501fcf3ce44SJohn Forte 		frp->fcipr_invalid_timeout = fptr->fcip_timeout_ticks +
6502fcf3ce44SJohn Forte 		    (FCIP_RTE_TIMEOUT / 2);
6503fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_rt_mutex);
6504fcf3ce44SJohn Forte 	} else {
6505fcf3ce44SJohn Forte 		fc_portid_t	d_id;
6506fcf3ce44SJohn Forte 
6507fcf3ce44SJohn Forte 		d_id.port_id = fr_hdr->d_id;
6508fcf3ce44SJohn Forte 		d_id.priv_lilp_posit = 0;
6509fcf3ce44SJohn Forte 
6510fcf3ce44SJohn Forte 		/*
6511fcf3ce44SJohn Forte 		 * Update PLOGI results; FCA Handle, and Port device handles
6512fcf3ce44SJohn Forte 		 */
6513fcf3ce44SJohn Forte 		mutex_enter(&fptr->fcip_rt_mutex);
6514fcf3ce44SJohn Forte 		frp->fcipr_pd = fc_pkt->pkt_pd;
6515fcf3ce44SJohn Forte 		frp->fcipr_fca_dev =
6516fcf3ce44SJohn Forte 		    fc_ulp_get_fca_device(fport->fcipp_handle, d_id);
6517fcf3ce44SJohn Forte 		frp->fcipr_state = PORT_DEVICE_LOGGED_IN;
6518fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_rt_mutex);
6519fcf3ce44SJohn Forte 	}
6520fcf3ce44SJohn Forte 
6521fcf3ce44SJohn Forte 	fcip_ipkt_free(fcip_pkt);
6522fcf3ce44SJohn Forte }
6523fcf3ce44SJohn Forte 
6524fcf3ce44SJohn Forte 
6525fcf3ce44SJohn Forte /*
6526fcf3ce44SJohn Forte  * pkt_alloc routine for outbound IP datagrams. The cache constructor
6527fcf3ce44SJohn Forte  * Only initializes the pkt_cmd_dma (which is where the outbound datagram
6528fcf3ce44SJohn Forte  * is stuffed) since we don't expect response
6529fcf3ce44SJohn Forte  */
6530fcf3ce44SJohn Forte static fcip_pkt_t *
6531fcf3ce44SJohn Forte fcip_pkt_alloc(struct fcip *fptr, mblk_t *bp, int flags, int datalen)
6532fcf3ce44SJohn Forte {
6533fcf3ce44SJohn Forte 	fcip_pkt_t 	*fcip_pkt;
6534fcf3ce44SJohn Forte 	fc_packet_t	*fc_pkt;
6535fcf3ce44SJohn Forte 	ddi_dma_cookie_t	pkt_cookie;
6536fcf3ce44SJohn Forte 	ddi_dma_cookie_t	*cp;
6537fcf3ce44SJohn Forte 	uint32_t		cnt;
6538fcf3ce44SJohn Forte 	fcip_port_info_t	*fport = fptr->fcip_port_info;
6539fcf3ce44SJohn Forte 
6540fcf3ce44SJohn Forte 	fcip_pkt = kmem_cache_alloc(fptr->fcip_xmit_cache, flags);
6541fcf3ce44SJohn Forte 	if (fcip_pkt == NULL) {
6542fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM, (CE_WARN,
6543fcf3ce44SJohn Forte 		    "fcip_pkt_alloc: kmem_cache_alloc failed"));
6544fcf3ce44SJohn Forte 		return (NULL);
6545fcf3ce44SJohn Forte 	}
6546fcf3ce44SJohn Forte 
6547fcf3ce44SJohn Forte 	fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
6548fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_fcpktp = fc_pkt;
6549fcf3ce44SJohn Forte 	fc_pkt->pkt_tran_flags = 0;
6550fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_dma_flags = 0;
6551fcf3ce44SJohn Forte 
6552fcf3ce44SJohn Forte 	/*
6553fcf3ce44SJohn Forte 	 * the cache constructor has allocated the dma handle
6554fcf3ce44SJohn Forte 	 */
6555fcf3ce44SJohn Forte 	fc_pkt->pkt_cmd = (caddr_t)bp->b_rptr;
6556fcf3ce44SJohn Forte 	if (ddi_dma_addr_bind_handle(fc_pkt->pkt_cmd_dma, NULL,
6557fcf3ce44SJohn Forte 	    (caddr_t)bp->b_rptr, datalen, DDI_DMA_WRITE | DDI_DMA_CONSISTENT,
6558fcf3ce44SJohn Forte 	    DDI_DMA_DONTWAIT, NULL, &pkt_cookie,
6559fcf3ce44SJohn Forte 	    &fc_pkt->pkt_cmd_cookie_cnt) != DDI_DMA_MAPPED) {
6560fcf3ce44SJohn Forte 			goto fail;
6561fcf3ce44SJohn Forte 	}
6562fcf3ce44SJohn Forte 
6563fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_dma_flags |= FCIP_CMD_DMA_BOUND;
6564fcf3ce44SJohn Forte 
6565fcf3ce44SJohn Forte 	if (fc_pkt->pkt_cmd_cookie_cnt >
6566fcf3ce44SJohn Forte 	    fport->fcipp_cmd_dma_attr.dma_attr_sgllen) {
6567fcf3ce44SJohn Forte 		goto fail;
6568fcf3ce44SJohn Forte 	}
6569fcf3ce44SJohn Forte 
6570fcf3ce44SJohn Forte 	ASSERT(fc_pkt->pkt_cmd_cookie_cnt != 0);
6571fcf3ce44SJohn Forte 
6572fcf3ce44SJohn Forte 	cp = fc_pkt->pkt_cmd_cookie = (ddi_dma_cookie_t *)kmem_alloc(
6573fcf3ce44SJohn Forte 	    fc_pkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie),
6574fcf3ce44SJohn Forte 	    KM_NOSLEEP);
6575fcf3ce44SJohn Forte 
6576fcf3ce44SJohn Forte 	if (cp == NULL) {
6577fcf3ce44SJohn Forte 		goto fail;
6578fcf3ce44SJohn Forte 	}
6579fcf3ce44SJohn Forte 
6580fcf3ce44SJohn Forte 	*cp = pkt_cookie;
6581fcf3ce44SJohn Forte 	cp++;
6582fcf3ce44SJohn Forte 	for (cnt = 1; cnt < fc_pkt->pkt_cmd_cookie_cnt; cnt++, cp++) {
6583fcf3ce44SJohn Forte 		ddi_dma_nextcookie(fc_pkt->pkt_cmd_dma, &pkt_cookie);
6584fcf3ce44SJohn Forte 		*cp = pkt_cookie;
6585fcf3ce44SJohn Forte 	}
6586fcf3ce44SJohn Forte 
6587fcf3ce44SJohn Forte 	fc_pkt->pkt_cmdlen = datalen;
6588fcf3ce44SJohn Forte 
6589fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_mp = NULL;
6590fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_wq = NULL;
6591fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_dest = NULL;
6592fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_next = NULL;
6593fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_prev = NULL;
6594fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_state = 0;
6595fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_reason = 0;
6596fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_flags = 0;
6597fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_frp = NULL;
6598fcf3ce44SJohn Forte 
6599fcf3ce44SJohn Forte 	return (fcip_pkt);
6600fcf3ce44SJohn Forte fail:
6601fcf3ce44SJohn Forte 	if (fcip_pkt) {
6602fcf3ce44SJohn Forte 		fcip_pkt_free(fcip_pkt, 0);
6603fcf3ce44SJohn Forte 	}
6604fcf3ce44SJohn Forte 	return ((fcip_pkt_t *)0);
6605fcf3ce44SJohn Forte }
6606fcf3ce44SJohn Forte 
6607fcf3ce44SJohn Forte /*
6608fcf3ce44SJohn Forte  * Free a packet and all its associated resources
6609fcf3ce44SJohn Forte  */
6610fcf3ce44SJohn Forte static void
6611fcf3ce44SJohn Forte fcip_pkt_free(struct fcip_pkt *fcip_pkt, int free_mblk)
6612fcf3ce44SJohn Forte {
6613fcf3ce44SJohn Forte 	fc_packet_t	*fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
6614fcf3ce44SJohn Forte 	struct fcip *fptr = fcip_pkt->fcip_pkt_fptr;
6615fcf3ce44SJohn Forte 
6616fcf3ce44SJohn Forte 	if (fc_pkt->pkt_cmd_cookie != NULL) {
6617fcf3ce44SJohn Forte 		kmem_free(fc_pkt->pkt_cmd_cookie, fc_pkt->pkt_cmd_cookie_cnt *
6618fcf3ce44SJohn Forte 		    sizeof (ddi_dma_cookie_t));
6619fcf3ce44SJohn Forte 		fc_pkt->pkt_cmd_cookie = NULL;
6620fcf3ce44SJohn Forte 	}
6621fcf3ce44SJohn Forte 
6622fcf3ce44SJohn Forte 	fcip_free_pkt_dma(fcip_pkt);
6623fcf3ce44SJohn Forte 	if (free_mblk && fcip_pkt->fcip_pkt_mp) {
6624fcf3ce44SJohn Forte 		freemsg(fcip_pkt->fcip_pkt_mp);
6625fcf3ce44SJohn Forte 		fcip_pkt->fcip_pkt_mp = NULL;
6626fcf3ce44SJohn Forte 	}
6627fcf3ce44SJohn Forte 
6628fcf3ce44SJohn Forte 	(void) fc_ulp_uninit_packet(fptr->fcip_port_info->fcipp_handle, fc_pkt);
6629fcf3ce44SJohn Forte 
6630fcf3ce44SJohn Forte 	kmem_cache_free(fptr->fcip_xmit_cache, (void *)fcip_pkt);
6631fcf3ce44SJohn Forte }
6632fcf3ce44SJohn Forte 
6633fcf3ce44SJohn Forte /*
6634fcf3ce44SJohn Forte  * Allocate a Packet for internal driver use. This is for requests
6635fcf3ce44SJohn Forte  * that originate from within the driver
6636fcf3ce44SJohn Forte  */
6637fcf3ce44SJohn Forte static fcip_pkt_t *
6638fcf3ce44SJohn Forte fcip_ipkt_alloc(struct fcip *fptr, int cmdlen, int resplen,
6639fcf3ce44SJohn Forte     opaque_t pd, int flags)
6640fcf3ce44SJohn Forte {
6641fcf3ce44SJohn Forte 	fcip_pkt_t 		*fcip_pkt;
6642fcf3ce44SJohn Forte 	fc_packet_t		*fc_pkt;
6643fcf3ce44SJohn Forte 	int			(*cb)(caddr_t);
6644fcf3ce44SJohn Forte 	fcip_port_info_t	*fport = fptr->fcip_port_info;
6645fcf3ce44SJohn Forte 	size_t			real_len;
6646fcf3ce44SJohn Forte 	uint_t			held_here = 0;
6647fcf3ce44SJohn Forte 	ddi_dma_cookie_t	pkt_cookie;
6648fcf3ce44SJohn Forte 	ddi_dma_cookie_t	*cp;
6649fcf3ce44SJohn Forte 	uint32_t		cnt;
6650fcf3ce44SJohn Forte 
6651fcf3ce44SJohn Forte 	cb = (flags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT;
6652fcf3ce44SJohn Forte 
6653fcf3ce44SJohn Forte 	fcip_pkt = kmem_zalloc((sizeof (fcip_pkt_t) +
6654fcf3ce44SJohn Forte 	    fport->fcipp_fca_pkt_size), flags);
6655fcf3ce44SJohn Forte 
6656fcf3ce44SJohn Forte 	if (fcip_pkt == NULL) {
6657fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
6658fcf3ce44SJohn Forte 		    (CE_WARN, "pkt alloc of ineternal pkt failed"));
6659fcf3ce44SJohn Forte 		goto fail;
6660fcf3ce44SJohn Forte 	}
6661fcf3ce44SJohn Forte 
6662fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_flags = FCIP_PKT_INTERNAL;
6663fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_fptr = fptr;
6664fcf3ce44SJohn Forte 	fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
6665fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_fcpktp = fc_pkt;
6666fcf3ce44SJohn Forte 	fc_pkt->pkt_tran_flags = 0;
6667fcf3ce44SJohn Forte 	fc_pkt->pkt_cmdlen = 0;
6668fcf3ce44SJohn Forte 	fc_pkt->pkt_rsplen = 0;
6669fcf3ce44SJohn Forte 	fc_pkt->pkt_datalen = 0;
6670fcf3ce44SJohn Forte 	fc_pkt->pkt_fca_private = (opaque_t)((caddr_t)fcip_pkt +
6671fcf3ce44SJohn Forte 	    sizeof (fcip_pkt_t));
6672fcf3ce44SJohn Forte 	fc_pkt->pkt_ulp_private = (opaque_t)fcip_pkt;
6673fcf3ce44SJohn Forte 
6674fcf3ce44SJohn Forte 	if (cmdlen) {
6675fcf3ce44SJohn Forte 		if (ddi_dma_alloc_handle(fptr->fcip_dip,
6676fcf3ce44SJohn Forte 		    &fport->fcipp_cmd_dma_attr, cb, NULL,
6677fcf3ce44SJohn Forte 		    &fc_pkt->pkt_cmd_dma) != DDI_SUCCESS) {
6678fcf3ce44SJohn Forte 			goto fail;
6679fcf3ce44SJohn Forte 		}
6680fcf3ce44SJohn Forte 
6681fcf3ce44SJohn Forte 		if (ddi_dma_mem_alloc(fc_pkt->pkt_cmd_dma, cmdlen,
6682fcf3ce44SJohn Forte 		    &fport->fcipp_fca_acc_attr, DDI_DMA_CONSISTENT,
6683fcf3ce44SJohn Forte 		    cb, NULL, (caddr_t *)&fc_pkt->pkt_cmd,
6684fcf3ce44SJohn Forte 		    &real_len, &fc_pkt->pkt_cmd_acc) != DDI_SUCCESS) {
6685fcf3ce44SJohn Forte 			goto fail;
6686fcf3ce44SJohn Forte 		}
6687fcf3ce44SJohn Forte 
6688fcf3ce44SJohn Forte 		fcip_pkt->fcip_pkt_dma_flags |= FCIP_CMD_DMA_MEM;
6689fcf3ce44SJohn Forte 		fc_pkt->pkt_cmdlen = cmdlen;
6690fcf3ce44SJohn Forte 
6691fcf3ce44SJohn Forte 		if (real_len < cmdlen) {
6692fcf3ce44SJohn Forte 			goto fail;
6693fcf3ce44SJohn Forte 		}
6694fcf3ce44SJohn Forte 
6695fcf3ce44SJohn Forte 		if (ddi_dma_addr_bind_handle(fc_pkt->pkt_cmd_dma, NULL,
6696fcf3ce44SJohn Forte 		    (caddr_t)fc_pkt->pkt_cmd, real_len,
6697fcf3ce44SJohn Forte 		    DDI_DMA_WRITE | DDI_DMA_CONSISTENT, cb, NULL,
6698fcf3ce44SJohn Forte 		    &pkt_cookie, &fc_pkt->pkt_cmd_cookie_cnt) !=
6699fcf3ce44SJohn Forte 		    DDI_DMA_MAPPED) {
6700fcf3ce44SJohn Forte 			goto fail;
6701fcf3ce44SJohn Forte 		}
6702fcf3ce44SJohn Forte 
6703fcf3ce44SJohn Forte 		fcip_pkt->fcip_pkt_dma_flags |= FCIP_CMD_DMA_BOUND;
6704fcf3ce44SJohn Forte 
6705fcf3ce44SJohn Forte 		if (fc_pkt->pkt_cmd_cookie_cnt >
6706fcf3ce44SJohn Forte 		    fport->fcipp_cmd_dma_attr.dma_attr_sgllen) {
6707fcf3ce44SJohn Forte 			goto fail;
6708fcf3ce44SJohn Forte 		}
6709fcf3ce44SJohn Forte 
6710fcf3ce44SJohn Forte 		ASSERT(fc_pkt->pkt_cmd_cookie_cnt != 0);
6711fcf3ce44SJohn Forte 
6712fcf3ce44SJohn Forte 		cp = fc_pkt->pkt_cmd_cookie = (ddi_dma_cookie_t *)kmem_alloc(
6713fcf3ce44SJohn Forte 		    fc_pkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie),
6714fcf3ce44SJohn Forte 		    KM_NOSLEEP);
6715fcf3ce44SJohn Forte 
6716fcf3ce44SJohn Forte 		if (cp == NULL) {
6717fcf3ce44SJohn Forte 			goto fail;
6718fcf3ce44SJohn Forte 		}
6719fcf3ce44SJohn Forte 
6720fcf3ce44SJohn Forte 		*cp = pkt_cookie;
6721fcf3ce44SJohn Forte 		cp++;
6722fcf3ce44SJohn Forte 		for (cnt = 1; cnt < fc_pkt->pkt_cmd_cookie_cnt; cnt++, cp++) {
6723fcf3ce44SJohn Forte 			ddi_dma_nextcookie(fc_pkt->pkt_cmd_dma, &pkt_cookie);
6724fcf3ce44SJohn Forte 			*cp = pkt_cookie;
6725fcf3ce44SJohn Forte 		}
6726fcf3ce44SJohn Forte 	}
6727fcf3ce44SJohn Forte 
6728fcf3ce44SJohn Forte 	if (resplen) {
6729fcf3ce44SJohn Forte 		if (ddi_dma_alloc_handle(fptr->fcip_dip,
6730fcf3ce44SJohn Forte 		    &fport->fcipp_resp_dma_attr, cb, NULL,
6731fcf3ce44SJohn Forte 		    &fc_pkt->pkt_resp_dma) != DDI_SUCCESS) {
6732fcf3ce44SJohn Forte 			goto fail;
6733fcf3ce44SJohn Forte 		}
6734fcf3ce44SJohn Forte 
6735fcf3ce44SJohn Forte 		if (ddi_dma_mem_alloc(fc_pkt->pkt_resp_dma, resplen,
6736fcf3ce44SJohn Forte 		    &fport->fcipp_fca_acc_attr, DDI_DMA_CONSISTENT,
6737fcf3ce44SJohn Forte 		    cb, NULL, (caddr_t *)&fc_pkt->pkt_resp,
6738fcf3ce44SJohn Forte 		    &real_len, &fc_pkt->pkt_resp_acc) != DDI_SUCCESS) {
6739fcf3ce44SJohn Forte 			goto fail;
6740fcf3ce44SJohn Forte 		}
6741fcf3ce44SJohn Forte 
6742fcf3ce44SJohn Forte 		fcip_pkt->fcip_pkt_dma_flags |= FCIP_RESP_DMA_MEM;
6743fcf3ce44SJohn Forte 
6744fcf3ce44SJohn Forte 		if (real_len < resplen) {
6745fcf3ce44SJohn Forte 			goto fail;
6746fcf3ce44SJohn Forte 		}
6747fcf3ce44SJohn Forte 
6748fcf3ce44SJohn Forte 		if (ddi_dma_addr_bind_handle(fc_pkt->pkt_resp_dma, NULL,
6749fcf3ce44SJohn Forte 		    (caddr_t)fc_pkt->pkt_resp, real_len,
6750fcf3ce44SJohn Forte 		    DDI_DMA_WRITE | DDI_DMA_CONSISTENT, cb, NULL,
6751fcf3ce44SJohn Forte 		    &pkt_cookie, &fc_pkt->pkt_resp_cookie_cnt) !=
6752fcf3ce44SJohn Forte 		    DDI_DMA_MAPPED) {
6753fcf3ce44SJohn Forte 			goto fail;
6754fcf3ce44SJohn Forte 		}
6755fcf3ce44SJohn Forte 
6756fcf3ce44SJohn Forte 		fcip_pkt->fcip_pkt_dma_flags |= FCIP_RESP_DMA_BOUND;
6757fcf3ce44SJohn Forte 		fc_pkt->pkt_rsplen = resplen;
6758fcf3ce44SJohn Forte 
6759fcf3ce44SJohn Forte 		if (fc_pkt->pkt_resp_cookie_cnt >
6760fcf3ce44SJohn Forte 		    fport->fcipp_resp_dma_attr.dma_attr_sgllen) {
6761fcf3ce44SJohn Forte 			goto fail;
6762fcf3ce44SJohn Forte 		}
6763fcf3ce44SJohn Forte 
6764fcf3ce44SJohn Forte 		ASSERT(fc_pkt->pkt_resp_cookie_cnt != 0);
6765fcf3ce44SJohn Forte 
6766fcf3ce44SJohn Forte 		cp = fc_pkt->pkt_resp_cookie = (ddi_dma_cookie_t *)kmem_alloc(
6767fcf3ce44SJohn Forte 		    fc_pkt->pkt_resp_cookie_cnt * sizeof (pkt_cookie),
6768fcf3ce44SJohn Forte 		    KM_NOSLEEP);
6769fcf3ce44SJohn Forte 
6770fcf3ce44SJohn Forte 		if (cp == NULL) {
6771fcf3ce44SJohn Forte 			goto fail;
6772fcf3ce44SJohn Forte 		}
6773fcf3ce44SJohn Forte 
6774fcf3ce44SJohn Forte 		*cp = pkt_cookie;
6775fcf3ce44SJohn Forte 		cp++;
6776fcf3ce44SJohn Forte 		for (cnt = 1; cnt < fc_pkt->pkt_resp_cookie_cnt; cnt++, cp++) {
6777fcf3ce44SJohn Forte 			ddi_dma_nextcookie(fc_pkt->pkt_resp_dma, &pkt_cookie);
6778fcf3ce44SJohn Forte 			*cp = pkt_cookie;
6779fcf3ce44SJohn Forte 		}
6780fcf3ce44SJohn Forte 	}
6781fcf3ce44SJohn Forte 
6782fcf3ce44SJohn Forte 	/*
6783fcf3ce44SJohn Forte 	 * Initialize pkt_pd prior to calling fc_ulp_init_packet
6784fcf3ce44SJohn Forte 	 */
6785fcf3ce44SJohn Forte 
6786fcf3ce44SJohn Forte 	fc_pkt->pkt_pd = pd;
6787fcf3ce44SJohn Forte 
6788fcf3ce44SJohn Forte 	/*
6789fcf3ce44SJohn Forte 	 * Ask the FCA to bless the internal packet
6790fcf3ce44SJohn Forte 	 */
6791fcf3ce44SJohn Forte 	if (fc_ulp_init_packet((opaque_t)fport->fcipp_handle,
6792fcf3ce44SJohn Forte 	    fc_pkt, flags) != FC_SUCCESS) {
6793fcf3ce44SJohn Forte 		goto fail;
6794fcf3ce44SJohn Forte 	}
6795fcf3ce44SJohn Forte 
6796fcf3ce44SJohn Forte 	/*
6797fcf3ce44SJohn Forte 	 * Keep track of # of ipkts alloc-ed
6798fcf3ce44SJohn Forte 	 * This function can get called with mutex either held or not. So, we'll
6799fcf3ce44SJohn Forte 	 * grab mutex if it is not already held by this thread.
6800fcf3ce44SJohn Forte 	 * This has to be cleaned up someday.
6801fcf3ce44SJohn Forte 	 */
6802fcf3ce44SJohn Forte 	if (!MUTEX_HELD(&fptr->fcip_mutex)) {
6803fcf3ce44SJohn Forte 		held_here = 1;
6804fcf3ce44SJohn Forte 		mutex_enter(&fptr->fcip_mutex);
6805fcf3ce44SJohn Forte 	}
6806fcf3ce44SJohn Forte 
6807fcf3ce44SJohn Forte 	fptr->fcip_num_ipkts_pending++;
6808fcf3ce44SJohn Forte 
6809fcf3ce44SJohn Forte 	if (held_here)
6810fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_mutex);
6811fcf3ce44SJohn Forte 
6812fcf3ce44SJohn Forte 	return (fcip_pkt);
6813fcf3ce44SJohn Forte fail:
6814fcf3ce44SJohn Forte 	if (fcip_pkt) {
6815fcf3ce44SJohn Forte 		fcip_ipkt_free(fcip_pkt);
6816fcf3ce44SJohn Forte 	}
6817fcf3ce44SJohn Forte 
6818fcf3ce44SJohn Forte 	return (NULL);
6819fcf3ce44SJohn Forte }
6820fcf3ce44SJohn Forte 
6821fcf3ce44SJohn Forte /*
6822fcf3ce44SJohn Forte  * free up an internal IP packet (like a FARP pkt etc)
6823fcf3ce44SJohn Forte  */
6824fcf3ce44SJohn Forte static void
6825fcf3ce44SJohn Forte fcip_ipkt_free(fcip_pkt_t *fcip_pkt)
6826fcf3ce44SJohn Forte {
6827fcf3ce44SJohn Forte 	fc_packet_t		*fc_pkt;
6828fcf3ce44SJohn Forte 	struct fcip		*fptr = fcip_pkt->fcip_pkt_fptr;
6829fcf3ce44SJohn Forte 	fcip_port_info_t	*fport = fptr->fcip_port_info;
6830fcf3ce44SJohn Forte 
6831fcf3ce44SJohn Forte 	ASSERT(fptr != NULL);
6832fcf3ce44SJohn Forte 	ASSERT(!mutex_owned(&fptr->fcip_mutex));
6833fcf3ce44SJohn Forte 
6834fcf3ce44SJohn Forte 	/* One less ipkt to wait for */
6835fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_mutex);
6836fcf3ce44SJohn Forte 	if (fptr->fcip_num_ipkts_pending)	/* Safety check */
6837fcf3ce44SJohn Forte 		fptr->fcip_num_ipkts_pending--;
6838fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_mutex);
6839fcf3ce44SJohn Forte 
6840fcf3ce44SJohn Forte 	fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
6841fcf3ce44SJohn Forte 
6842fcf3ce44SJohn Forte 	if (fc_pkt->pkt_cmd_cookie != NULL) {
6843fcf3ce44SJohn Forte 		kmem_free(fc_pkt->pkt_cmd_cookie, fc_pkt->pkt_cmd_cookie_cnt *
6844fcf3ce44SJohn Forte 		    sizeof (ddi_dma_cookie_t));
6845fcf3ce44SJohn Forte 		fc_pkt->pkt_cmd_cookie = NULL;
6846fcf3ce44SJohn Forte 	}
6847fcf3ce44SJohn Forte 
6848fcf3ce44SJohn Forte 	if (fc_pkt->pkt_resp_cookie != NULL) {
6849fcf3ce44SJohn Forte 		kmem_free(fc_pkt->pkt_resp_cookie, fc_pkt->pkt_resp_cookie_cnt *
6850fcf3ce44SJohn Forte 		    sizeof (ddi_dma_cookie_t));
6851fcf3ce44SJohn Forte 		fc_pkt->pkt_resp_cookie = NULL;
6852fcf3ce44SJohn Forte 	}
6853fcf3ce44SJohn Forte 
6854fcf3ce44SJohn Forte 	if (fc_ulp_uninit_packet(fport->fcipp_handle, fc_pkt) != FC_SUCCESS) {
6855fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_ELS, (CE_WARN,
6856fcf3ce44SJohn Forte 		    "fc_ulp_uninit_pkt failed for internal fc pkt 0x%p",
6857fcf3ce44SJohn Forte 		    (void *)fc_pkt));
6858fcf3ce44SJohn Forte 	}
6859fcf3ce44SJohn Forte 	fcip_free_pkt_dma(fcip_pkt);
6860fcf3ce44SJohn Forte 	kmem_free(fcip_pkt, (sizeof (fcip_pkt_t) + fport->fcipp_fca_pkt_size));
6861fcf3ce44SJohn Forte }
6862fcf3ce44SJohn Forte 
6863fcf3ce44SJohn Forte /*
6864fcf3ce44SJohn Forte  * initialize a unicast request. This is a misnomer because even the
6865fcf3ce44SJohn Forte  * broadcast requests are initialized with this routine
6866fcf3ce44SJohn Forte  */
6867fcf3ce44SJohn Forte static void
6868fcf3ce44SJohn Forte fcip_init_unicast_pkt(fcip_pkt_t *fcip_pkt, fc_portid_t sid, fc_portid_t did,
6869fcf3ce44SJohn Forte     void (*comp) ())
6870fcf3ce44SJohn Forte {
6871fcf3ce44SJohn Forte 	fc_packet_t		*fc_pkt;
6872fcf3ce44SJohn Forte 	fc_frame_hdr_t		*fr_hdr;
6873fcf3ce44SJohn Forte 	struct fcip		*fptr = fcip_pkt->fcip_pkt_fptr;
6874fcf3ce44SJohn Forte 
6875fcf3ce44SJohn Forte 	fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
6876fcf3ce44SJohn Forte 	fr_hdr = &fc_pkt->pkt_cmd_fhdr;
6877fcf3ce44SJohn Forte 
6878fcf3ce44SJohn Forte 	fr_hdr->r_ctl = R_CTL_DEVICE_DATA | R_CTL_UNSOL_DATA;
6879fcf3ce44SJohn Forte 	fr_hdr->s_id = sid.port_id;
6880fcf3ce44SJohn Forte 	fr_hdr->d_id = did.port_id;
6881fcf3ce44SJohn Forte 	fr_hdr->type = FC_TYPE_IS8802_SNAP;
6882fcf3ce44SJohn Forte 	fr_hdr->f_ctl = F_CTL_FIRST_SEQ | F_CTL_LAST_SEQ;
6883fcf3ce44SJohn Forte 	fr_hdr->df_ctl = DF_CTL_NET_HDR;
6884fcf3ce44SJohn Forte 	fr_hdr->seq_cnt = 0;
6885fcf3ce44SJohn Forte 	fr_hdr->ox_id = 0xffff;
6886fcf3ce44SJohn Forte 	fr_hdr->rx_id = 0xffff;
6887fcf3ce44SJohn Forte 	fr_hdr->ro = 0;
6888fcf3ce44SJohn Forte 	/*
6889fcf3ce44SJohn Forte 	 * reset all the length fields
6890fcf3ce44SJohn Forte 	 */
6891fcf3ce44SJohn Forte 	fc_pkt->pkt_rsplen = 0;
6892fcf3ce44SJohn Forte 	fc_pkt->pkt_datalen = 0;
6893fcf3ce44SJohn Forte 	fc_pkt->pkt_comp = comp;
6894fcf3ce44SJohn Forte 	if (comp) {
6895fcf3ce44SJohn Forte 		fc_pkt->pkt_tran_flags |= FC_TRAN_INTR;
6896fcf3ce44SJohn Forte 	} else {
6897fcf3ce44SJohn Forte 		fc_pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
6898fcf3ce44SJohn Forte 	}
6899fcf3ce44SJohn Forte 	fc_pkt->pkt_tran_type = FC_PKT_OUTBOUND | FC_PKT_IP_WRITE;
6900fcf3ce44SJohn Forte 	fc_pkt->pkt_timeout = fcip_pkt_ttl_ticks;
6901fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_ttl = fptr->fcip_timeout_ticks + fc_pkt->pkt_timeout;
6902fcf3ce44SJohn Forte }
6903fcf3ce44SJohn Forte 
6904fcf3ce44SJohn Forte 
6905fcf3ce44SJohn Forte /*
6906fcf3ce44SJohn Forte  * Initialize a fcip_packet for broadcast data transfers
6907fcf3ce44SJohn Forte  */
6908fcf3ce44SJohn Forte static void
6909fcf3ce44SJohn Forte fcip_init_broadcast_pkt(fcip_pkt_t *fcip_pkt, void (*comp) (), int is_els)
6910fcf3ce44SJohn Forte {
6911fcf3ce44SJohn Forte 	fc_packet_t		*fc_pkt;
6912fcf3ce44SJohn Forte 	fc_frame_hdr_t		*fr_hdr;
6913fcf3ce44SJohn Forte 	struct fcip		*fptr = fcip_pkt->fcip_pkt_fptr;
6914fcf3ce44SJohn Forte 	fcip_port_info_t	*fport = fptr->fcip_port_info;
6915fcf3ce44SJohn Forte 	uint32_t		sid;
6916fcf3ce44SJohn Forte 	uint32_t		did;
6917fcf3ce44SJohn Forte 
6918fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_1((fcip_init_broadcast_pkt, "fcip io", /* CSTYLED */,
6919fcf3ce44SJohn Forte 		tnf_string, msg, "enter"));
6920fcf3ce44SJohn Forte 	fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
6921fcf3ce44SJohn Forte 	fr_hdr = &fc_pkt->pkt_cmd_fhdr;
6922fcf3ce44SJohn Forte 	sid = fport->fcipp_sid.port_id;
6923fcf3ce44SJohn Forte 
6924fcf3ce44SJohn Forte 	if (is_els) {
6925fcf3ce44SJohn Forte 		fr_hdr->r_ctl = R_CTL_ELS_REQ;
6926fcf3ce44SJohn Forte 	} else {
6927fcf3ce44SJohn Forte 		fr_hdr->r_ctl = R_CTL_DEVICE_DATA | R_CTL_UNSOL_DATA;
6928fcf3ce44SJohn Forte 	}
6929fcf3ce44SJohn Forte 	fr_hdr->s_id = sid;
6930fcf3ce44SJohn Forte 	/*
6931fcf3ce44SJohn Forte 	 * The destination broadcast address depends on the topology
6932fcf3ce44SJohn Forte 	 * of the underlying port
6933fcf3ce44SJohn Forte 	 */
6934fcf3ce44SJohn Forte 	did = fptr->fcip_broadcast_did;
6935fcf3ce44SJohn Forte 	/*
6936fcf3ce44SJohn Forte 	 * mark pkt a broadcast pkt
6937fcf3ce44SJohn Forte 	 */
6938fcf3ce44SJohn Forte 	fc_pkt->pkt_tran_type = FC_PKT_BROADCAST;
6939fcf3ce44SJohn Forte 
6940fcf3ce44SJohn Forte 	fr_hdr->d_id = did;
6941fcf3ce44SJohn Forte 	fr_hdr->type = FC_TYPE_IS8802_SNAP;
6942fcf3ce44SJohn Forte 	fr_hdr->f_ctl = F_CTL_FIRST_SEQ | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
6943fcf3ce44SJohn Forte 	fr_hdr->f_ctl &= ~(F_CTL_SEQ_INITIATIVE);
6944fcf3ce44SJohn Forte 	fr_hdr->df_ctl = DF_CTL_NET_HDR;
6945fcf3ce44SJohn Forte 	fr_hdr->seq_cnt = 0;
6946fcf3ce44SJohn Forte 	fr_hdr->ox_id = 0xffff;
6947fcf3ce44SJohn Forte 	fr_hdr->rx_id = 0xffff;
6948fcf3ce44SJohn Forte 	fr_hdr->ro = 0;
6949fcf3ce44SJohn Forte 	fc_pkt->pkt_comp = comp;
6950fcf3ce44SJohn Forte 
6951fcf3ce44SJohn Forte 	if (comp) {
6952fcf3ce44SJohn Forte 		fc_pkt->pkt_tran_flags |= FC_TRAN_INTR;
6953fcf3ce44SJohn Forte 	} else {
6954fcf3ce44SJohn Forte 		fc_pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
6955fcf3ce44SJohn Forte 	}
6956fcf3ce44SJohn Forte 
6957fcf3ce44SJohn Forte 	fc_pkt->pkt_tran_type = FC_PKT_BROADCAST;
6958fcf3ce44SJohn Forte 	fc_pkt->pkt_timeout = fcip_pkt_ttl_ticks;
6959fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_ttl = fptr->fcip_timeout_ticks + fc_pkt->pkt_timeout;
6960fcf3ce44SJohn Forte }
6961fcf3ce44SJohn Forte 
6962fcf3ce44SJohn Forte 
6963fcf3ce44SJohn Forte 
6964fcf3ce44SJohn Forte /*
6965fcf3ce44SJohn Forte  * Free up all DMA resources associated with an allocated packet
6966fcf3ce44SJohn Forte  */
6967fcf3ce44SJohn Forte static void
6968fcf3ce44SJohn Forte fcip_free_pkt_dma(fcip_pkt_t *fcip_pkt)
6969fcf3ce44SJohn Forte {
6970fcf3ce44SJohn Forte 	fc_packet_t	*fc_pkt;
6971fcf3ce44SJohn Forte 
6972fcf3ce44SJohn Forte 	fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
6973fcf3ce44SJohn Forte 
6974fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
6975fcf3ce44SJohn Forte 	    (CE_NOTE, "in freepktdma : flags 0x%x",
6976fcf3ce44SJohn Forte 	    fcip_pkt->fcip_pkt_dma_flags));
6977fcf3ce44SJohn Forte 
6978fcf3ce44SJohn Forte 	if (fcip_pkt->fcip_pkt_dma_flags & FCIP_CMD_DMA_BOUND) {
6979fcf3ce44SJohn Forte 		(void) ddi_dma_unbind_handle(fc_pkt->pkt_cmd_dma);
6980fcf3ce44SJohn Forte 	}
6981fcf3ce44SJohn Forte 	if (fcip_pkt->fcip_pkt_dma_flags & FCIP_CMD_DMA_MEM) {
6982fcf3ce44SJohn Forte 		ddi_dma_mem_free(&fc_pkt->pkt_cmd_acc);
6983fcf3ce44SJohn Forte 	}
6984fcf3ce44SJohn Forte 
6985fcf3ce44SJohn Forte 	if (fcip_pkt->fcip_pkt_dma_flags & FCIP_RESP_DMA_BOUND) {
6986fcf3ce44SJohn Forte 		(void) ddi_dma_unbind_handle(fc_pkt->pkt_resp_dma);
6987fcf3ce44SJohn Forte 	}
6988fcf3ce44SJohn Forte 	if (fcip_pkt->fcip_pkt_dma_flags & FCIP_RESP_DMA_MEM) {
6989fcf3ce44SJohn Forte 		ddi_dma_mem_free(&fc_pkt->pkt_resp_acc);
6990fcf3ce44SJohn Forte 	}
6991fcf3ce44SJohn Forte 	/*
6992fcf3ce44SJohn Forte 	 * for internal commands, we need to free up the dma handles too.
6993fcf3ce44SJohn Forte 	 * This is done in the cache destructor for non internal cmds
6994fcf3ce44SJohn Forte 	 */
6995fcf3ce44SJohn Forte 	if (fcip_pkt->fcip_pkt_flags & FCIP_PKT_INTERNAL) {
6996fcf3ce44SJohn Forte 		if (fc_pkt->pkt_cmd_dma) {
6997fcf3ce44SJohn Forte 			ddi_dma_free_handle(&fc_pkt->pkt_cmd_dma);
6998fcf3ce44SJohn Forte 		}
6999fcf3ce44SJohn Forte 		if (fc_pkt->pkt_resp_dma) {
7000fcf3ce44SJohn Forte 			ddi_dma_free_handle(&fc_pkt->pkt_resp_dma);
7001fcf3ce44SJohn Forte 		}
7002fcf3ce44SJohn Forte 	}
7003fcf3ce44SJohn Forte }
7004fcf3ce44SJohn Forte 
7005fcf3ce44SJohn Forte 
7006fcf3ce44SJohn Forte /*
7007fcf3ce44SJohn Forte  * helper routine to generate a string, given an ether addr
7008fcf3ce44SJohn Forte  */
7009fcf3ce44SJohn Forte static void
7010fcf3ce44SJohn Forte fcip_ether_to_str(struct ether_addr *e, caddr_t s)
7011fcf3ce44SJohn Forte {
7012fcf3ce44SJohn Forte 	int i;
7013fcf3ce44SJohn Forte 
7014fcf3ce44SJohn Forte 	for (i = 0; i < sizeof (struct ether_addr); i++, s += 2) {
7015fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_MISC,
7016fcf3ce44SJohn Forte 		    (CE_CONT, "0x%02X:", e->ether_addr_octet[i]));
7017fcf3ce44SJohn Forte 		(void) sprintf(s, "%02X", e->ether_addr_octet[i]);
7018fcf3ce44SJohn Forte 	}
7019fcf3ce44SJohn Forte 
7020fcf3ce44SJohn Forte 	*s = '\0';
7021fcf3ce44SJohn Forte }
7022fcf3ce44SJohn Forte 
7023fcf3ce44SJohn Forte /*
7024fcf3ce44SJohn Forte  * When a broadcast request comes from the upper streams modules, it
7025fcf3ce44SJohn Forte  * is ugly to look into every datagram to figure out if it is a broadcast
7026fcf3ce44SJohn Forte  * datagram or a unicast packet. Instead just add the broadcast entries
7027fcf3ce44SJohn Forte  * into our routing and dest tables and the standard hash table look ups
7028fcf3ce44SJohn Forte  * will find the entries. It is a lot cleaner this way. Also Solaris ifconfig
7029fcf3ce44SJohn Forte  * seems to be very ethernet specific and it requires broadcasts to the
7030fcf3ce44SJohn Forte  * ether broadcast addr of 0xffffffffff to succeed even though we specified
7031fcf3ce44SJohn Forte  * in the dl_info request that our broadcast MAC addr is 0x0000000000
7032fcf3ce44SJohn Forte  * (can't figure out why RFC2625 did this though). So add broadcast entries
7033fcf3ce44SJohn Forte  * for both MAC address
7034fcf3ce44SJohn Forte  */
7035fcf3ce44SJohn Forte static int
7036fcf3ce44SJohn Forte fcip_dest_add_broadcast_entry(struct fcip *fptr, int new_flag)
7037fcf3ce44SJohn Forte {
7038fcf3ce44SJohn Forte 	fc_portmap_t 		map;
7039fcf3ce44SJohn Forte 	struct fcip_routing_table *frp;
7040fcf3ce44SJohn Forte 	uint32_t		did;
7041fcf3ce44SJohn Forte 	la_wwn_t		broadcast_wwn;
7042fcf3ce44SJohn Forte 
7043fcf3ce44SJohn Forte 	/*
7044fcf3ce44SJohn Forte 	 * get port_id of destination for broadcast - this is topology
7045fcf3ce44SJohn Forte 	 * dependent
7046fcf3ce44SJohn Forte 	 */
7047fcf3ce44SJohn Forte 	did = fptr->fcip_broadcast_did;
7048fcf3ce44SJohn Forte 
7049fcf3ce44SJohn Forte 	ether_to_wwn(&fcip_arpbroadcast_addr, &broadcast_wwn);
7050fcf3ce44SJohn Forte 	bcopy((void *)&broadcast_wwn, (void *)&map.map_pwwn, sizeof (la_wwn_t));
7051fcf3ce44SJohn Forte 	bcopy((void *)&broadcast_wwn, (void *)&map.map_nwwn, sizeof (la_wwn_t));
7052fcf3ce44SJohn Forte 
7053fcf3ce44SJohn Forte 	map.map_did.port_id = did;
7054fcf3ce44SJohn Forte 	map.map_hard_addr.hard_addr = did;
7055fcf3ce44SJohn Forte 	map.map_state = PORT_DEVICE_VALID;
7056fcf3ce44SJohn Forte 	if (new_flag) {
7057fcf3ce44SJohn Forte 		map.map_type = PORT_DEVICE_NEW;
7058fcf3ce44SJohn Forte 	} else {
7059fcf3ce44SJohn Forte 		map.map_type = PORT_DEVICE_CHANGED;
7060fcf3ce44SJohn Forte 	}
7061fcf3ce44SJohn Forte 	map.map_flags = 0;
7062fcf3ce44SJohn Forte 	map.map_pd = NULL;
7063fcf3ce44SJohn Forte 	bzero(&map.map_fc4_types, sizeof (map.map_fc4_types));
7064fcf3ce44SJohn Forte 	fcip_rt_update(fptr, &map, 1);
7065fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_rt_mutex);
7066fcf3ce44SJohn Forte 	frp = fcip_lookup_rtable(fptr, &broadcast_wwn, FCIP_COMPARE_NWWN);
7067fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_rt_mutex);
7068fcf3ce44SJohn Forte 	if (frp == NULL) {
7069fcf3ce44SJohn Forte 		return (FC_FAILURE);
7070fcf3ce44SJohn Forte 	}
7071fcf3ce44SJohn Forte 	(void) fcip_add_dest(fptr, frp);
7072fcf3ce44SJohn Forte 	/*
7073fcf3ce44SJohn Forte 	 * The Upper IP layers expect the traditional broadcast MAC addr
7074fcf3ce44SJohn Forte 	 * of 0xff ff ff ff ff ff to work too if we want to plumb the fcip
7075fcf3ce44SJohn Forte 	 * stream through the /etc/hostname.fcipXX file. Instead of checking
7076fcf3ce44SJohn Forte 	 * each phys addr for a match with fcip's ARP header broadcast
7077fcf3ce44SJohn Forte 	 * addr (0x00 00 00 00 00 00), its simply easier to add another
7078fcf3ce44SJohn Forte 	 * broadcast entry for 0xff ff ff ff ff ff.
7079fcf3ce44SJohn Forte 	 */
7080fcf3ce44SJohn Forte 	ether_to_wwn(&fcipnhbroadcastaddr, &broadcast_wwn);
7081fcf3ce44SJohn Forte 	bcopy((void *)&broadcast_wwn, (void *)&map.map_pwwn, sizeof (la_wwn_t));
7082fcf3ce44SJohn Forte 	bcopy((void *)&broadcast_wwn, (void *)&map.map_nwwn, sizeof (la_wwn_t));
7083fcf3ce44SJohn Forte 	fcip_rt_update(fptr, &map, 1);
7084fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_rt_mutex);
7085fcf3ce44SJohn Forte 	frp = fcip_lookup_rtable(fptr, &broadcast_wwn, FCIP_COMPARE_NWWN);
7086fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_rt_mutex);
7087fcf3ce44SJohn Forte 	if (frp == NULL) {
7088fcf3ce44SJohn Forte 		return (FC_FAILURE);
7089fcf3ce44SJohn Forte 	}
7090fcf3ce44SJohn Forte 	(void) fcip_add_dest(fptr, frp);
7091fcf3ce44SJohn Forte 	return (FC_SUCCESS);
7092fcf3ce44SJohn Forte }
7093fcf3ce44SJohn Forte 
7094fcf3ce44SJohn Forte /*
7095fcf3ce44SJohn Forte  * We need to obtain the D_ID of the broadcast port for transmitting all
7096fcf3ce44SJohn Forte  * our broadcast (and multicast) requests. The broadcast D_ID as we know
7097fcf3ce44SJohn Forte  * is dependent on the link topology
7098fcf3ce44SJohn Forte  */
7099fcf3ce44SJohn Forte static uint32_t
7100fcf3ce44SJohn Forte fcip_get_broadcast_did(struct fcip *fptr)
7101fcf3ce44SJohn Forte {
7102fcf3ce44SJohn Forte 	fcip_port_info_t	*fport = fptr->fcip_port_info;
7103fcf3ce44SJohn Forte 	uint32_t		did = 0;
7104fcf3ce44SJohn Forte 	uint32_t		sid;
7105fcf3ce44SJohn Forte 
7106fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_2((fcip_get_broadcast_did, "fcip io", /* CSTYLED */,
7107fcf3ce44SJohn Forte 		tnf_string, msg, "enter",
7108fcf3ce44SJohn Forte 		tnf_opaque, fptr, fptr));
7109fcf3ce44SJohn Forte 
7110fcf3ce44SJohn Forte 	sid = fport->fcipp_sid.port_id;
7111fcf3ce44SJohn Forte 
7112fcf3ce44SJohn Forte 	switch (fport->fcipp_topology) {
7113fcf3ce44SJohn Forte 
7114fcf3ce44SJohn Forte 	case FC_TOP_PT_PT: {
7115fcf3ce44SJohn Forte 		fc_portmap_t	*port_map = NULL;
7116fcf3ce44SJohn Forte 		uint32_t	listlen = 0;
7117fcf3ce44SJohn Forte 
7118fcf3ce44SJohn Forte 		if (fc_ulp_getportmap(fport->fcipp_handle, &port_map,
7119fcf3ce44SJohn Forte 		    &listlen, FC_ULP_PLOGI_DONTCARE) == FC_SUCCESS) {
7120fcf3ce44SJohn Forte 			FCIP_DEBUG(FCIP_DEBUG_INIT, (CE_NOTE,
7121fcf3ce44SJohn Forte 			    "fcip_gpmap: listlen :  0x%x", listlen));
7122fcf3ce44SJohn Forte 			if (listlen == 1) {
7123fcf3ce44SJohn Forte 				did = port_map->map_did.port_id;
7124fcf3ce44SJohn Forte 			}
7125fcf3ce44SJohn Forte 		}
7126fcf3ce44SJohn Forte 		if (port_map) {
7127fcf3ce44SJohn Forte 			kmem_free(port_map, listlen * sizeof (fc_portmap_t));
7128fcf3ce44SJohn Forte 		}
7129fcf3ce44SJohn Forte 		if (listlen != 1) {
7130fcf3ce44SJohn Forte 			/* Dummy return value */
7131fcf3ce44SJohn Forte 			return (0x00FFFFFF);
7132fcf3ce44SJohn Forte 		}
7133fcf3ce44SJohn Forte 		break;
7134fcf3ce44SJohn Forte 	}
7135fcf3ce44SJohn Forte 
7136fcf3ce44SJohn Forte 	case FC_TOP_NO_NS:
7137fcf3ce44SJohn Forte 	/* FALLTHROUGH */
7138fcf3ce44SJohn Forte 	case FC_TOP_FABRIC:
7139fcf3ce44SJohn Forte 		/*
7140fcf3ce44SJohn Forte 		 * The broadcast address is the same whether or not
7141fcf3ce44SJohn Forte 		 * the switch/fabric contains a Name service.
7142fcf3ce44SJohn Forte 		 */
7143fcf3ce44SJohn Forte 		did = 0x00FFFFFF;
7144fcf3ce44SJohn Forte 		break;
7145fcf3ce44SJohn Forte 
7146fcf3ce44SJohn Forte 	case FC_TOP_PUBLIC_LOOP:
7147fcf3ce44SJohn Forte 		/*
7148fcf3ce44SJohn Forte 		 * The open replicate primitive must not be used. The
7149fcf3ce44SJohn Forte 		 * broadcast sequence is simply sent to ALPA 0x00. The
7150fcf3ce44SJohn Forte 		 * fabric controller then propagates the broadcast to all
7151fcf3ce44SJohn Forte 		 * other ports. The fabric propagates the broadcast by
7152fcf3ce44SJohn Forte 		 * using the OPNfr primitive.
7153fcf3ce44SJohn Forte 		 */
7154fcf3ce44SJohn Forte 		did = 0x00;
7155fcf3ce44SJohn Forte 		break;
7156fcf3ce44SJohn Forte 
7157fcf3ce44SJohn Forte 	case FC_TOP_PRIVATE_LOOP:
7158fcf3ce44SJohn Forte 		/*
7159fcf3ce44SJohn Forte 		 * The source port for broadcast in private loop mode
7160fcf3ce44SJohn Forte 		 * must send an OPN(fr) signal forcing all ports in the
7161fcf3ce44SJohn Forte 		 * loop to replicate the frames that they receive.
7162fcf3ce44SJohn Forte 		 */
7163fcf3ce44SJohn Forte 		did = 0x00FFFFFF;
7164fcf3ce44SJohn Forte 		break;
7165fcf3ce44SJohn Forte 
7166fcf3ce44SJohn Forte 	case FC_TOP_UNKNOWN:
7167fcf3ce44SJohn Forte 	/* FALLTHROUGH */
7168fcf3ce44SJohn Forte 	default:
7169fcf3ce44SJohn Forte 		did = sid;
7170fcf3ce44SJohn Forte 		FCIP_DEBUG(FCIP_DEBUG_INIT, (CE_WARN,
7171fcf3ce44SJohn Forte 		    "fcip(0x%x):unknown topology in init_broadcast_pkt",
7172fcf3ce44SJohn Forte 		    fptr->fcip_instance));
7173fcf3ce44SJohn Forte 		break;
7174fcf3ce44SJohn Forte 	}
7175fcf3ce44SJohn Forte 	FCIP_TNF_PROBE_2((fcip_get_broadcast_did, "fcip io", /* CSTYLED */,
7176fcf3ce44SJohn Forte 		tnf_string, msg, "return",
7177fcf3ce44SJohn Forte 		tnf_opaque, did, did));
7178fcf3ce44SJohn Forte 
7179fcf3ce44SJohn Forte 	return (did);
7180fcf3ce44SJohn Forte }
7181fcf3ce44SJohn Forte 
7182fcf3ce44SJohn Forte 
7183fcf3ce44SJohn Forte /*
7184fcf3ce44SJohn Forte  * fcip timeout performs 2 operations:
7185fcf3ce44SJohn Forte  * 1. timeout any packets sent to the FCA for which a callback hasn't
7186fcf3ce44SJohn Forte  *    happened. If you are wondering why we need a callback since all
7187fcf3ce44SJohn Forte  *    traffic in FCIP is unidirectional, hence all exchanges are unidirectional
7188fcf3ce44SJohn Forte  *    but wait, we can only free up the resources after we know the FCA has
7189fcf3ce44SJohn Forte  *    DMA'ed out the data. pretty obvious eh :)
7190fcf3ce44SJohn Forte  *
7191fcf3ce44SJohn Forte  * 2. Retire and routing table entries we marked up for retiring. This is
7192fcf3ce44SJohn Forte  *    to give the link a chance to recover instead of marking a port down
7193fcf3ce44SJohn Forte  *    when we have lost all communication with it after a link transition
7194fcf3ce44SJohn Forte  */
7195fcf3ce44SJohn Forte static void
7196fcf3ce44SJohn Forte fcip_timeout(void *arg)
7197fcf3ce44SJohn Forte {
7198fcf3ce44SJohn Forte 	struct fcip 			*fptr = (struct fcip *)arg;
7199fcf3ce44SJohn Forte 	int				i;
7200fcf3ce44SJohn Forte 	fcip_pkt_t			*fcip_pkt;
7201fcf3ce44SJohn Forte 	struct fcip_dest		*fdestp;
7202fcf3ce44SJohn Forte 	int 				index;
7203fcf3ce44SJohn Forte 	struct fcip_routing_table 	*frtp;
7204fcf3ce44SJohn Forte 	int				dispatch_rte_removal = 0;
7205fcf3ce44SJohn Forte 
7206fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_mutex);
7207fcf3ce44SJohn Forte 
7208fcf3ce44SJohn Forte 	fptr->fcip_flags |= FCIP_IN_TIMEOUT;
7209fcf3ce44SJohn Forte 	fptr->fcip_timeout_ticks += fcip_tick_incr;
7210fcf3ce44SJohn Forte 
7211fcf3ce44SJohn Forte 	if (fptr->fcip_flags & (FCIP_DETACHED | FCIP_DETACHING | \
7212fcf3ce44SJohn Forte 	    FCIP_SUSPENDED | FCIP_POWER_DOWN)) {
7213fcf3ce44SJohn Forte 		fptr->fcip_flags &= ~(FCIP_IN_TIMEOUT);
7214fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_mutex);
7215fcf3ce44SJohn Forte 		return;
7216fcf3ce44SJohn Forte 	}
7217fcf3ce44SJohn Forte 
7218fcf3ce44SJohn Forte 	if (fptr->fcip_port_state == FCIP_PORT_OFFLINE) {
7219fcf3ce44SJohn Forte 		if (fptr->fcip_timeout_ticks > fptr->fcip_mark_offline) {
7220fcf3ce44SJohn Forte 			fptr->fcip_flags |= FCIP_LINK_DOWN;
7221fcf3ce44SJohn Forte 		}
7222fcf3ce44SJohn Forte 	}
7223fcf3ce44SJohn Forte 	if (!fptr->fcip_flags & FCIP_RTE_REMOVING) {
7224fcf3ce44SJohn Forte 		dispatch_rte_removal = 1;
7225fcf3ce44SJohn Forte 	}
7226fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_mutex);
7227fcf3ce44SJohn Forte 
7228fcf3ce44SJohn Forte 	/*
7229fcf3ce44SJohn Forte 	 * Check if we have any Invalid routing table entries in our
7230fcf3ce44SJohn Forte 	 * hashtable we have marked off for deferred removal. If any,
7231fcf3ce44SJohn Forte 	 * we can spawn a taskq thread to do the cleanup for us. We
7232fcf3ce44SJohn Forte 	 * need to avoid cleanup in the timeout thread since we may
7233fcf3ce44SJohn Forte 	 * have to wait for outstanding commands to complete before
7234fcf3ce44SJohn Forte 	 * we retire a routing table entry. Also dispatch the taskq
7235fcf3ce44SJohn Forte 	 * thread only if we are already do not have a taskq thread
7236fcf3ce44SJohn Forte 	 * dispatched.
7237fcf3ce44SJohn Forte 	 */
7238fcf3ce44SJohn Forte 	if (dispatch_rte_removal) {
7239fcf3ce44SJohn Forte 		mutex_enter(&fptr->fcip_rt_mutex);
7240fcf3ce44SJohn Forte 		for (index = 0; index < FCIP_RT_HASH_ELEMS; index++) {
7241fcf3ce44SJohn Forte 			frtp = fptr->fcip_rtable[index];
7242fcf3ce44SJohn Forte 			while (frtp) {
7243fcf3ce44SJohn Forte 				if ((frtp->fcipr_state == FCIP_RT_INVALID) &&
7244fcf3ce44SJohn Forte 				    (fptr->fcip_timeout_ticks >
7245fcf3ce44SJohn Forte 				    frtp->fcipr_invalid_timeout)) {
7246fcf3ce44SJohn Forte 					/*
7247fcf3ce44SJohn Forte 					 * If we cannot schedule a task thread
7248fcf3ce44SJohn Forte 					 * let us attempt again on the next
7249fcf3ce44SJohn Forte 					 * tick rather than call
7250fcf3ce44SJohn Forte 					 * fcip_rte_remove_deferred() from here
7251fcf3ce44SJohn Forte 					 * directly since the routine can sleep.
7252fcf3ce44SJohn Forte 					 */
7253fcf3ce44SJohn Forte 					frtp->fcipr_state = FCIP_RT_RETIRED;
7254fcf3ce44SJohn Forte 
7255fcf3ce44SJohn Forte 					mutex_enter(&fptr->fcip_mutex);
7256fcf3ce44SJohn Forte 					fptr->fcip_flags |= FCIP_RTE_REMOVING;
7257fcf3ce44SJohn Forte 					mutex_exit(&fptr->fcip_mutex);
7258fcf3ce44SJohn Forte 
7259fcf3ce44SJohn Forte 					if (taskq_dispatch(fptr->fcip_tq,
7260fcf3ce44SJohn Forte 					    fcip_rte_remove_deferred, fptr,
7261*fc8ae2ecSToomas Soome 					    KM_NOSLEEP) == TASKQID_INVALID) {
7262fcf3ce44SJohn Forte 						/*
7263fcf3ce44SJohn Forte 						 * failed - so mark the entry
7264fcf3ce44SJohn Forte 						 * as invalid again.
7265fcf3ce44SJohn Forte 						 */
7266fcf3ce44SJohn Forte 						frtp->fcipr_state =
7267fcf3ce44SJohn Forte 						    FCIP_RT_INVALID;
7268fcf3ce44SJohn Forte 
7269fcf3ce44SJohn Forte 						mutex_enter(&fptr->fcip_mutex);
7270fcf3ce44SJohn Forte 						fptr->fcip_flags &=
7271fcf3ce44SJohn Forte 						    ~FCIP_RTE_REMOVING;
7272fcf3ce44SJohn Forte 						mutex_exit(&fptr->fcip_mutex);
7273fcf3ce44SJohn Forte 					}
7274fcf3ce44SJohn Forte 				}
7275fcf3ce44SJohn Forte 				frtp = frtp->fcipr_next;
7276fcf3ce44SJohn Forte 			}
7277fcf3ce44SJohn Forte 		}
7278fcf3ce44SJohn Forte 		mutex_exit(&fptr->fcip_rt_mutex);
7279fcf3ce44SJohn Forte 	}
7280fcf3ce44SJohn Forte 
7281fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_dest_mutex);
7282fcf3ce44SJohn Forte 
7283fcf3ce44SJohn Forte 	/*
7284fcf3ce44SJohn Forte 	 * Now timeout any packets stuck with the transport/FCA for too long
7285fcf3ce44SJohn Forte 	 */
7286fcf3ce44SJohn Forte 	for (i = 0; i < FCIP_DEST_HASH_ELEMS; i++) {
7287fcf3ce44SJohn Forte 		fdestp = fptr->fcip_dest[i];
7288fcf3ce44SJohn Forte 		while (fdestp != NULL) {
7289fcf3ce44SJohn Forte 			mutex_enter(&fdestp->fcipd_mutex);
7290fcf3ce44SJohn Forte 			for (fcip_pkt = fdestp->fcipd_head; fcip_pkt != NULL;
7291fcf3ce44SJohn Forte 			    fcip_pkt = fcip_pkt->fcip_pkt_next) {
7292fcf3ce44SJohn Forte 				if (fcip_pkt->fcip_pkt_flags &
7293fcf3ce44SJohn Forte 				    (FCIP_PKT_RETURNED | FCIP_PKT_IN_TIMEOUT |
7294fcf3ce44SJohn Forte 				    FCIP_PKT_IN_ABORT)) {
7295fcf3ce44SJohn Forte 					continue;
7296fcf3ce44SJohn Forte 				}
7297fcf3ce44SJohn Forte 				if (fptr->fcip_timeout_ticks >
7298fcf3ce44SJohn Forte 				    fcip_pkt->fcip_pkt_ttl) {
7299fcf3ce44SJohn Forte 					fcip_pkt->fcip_pkt_flags |=
7300fcf3ce44SJohn Forte 					    FCIP_PKT_IN_TIMEOUT;
7301fcf3ce44SJohn Forte 
7302fcf3ce44SJohn Forte 					mutex_exit(&fdestp->fcipd_mutex);
7303fcf3ce44SJohn Forte 					if (taskq_dispatch(fptr->fcip_tq,
7304fcf3ce44SJohn Forte 					    fcip_pkt_timeout, fcip_pkt,
7305*fc8ae2ecSToomas Soome 					    KM_NOSLEEP) == TASKQID_INVALID) {
7306fcf3ce44SJohn Forte 						/*
7307fcf3ce44SJohn Forte 						 * timeout immediately
7308fcf3ce44SJohn Forte 						 */
7309fcf3ce44SJohn Forte 						fcip_pkt_timeout(fcip_pkt);
7310fcf3ce44SJohn Forte 					}
7311fcf3ce44SJohn Forte 					mutex_enter(&fdestp->fcipd_mutex);
7312fcf3ce44SJohn Forte 					/*
7313fcf3ce44SJohn Forte 					 * The linked list is altered because
7314fcf3ce44SJohn Forte 					 * of one of the following reasons:
7315fcf3ce44SJohn Forte 					 *	a. Timeout code dequeued a pkt
7316fcf3ce44SJohn Forte 					 *	b. Pkt completion happened
7317fcf3ce44SJohn Forte 					 *
7318fcf3ce44SJohn Forte 					 * So restart the spin starting at
7319fcf3ce44SJohn Forte 					 * the head again; This is a bit
7320fcf3ce44SJohn Forte 					 * excessive, but okay since
7321fcf3ce44SJohn Forte 					 * fcip_timeout_ticks isn't incremented
7322fcf3ce44SJohn Forte 					 * for this spin, we will skip the
7323fcf3ce44SJohn Forte 					 * not-to-be-timedout packets quickly
7324fcf3ce44SJohn Forte 					 */
7325fcf3ce44SJohn Forte 					fcip_pkt = fdestp->fcipd_head;
7326fcf3ce44SJohn Forte 					if (fcip_pkt == NULL) {
7327fcf3ce44SJohn Forte 						break;
7328fcf3ce44SJohn Forte 					}
7329fcf3ce44SJohn Forte 				}
7330fcf3ce44SJohn Forte 			}
7331fcf3ce44SJohn Forte 			mutex_exit(&fdestp->fcipd_mutex);
7332fcf3ce44SJohn Forte 			fdestp = fdestp->fcipd_next;
7333fcf3ce44SJohn Forte 		}
7334fcf3ce44SJohn Forte 	}
7335fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_dest_mutex);
7336fcf3ce44SJohn Forte 
7337fcf3ce44SJohn Forte 	/*
7338fcf3ce44SJohn Forte 	 * reschedule the timeout thread
7339fcf3ce44SJohn Forte 	 */
7340fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_mutex);
7341fcf3ce44SJohn Forte 
7342fcf3ce44SJohn Forte 	fptr->fcip_timeout_id = timeout(fcip_timeout, fptr,
7343fcf3ce44SJohn Forte 	    drv_usectohz(1000000));
7344fcf3ce44SJohn Forte 	fptr->fcip_flags &= ~(FCIP_IN_TIMEOUT);
7345fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_mutex);
7346fcf3ce44SJohn Forte }
7347fcf3ce44SJohn Forte 
7348fcf3ce44SJohn Forte 
7349fcf3ce44SJohn Forte /*
7350fcf3ce44SJohn Forte  * This routine is either called from taskq or directly from fcip_timeout
7351fcf3ce44SJohn Forte  * does the actual job of aborting the packet
7352fcf3ce44SJohn Forte  */
7353fcf3ce44SJohn Forte static void
7354fcf3ce44SJohn Forte fcip_pkt_timeout(void *arg)
7355fcf3ce44SJohn Forte {
7356fcf3ce44SJohn Forte 	fcip_pkt_t		*fcip_pkt = (fcip_pkt_t *)arg;
7357fcf3ce44SJohn Forte 	struct fcip_dest	*fdestp;
7358fcf3ce44SJohn Forte 	struct fcip		*fptr;
7359fcf3ce44SJohn Forte 	fc_packet_t		*fc_pkt;
7360fcf3ce44SJohn Forte 	fcip_port_info_t	*fport;
7361fcf3ce44SJohn Forte 	int			rval;
7362fcf3ce44SJohn Forte 
7363fcf3ce44SJohn Forte 	fdestp = fcip_pkt->fcip_pkt_dest;
7364fcf3ce44SJohn Forte 	fptr = fcip_pkt->fcip_pkt_fptr;
7365fcf3ce44SJohn Forte 	fport = fptr->fcip_port_info;
7366fcf3ce44SJohn Forte 	fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
7367fcf3ce44SJohn Forte 
7368fcf3ce44SJohn Forte 	/*
7369fcf3ce44SJohn Forte 	 * try to abort the pkt
7370fcf3ce44SJohn Forte 	 */
7371fcf3ce44SJohn Forte 	fcip_pkt->fcip_pkt_flags |= FCIP_PKT_IN_ABORT;
7372fcf3ce44SJohn Forte 	rval = fc_ulp_abort(fport->fcipp_handle, fc_pkt, KM_NOSLEEP);
7373fcf3ce44SJohn Forte 
7374fcf3ce44SJohn Forte 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
7375fcf3ce44SJohn Forte 	    (CE_NOTE, "fc_ulp_abort returns: 0x%x", rval));
7376fcf3ce44SJohn Forte 
7377fcf3ce44SJohn Forte 	if (rval == FC_SUCCESS) {
7378fcf3ce44SJohn Forte 		ASSERT(fdestp != NULL);
7379fcf3ce44SJohn Forte 
7380fcf3ce44SJohn Forte 		/*
7381fcf3ce44SJohn Forte 		 * dequeue the pkt from the dest structure pkt list
7382fcf3ce44SJohn Forte 		 */
7383fcf3ce44SJohn Forte 		fcip_pkt->fcip_pkt_flags &= ~FCIP_PKT_IN_ABORT;
7384fcf3ce44SJohn Forte 		mutex_enter(&fdestp->fcipd_mutex);
7385fcf3ce44SJohn Forte 		rval = fcip_fdestp_dequeue_pkt(fdestp, fcip_pkt);
7386fcf3ce44SJohn Forte 		ASSERT(rval == 1);
7387fcf3ce44SJohn Forte 		mutex_exit(&fdestp->fcipd_mutex);
7388fcf3ce44SJohn Forte 
7389fcf3ce44SJohn Forte 		/*
7390fcf3ce44SJohn Forte 		 * Now cleanup the pkt and free the mblk
7391fcf3ce44SJohn Forte 		 */
7392fcf3ce44SJohn Forte 		fcip_pkt_free(fcip_pkt, 1);
7393fcf3ce44SJohn Forte 	} else {
7394fcf3ce44SJohn Forte 		/*
7395fcf3ce44SJohn Forte 		 * abort failed - just mark the pkt as done and
7396fcf3ce44SJohn Forte 		 * wait for it to complete in fcip_pkt_callback since
7397fcf3ce44SJohn Forte 		 * the pkt has already been xmitted by the FCA
7398fcf3ce44SJohn Forte 		 */
7399fcf3ce44SJohn Forte 		fcip_pkt->fcip_pkt_flags &= ~FCIP_PKT_IN_TIMEOUT;
7400fcf3ce44SJohn Forte 		if (fcip_pkt->fcip_pkt_flags & FCIP_PKT_RETURNED) {
7401fcf3ce44SJohn Forte 			fcip_pkt->fcip_pkt_flags &= ~FCIP_PKT_IN_ABORT;
7402fcf3ce44SJohn Forte 			mutex_enter(&fdestp->fcipd_mutex);
7403fcf3ce44SJohn Forte 			rval = fcip_fdestp_dequeue_pkt(fdestp, fcip_pkt);
7404fcf3ce44SJohn Forte 			ASSERT(rval == 1);
7405fcf3ce44SJohn Forte 			mutex_exit(&fdestp->fcipd_mutex);
7406fcf3ce44SJohn Forte 
7407fcf3ce44SJohn Forte 			fcip_pkt_free(fcip_pkt, 1);
7408fcf3ce44SJohn Forte 		}
7409fcf3ce44SJohn Forte 		return;
7410fcf3ce44SJohn Forte 	}
7411fcf3ce44SJohn Forte }
7412fcf3ce44SJohn Forte 
7413fcf3ce44SJohn Forte 
7414fcf3ce44SJohn Forte /*
7415fcf3ce44SJohn Forte  * Remove  a routing table entry marked for deferred removal. This routine
7416fcf3ce44SJohn Forte  * unlike fcip_pkt_timeout, is always called from a taskq context
7417fcf3ce44SJohn Forte  */
7418fcf3ce44SJohn Forte static void
7419fcf3ce44SJohn Forte fcip_rte_remove_deferred(void *arg)
7420fcf3ce44SJohn Forte {
7421fcf3ce44SJohn Forte 	struct fcip 			*fptr = (struct fcip *)arg;
7422fcf3ce44SJohn Forte 	int				hash_bucket;
7423fcf3ce44SJohn Forte 	struct fcip_dest 		*fdestp;
7424fcf3ce44SJohn Forte 	la_wwn_t			*pwwn;
7425fcf3ce44SJohn Forte 	int 				index;
7426fcf3ce44SJohn Forte 	struct fcip_routing_table 	*frtp, *frtp_next, *frtp_prev;
7427fcf3ce44SJohn Forte 
7428fcf3ce44SJohn Forte 
7429fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_rt_mutex);
7430fcf3ce44SJohn Forte 	for (index = 0; index < FCIP_RT_HASH_ELEMS; index++) {
7431fcf3ce44SJohn Forte 		frtp = fptr->fcip_rtable[index];
7432fcf3ce44SJohn Forte 		frtp_prev = NULL;
7433fcf3ce44SJohn Forte 		while (frtp) {
7434fcf3ce44SJohn Forte 			frtp_next = frtp->fcipr_next;
7435fcf3ce44SJohn Forte 
7436fcf3ce44SJohn Forte 			if (frtp->fcipr_state == FCIP_RT_RETIRED) {
7437fcf3ce44SJohn Forte 
7438fcf3ce44SJohn Forte 				pwwn = &frtp->fcipr_pwwn;
7439fcf3ce44SJohn Forte 				/*
7440fcf3ce44SJohn Forte 				 * Get hold of destination pointer
7441fcf3ce44SJohn Forte 				 */
7442fcf3ce44SJohn Forte 				mutex_enter(&fptr->fcip_dest_mutex);
7443fcf3ce44SJohn Forte 
7444fcf3ce44SJohn Forte 				hash_bucket = FCIP_DEST_HASH(pwwn->raw_wwn);
7445fcf3ce44SJohn Forte 				ASSERT(hash_bucket < FCIP_DEST_HASH_ELEMS);
7446fcf3ce44SJohn Forte 
7447fcf3ce44SJohn Forte 				fdestp = fptr->fcip_dest[hash_bucket];
7448fcf3ce44SJohn Forte 				while (fdestp != NULL) {
7449fcf3ce44SJohn Forte 					mutex_enter(&fdestp->fcipd_mutex);
7450fcf3ce44SJohn Forte 					if (fdestp->fcipd_rtable) {
7451fcf3ce44SJohn Forte 						if (fcip_wwn_compare(pwwn,
7452fcf3ce44SJohn Forte 						    &fdestp->fcipd_pwwn,
7453fcf3ce44SJohn Forte 						    FCIP_COMPARE_PWWN) == 0) {
7454fcf3ce44SJohn Forte 							mutex_exit(
7455fcf3ce44SJohn Forte 							&fdestp->fcipd_mutex);
7456fcf3ce44SJohn Forte 							break;
7457fcf3ce44SJohn Forte 						}
7458fcf3ce44SJohn Forte 					}
7459fcf3ce44SJohn Forte 					mutex_exit(&fdestp->fcipd_mutex);
7460fcf3ce44SJohn Forte 					fdestp = fdestp->fcipd_next;
7461fcf3ce44SJohn Forte 				}
7462fcf3ce44SJohn Forte 
7463fcf3ce44SJohn Forte 				mutex_exit(&fptr->fcip_dest_mutex);
7464fcf3ce44SJohn Forte 				if (fdestp == NULL) {
7465fcf3ce44SJohn Forte 					frtp_prev = frtp;
7466fcf3ce44SJohn Forte 					frtp = frtp_next;
7467fcf3ce44SJohn Forte 					continue;
7468fcf3ce44SJohn Forte 				}
7469fcf3ce44SJohn Forte 
7470fcf3ce44SJohn Forte 				mutex_enter(&fdestp->fcipd_mutex);
7471fcf3ce44SJohn Forte 				if (fdestp->fcipd_ncmds) {
7472fcf3ce44SJohn Forte 					/*
7473fcf3ce44SJohn Forte 					 * Instead of waiting to drain commands
7474fcf3ce44SJohn Forte 					 * let us revisit this RT entry in
7475fcf3ce44SJohn Forte 					 * the next pass.
7476fcf3ce44SJohn Forte 					 */
7477fcf3ce44SJohn Forte 					mutex_exit(&fdestp->fcipd_mutex);
7478fcf3ce44SJohn Forte 					frtp_prev = frtp;
7479fcf3ce44SJohn Forte 					frtp = frtp_next;
7480fcf3ce44SJohn Forte 					continue;
7481fcf3ce44SJohn Forte 				}
7482fcf3ce44SJohn Forte 
7483fcf3ce44SJohn Forte 				/*
7484fcf3ce44SJohn Forte 				 * We are clean, so remove the RTE
7485fcf3ce44SJohn Forte 				 */
7486fcf3ce44SJohn Forte 				fdestp->fcipd_rtable = NULL;
7487fcf3ce44SJohn Forte 				mutex_exit(&fdestp->fcipd_mutex);
7488fcf3ce44SJohn Forte 
7489fcf3ce44SJohn Forte 				FCIP_TNF_PROBE_2((fcip_rte_remove_deferred,
7490fcf3ce44SJohn Forte 					"fcip io", /* CSTYLED */,
7491fcf3ce44SJohn Forte 					tnf_string, msg,
7492fcf3ce44SJohn Forte 					"remove retired routing entry",
7493fcf3ce44SJohn Forte 					tnf_int, index, index));
7494fcf3ce44SJohn Forte 
7495fcf3ce44SJohn Forte 				if (frtp_prev == NULL) {
7496fcf3ce44SJohn Forte 					/* first element */
7497fcf3ce44SJohn Forte 					fptr->fcip_rtable[index] =
7498fcf3ce44SJohn Forte 					    frtp->fcipr_next;
7499fcf3ce44SJohn Forte 				} else {
7500fcf3ce44SJohn Forte 					frtp_prev->fcipr_next =
7501fcf3ce44SJohn Forte 					    frtp->fcipr_next;
7502fcf3ce44SJohn Forte 				}
7503fcf3ce44SJohn Forte 				kmem_free(frtp,
7504fcf3ce44SJohn Forte 				    sizeof (struct fcip_routing_table));
7505fcf3ce44SJohn Forte 
7506fcf3ce44SJohn Forte 				frtp = frtp_next;
7507fcf3ce44SJohn Forte 			} else {
7508fcf3ce44SJohn Forte 				frtp_prev = frtp;
7509fcf3ce44SJohn Forte 				frtp = frtp_next;
7510fcf3ce44SJohn Forte 			}
7511fcf3ce44SJohn Forte 		}
7512fcf3ce44SJohn Forte 	}
7513fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_rt_mutex);
7514fcf3ce44SJohn Forte 	/*
7515fcf3ce44SJohn Forte 	 * Clear the RTE_REMOVING flag
7516fcf3ce44SJohn Forte 	 */
7517fcf3ce44SJohn Forte 	mutex_enter(&fptr->fcip_mutex);
7518fcf3ce44SJohn Forte 	fptr->fcip_flags &= ~FCIP_RTE_REMOVING;
7519fcf3ce44SJohn Forte 	mutex_exit(&fptr->fcip_mutex);
7520fcf3ce44SJohn Forte }
7521fcf3ce44SJohn Forte 
7522fcf3ce44SJohn Forte /*
7523fcf3ce44SJohn Forte  * Walk through all the dest hash table entries and count up the total
7524fcf3ce44SJohn Forte  * no. of packets outstanding against a given port
7525fcf3ce44SJohn Forte  */
7526fcf3ce44SJohn Forte static int
7527fcf3ce44SJohn Forte fcip_port_get_num_pkts(struct fcip *fptr)
7528fcf3ce44SJohn Forte {
7529fcf3ce44SJohn Forte 	int 			num_cmds = 0;
7530fcf3ce44SJohn Forte 	int 			i;
7531fcf3ce44SJohn Forte 	struct fcip_dest	*fdestp;
7532fcf3ce44SJohn Forte 
7533fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&fptr->fcip_dest_mutex));
7534fcf3ce44SJohn Forte 
7535fcf3ce44SJohn Forte 	for (i = 0; i < FCIP_DEST_HASH_ELEMS; i++) {
7536fcf3ce44SJohn Forte 		fdestp = fptr->fcip_dest[i];
7537fcf3ce44SJohn Forte 		while (fdestp != NULL) {
7538fcf3ce44SJohn Forte 			mutex_enter(&fdestp->fcipd_mutex);
7539fcf3ce44SJohn Forte 
7540fcf3ce44SJohn Forte 			ASSERT(fdestp->fcipd_ncmds >= 0);
7541fcf3ce44SJohn Forte 
7542fcf3ce44SJohn Forte 			if (fdestp->fcipd_ncmds > 0) {
7543fcf3ce44SJohn Forte 				num_cmds += fdestp->fcipd_ncmds;
7544fcf3ce44SJohn Forte 			}
7545fcf3ce44SJohn Forte 			mutex_exit(&fdestp->fcipd_mutex);
7546fcf3ce44SJohn Forte 			fdestp = fdestp->fcipd_next;
7547fcf3ce44SJohn Forte 		}
7548fcf3ce44SJohn Forte 	}
7549fcf3ce44SJohn Forte 
7550fcf3ce44SJohn Forte 	return (num_cmds);
7551fcf3ce44SJohn Forte }
7552fcf3ce44SJohn Forte 
7553fcf3ce44SJohn Forte 
7554fcf3ce44SJohn Forte /*
7555fcf3ce44SJohn Forte  * Walk through the routing table for this state instance and see if there is a
7556fcf3ce44SJohn Forte  * PLOGI in progress for any of the entries. Return success even if we find one.
7557fcf3ce44SJohn Forte  */
7558fcf3ce44SJohn Forte static int
7559fcf3ce44SJohn Forte fcip_plogi_in_progress(struct fcip *fptr)
7560fcf3ce44SJohn Forte {
7561fcf3ce44SJohn Forte 	int				i;
7562fcf3ce44SJohn Forte 	struct fcip_routing_table	*frp;
7563fcf3ce44SJohn Forte 
7564fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&fptr->fcip_rt_mutex));
7565fcf3ce44SJohn Forte 
7566fcf3ce44SJohn Forte 	for (i = 0; i < FCIP_RT_HASH_ELEMS; i++) {
7567fcf3ce44SJohn Forte 		frp = fptr->fcip_rtable[i];
7568fcf3ce44SJohn Forte 		while (frp) {
7569fcf3ce44SJohn Forte 			if (frp->fcipr_state == FCIP_RT_LOGIN_PROGRESS) {
7570fcf3ce44SJohn Forte 				/* Found an entry where PLOGI is in progress */
7571fcf3ce44SJohn Forte 				return (1);
7572fcf3ce44SJohn Forte 			}
7573fcf3ce44SJohn Forte 			frp = frp->fcipr_next;
7574fcf3ce44SJohn Forte 		}
7575fcf3ce44SJohn Forte 	}
7576fcf3ce44SJohn Forte 
7577fcf3ce44SJohn Forte 	return (0);
7578fcf3ce44SJohn Forte }
7579fcf3ce44SJohn Forte 
7580fcf3ce44SJohn Forte /*
7581fcf3ce44SJohn Forte  * Walk through the fcip port global list and check if the given port exists in
7582fcf3ce44SJohn Forte  * the list. Returns "0" if port exists and "1" if otherwise.
7583fcf3ce44SJohn Forte  */
7584fcf3ce44SJohn Forte static int
7585fcf3ce44SJohn Forte fcip_check_port_exists(struct fcip *fptr)
7586fcf3ce44SJohn Forte {
7587fcf3ce44SJohn Forte 	fcip_port_info_t	*cur_fport;
7588fcf3ce44SJohn Forte 	fcip_port_info_t	*fport;
7589fcf3ce44SJohn Forte 
7590fcf3ce44SJohn Forte 	mutex_enter(&fcip_global_mutex);
7591fcf3ce44SJohn Forte 	fport = fptr->fcip_port_info;
7592fcf3ce44SJohn Forte 	cur_fport = fcip_port_head;
7593fcf3ce44SJohn Forte 	while (cur_fport != NULL) {
7594fcf3ce44SJohn Forte 		if (cur_fport == fport) {
7595fcf3ce44SJohn Forte 			/* Found */
7596fcf3ce44SJohn Forte 			mutex_exit(&fcip_global_mutex);
7597fcf3ce44SJohn Forte 			return (0);
7598fcf3ce44SJohn Forte 		} else {
7599fcf3ce44SJohn Forte 			cur_fport = cur_fport->fcipp_next;
7600fcf3ce44SJohn Forte 		}
7601fcf3ce44SJohn Forte 	}
7602fcf3ce44SJohn Forte 	mutex_exit(&fcip_global_mutex);
7603fcf3ce44SJohn Forte 
7604fcf3ce44SJohn Forte 	return (1);
7605fcf3ce44SJohn Forte }
7606fcf3ce44SJohn Forte 
7607fcf3ce44SJohn Forte /*
7608fcf3ce44SJohn Forte  * Constructor to initialize the sendup elements for callback into
7609fcf3ce44SJohn Forte  * modules upstream
7610fcf3ce44SJohn Forte  */
7611fcf3ce44SJohn Forte 
7612fcf3ce44SJohn Forte /* ARGSUSED */
7613fcf3ce44SJohn Forte static int
7614fcf3ce44SJohn Forte fcip_sendup_constructor(void *buf, void *arg, int flags)
7615fcf3ce44SJohn Forte {
7616fcf3ce44SJohn Forte 	struct fcip_sendup_elem	*msg_elem = (struct fcip_sendup_elem *)buf;
7617fcf3ce44SJohn Forte 	fcip_port_info_t	*fport = (fcip_port_info_t *)arg;
7618fcf3ce44SJohn Forte 
7619fcf3ce44SJohn Forte 	ASSERT(fport != NULL);
7620fcf3ce44SJohn Forte 
7621fcf3ce44SJohn Forte 	msg_elem->fcipsu_mp = NULL;
7622fcf3ce44SJohn Forte 	msg_elem->fcipsu_func = NULL;
7623fcf3ce44SJohn Forte 	msg_elem->fcipsu_next = NULL;
7624fcf3ce44SJohn Forte 
7625fcf3ce44SJohn Forte 	return (FCIP_SUCCESS);
7626fcf3ce44SJohn Forte }
7627