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