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