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