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