11991Sheppo /* 21991Sheppo * CDDL HEADER START 31991Sheppo * 41991Sheppo * The contents of this file are subject to the terms of the 51991Sheppo * Common Development and Distribution License (the "License"). 61991Sheppo * You may not use this file except in compliance with the License. 71991Sheppo * 81991Sheppo * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91991Sheppo * or http://www.opensolaris.org/os/licensing. 101991Sheppo * See the License for the specific language governing permissions 111991Sheppo * and limitations under the License. 121991Sheppo * 131991Sheppo * When distributing Covered Code, include this CDDL HEADER in each 141991Sheppo * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151991Sheppo * If applicable, add the following below this CDDL HEADER, with the 161991Sheppo * fields enclosed by brackets "[]" replaced with your own identifying 171991Sheppo * information: Portions Copyright [yyyy] [name of copyright owner] 181991Sheppo * 191991Sheppo * CDDL HEADER END 201991Sheppo */ 211991Sheppo 221991Sheppo /* 235944Sha137994 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 241991Sheppo * Use is subject to license terms. 251991Sheppo */ 261991Sheppo 271991Sheppo #pragma ident "%Z%%M% %I% %E% SMI" 281991Sheppo 291991Sheppo /* 302410Slm66018 * sun4v LDC Link Layer 311991Sheppo */ 321991Sheppo #include <sys/types.h> 331991Sheppo #include <sys/file.h> 341991Sheppo #include <sys/errno.h> 351991Sheppo #include <sys/open.h> 361991Sheppo #include <sys/cred.h> 371991Sheppo #include <sys/kmem.h> 381991Sheppo #include <sys/conf.h> 391991Sheppo #include <sys/cmn_err.h> 401991Sheppo #include <sys/ksynch.h> 411991Sheppo #include <sys/modctl.h> 421991Sheppo #include <sys/stat.h> /* needed for S_IFBLK and S_IFCHR */ 431991Sheppo #include <sys/debug.h> 441991Sheppo #include <sys/cred.h> 451991Sheppo #include <sys/promif.h> 461991Sheppo #include <sys/ddi.h> 471991Sheppo #include <sys/sunddi.h> 481991Sheppo #include <sys/cyclic.h> 491991Sheppo #include <sys/machsystm.h> 501991Sheppo #include <sys/vm.h> 511991Sheppo #include <sys/cpu.h> 521991Sheppo #include <sys/intreg.h> 531991Sheppo #include <sys/machcpuvar.h> 542531Snarayan #include <sys/mmu.h> 552531Snarayan #include <sys/pte.h> 562531Snarayan #include <vm/hat.h> 572531Snarayan #include <vm/as.h> 582531Snarayan #include <vm/hat_sfmmu.h> 592531Snarayan #include <sys/vm_machparam.h> 602531Snarayan #include <vm/seg_kmem.h> 612531Snarayan #include <vm/seg_kpm.h> 621991Sheppo #include <sys/note.h> 631991Sheppo #include <sys/ivintr.h> 641991Sheppo #include <sys/hypervisor_api.h> 651991Sheppo #include <sys/ldc.h> 661991Sheppo #include <sys/ldc_impl.h> 671991Sheppo #include <sys/cnex.h> 681991Sheppo #include <sys/hsvc.h> 695944Sha137994 #include <sys/sdt.h> 701991Sheppo 711991Sheppo /* Core internal functions */ 72*6408Sha137994 int i_ldc_h2v_error(int h_error); 73*6408Sha137994 void i_ldc_reset(ldc_chan_t *ldcp, boolean_t force_reset); 74*6408Sha137994 751991Sheppo static int i_ldc_txq_reconf(ldc_chan_t *ldcp); 762793Slm66018 static int i_ldc_rxq_reconf(ldc_chan_t *ldcp, boolean_t force_reset); 772841Snarayan static int i_ldc_rxq_drain(ldc_chan_t *ldcp); 781991Sheppo static void i_ldc_reset_state(ldc_chan_t *ldcp); 791991Sheppo 801991Sheppo static int i_ldc_get_tx_tail(ldc_chan_t *ldcp, uint64_t *tail); 814690Snarayan static void i_ldc_get_tx_head(ldc_chan_t *ldcp, uint64_t *head); 821991Sheppo static int i_ldc_set_tx_tail(ldc_chan_t *ldcp, uint64_t tail); 831991Sheppo static int i_ldc_set_rx_head(ldc_chan_t *ldcp, uint64_t head); 841991Sheppo static int i_ldc_send_pkt(ldc_chan_t *ldcp, uint8_t pkttype, uint8_t subtype, 851991Sheppo uint8_t ctrlmsg); 861991Sheppo 875944Sha137994 static int i_ldc_set_rxdq_head(ldc_chan_t *ldcp, uint64_t head); 885944Sha137994 static void i_ldc_rxdq_copy(ldc_chan_t *ldcp, uint64_t *head); 895944Sha137994 static uint64_t i_ldc_dq_rx_get_state(ldc_chan_t *ldcp, uint64_t *head, 905944Sha137994 uint64_t *tail, uint64_t *link_state); 915944Sha137994 static uint64_t i_ldc_hvq_rx_get_state(ldc_chan_t *ldcp, uint64_t *head, 925944Sha137994 uint64_t *tail, uint64_t *link_state); 935944Sha137994 static int i_ldc_rx_ackpeek(ldc_chan_t *ldcp, uint64_t rx_head, 945944Sha137994 uint64_t rx_tail); 955944Sha137994 static uint_t i_ldc_chkq(ldc_chan_t *ldcp); 965944Sha137994 971991Sheppo /* Interrupt handling functions */ 981991Sheppo static uint_t i_ldc_tx_hdlr(caddr_t arg1, caddr_t arg2); 991991Sheppo static uint_t i_ldc_rx_hdlr(caddr_t arg1, caddr_t arg2); 1005944Sha137994 static uint_t i_ldc_rx_process_hvq(ldc_chan_t *ldcp, boolean_t *notify_client, 1015944Sha137994 uint64_t *notify_event); 1021991Sheppo static void i_ldc_clear_intr(ldc_chan_t *ldcp, cnex_intrtype_t itype); 1031991Sheppo 1041991Sheppo /* Read method functions */ 1051991Sheppo static int i_ldc_read_raw(ldc_chan_t *ldcp, caddr_t target_bufp, size_t *sizep); 1061991Sheppo static int i_ldc_read_packet(ldc_chan_t *ldcp, caddr_t target_bufp, 1071991Sheppo size_t *sizep); 1081991Sheppo static int i_ldc_read_stream(ldc_chan_t *ldcp, caddr_t target_bufp, 1091991Sheppo size_t *sizep); 1101991Sheppo 1111991Sheppo /* Write method functions */ 1121991Sheppo static int i_ldc_write_raw(ldc_chan_t *ldcp, caddr_t target_bufp, 1131991Sheppo size_t *sizep); 1141991Sheppo static int i_ldc_write_packet(ldc_chan_t *ldcp, caddr_t target_bufp, 1151991Sheppo size_t *sizep); 1161991Sheppo static int i_ldc_write_stream(ldc_chan_t *ldcp, caddr_t target_bufp, 1171991Sheppo size_t *sizep); 1181991Sheppo 1191991Sheppo /* Pkt processing internal functions */ 1201991Sheppo static int i_ldc_check_seqid(ldc_chan_t *ldcp, ldc_msg_t *ldcmsg); 1211991Sheppo static int i_ldc_ctrlmsg(ldc_chan_t *ldcp, ldc_msg_t *ldcmsg); 1221991Sheppo static int i_ldc_process_VER(ldc_chan_t *ldcp, ldc_msg_t *msg); 1231991Sheppo static int i_ldc_process_RTS(ldc_chan_t *ldcp, ldc_msg_t *msg); 1241991Sheppo static int i_ldc_process_RTR(ldc_chan_t *ldcp, ldc_msg_t *msg); 1251991Sheppo static int i_ldc_process_RDX(ldc_chan_t *ldcp, ldc_msg_t *msg); 1261991Sheppo static int i_ldc_process_data_ACK(ldc_chan_t *ldcp, ldc_msg_t *msg); 1271991Sheppo 1281991Sheppo /* LDC Version */ 1291991Sheppo static ldc_ver_t ldc_versions[] = { {1, 0} }; 1301991Sheppo 1311991Sheppo /* number of supported versions */ 1321991Sheppo #define LDC_NUM_VERS (sizeof (ldc_versions) / sizeof (ldc_versions[0])) 1331991Sheppo 1345944Sha137994 /* Invalid value for the ldc_chan_t rx_ack_head field */ 1355944Sha137994 #define ACKPEEK_HEAD_INVALID ((uint64_t)-1) 1365944Sha137994 1375944Sha137994 1381991Sheppo /* Module State Pointer */ 139*6408Sha137994 ldc_soft_state_t *ldcssp; 1401991Sheppo 1411991Sheppo static struct modldrv md = { 1421991Sheppo &mod_miscops, /* This is a misc module */ 1431991Sheppo "sun4v LDC module v%I%", /* Name of the module */ 1441991Sheppo }; 1451991Sheppo 1461991Sheppo static struct modlinkage ml = { 1471991Sheppo MODREV_1, 1481991Sheppo &md, 1491991Sheppo NULL 1501991Sheppo }; 1511991Sheppo 1521991Sheppo static uint64_t ldc_sup_minor; /* Supported minor number */ 1531991Sheppo static hsvc_info_t ldc_hsvc = { 1541991Sheppo HSVC_REV_1, NULL, HSVC_GROUP_LDC, 1, 0, "ldc" 1551991Sheppo }; 1561991Sheppo 1572531Snarayan /* 1582410Slm66018 * The no. of MTU size messages that can be stored in 1592410Slm66018 * the LDC Tx queue. The number of Tx queue entries is 1602410Slm66018 * then computed as (mtu * mtu_msgs)/sizeof(queue_entry) 1612410Slm66018 */ 1622410Slm66018 uint64_t ldc_mtu_msgs = LDC_MTU_MSGS; 1632410Slm66018 1642410Slm66018 /* 1652410Slm66018 * The minimum queue length. This is the size of the smallest 1662410Slm66018 * LDC queue. If the computed value is less than this default, 1672410Slm66018 * the queue length is rounded up to 'ldc_queue_entries'. 1682410Slm66018 */ 1692410Slm66018 uint64_t ldc_queue_entries = LDC_QUEUE_ENTRIES; 1702410Slm66018 1712410Slm66018 /* 1725944Sha137994 * The length of the reliable-mode data queue in terms of the LDC 1735944Sha137994 * receive queue length. i.e., the number of times larger than the 1745944Sha137994 * LDC receive queue that the data queue should be. The HV receive 1755944Sha137994 * queue is required to be a power of 2 and this implementation 1765944Sha137994 * assumes the data queue will also be a power of 2. By making the 1775944Sha137994 * multiplier a power of 2, we ensure the data queue will be a 1785944Sha137994 * power of 2. We use a multiplier because the receive queue is 1795944Sha137994 * sized to be sane relative to the MTU and the same is needed for 1805944Sha137994 * the data queue. 1815944Sha137994 */ 1825944Sha137994 uint64_t ldc_rxdq_multiplier = LDC_RXDQ_MULTIPLIER; 1835944Sha137994 1845944Sha137994 /* 1852410Slm66018 * LDC retry count and delay - when the HV returns EWOULDBLOCK 1862410Slm66018 * the operation is retried 'ldc_max_retries' times with a 1872410Slm66018 * wait of 'ldc_delay' usecs between each retry. 1882032Slm66018 */ 1892032Slm66018 int ldc_max_retries = LDC_MAX_RETRIES; 1902032Slm66018 clock_t ldc_delay = LDC_DELAY; 1912032Slm66018 1923151Ssg70180 /* 1933151Ssg70180 * delay between each retry of channel unregistration in 1943151Ssg70180 * ldc_close(), to wait for pending interrupts to complete. 1953151Ssg70180 */ 1963151Ssg70180 clock_t ldc_close_delay = LDC_CLOSE_DELAY; 1973151Ssg70180 1981991Sheppo #ifdef DEBUG 1991991Sheppo 2001991Sheppo /* 2011991Sheppo * Print debug messages 2021991Sheppo * 2031991Sheppo * set ldcdbg to 0x7 for enabling all msgs 2041991Sheppo * 0x4 - Warnings 2051991Sheppo * 0x2 - All debug messages 2061991Sheppo * 0x1 - Minimal debug messages 2071991Sheppo * 2081991Sheppo * set ldcdbgchan to the channel number you want to debug 2091991Sheppo * setting it to -1 prints debug messages for all channels 2101991Sheppo * NOTE: ldcdbgchan has no effect on error messages 2111991Sheppo */ 2121991Sheppo 2131991Sheppo int ldcdbg = 0x0; 2141991Sheppo int64_t ldcdbgchan = DBG_ALL_LDCS; 2153560Snarayan uint64_t ldc_inject_err_flag = 0; 2161991Sheppo 217*6408Sha137994 void 2181991Sheppo ldcdebug(int64_t id, const char *fmt, ...) 2191991Sheppo { 2201991Sheppo char buf[512]; 2211991Sheppo va_list ap; 2221991Sheppo 2231991Sheppo /* 2241991Sheppo * Do not return if, 2251991Sheppo * caller wants to print it anyway - (id == DBG_ALL_LDCS) 2261991Sheppo * debug channel is set to all LDCs - (ldcdbgchan == DBG_ALL_LDCS) 2271991Sheppo * debug channel = caller specified channel 2281991Sheppo */ 2291991Sheppo if ((id != DBG_ALL_LDCS) && 2301991Sheppo (ldcdbgchan != DBG_ALL_LDCS) && 2311991Sheppo (ldcdbgchan != id)) { 2321991Sheppo return; 2331991Sheppo } 2341991Sheppo 2351991Sheppo va_start(ap, fmt); 2361991Sheppo (void) vsprintf(buf, fmt, ap); 2371991Sheppo va_end(ap); 2381991Sheppo 2392793Slm66018 cmn_err(CE_CONT, "?%s", buf); 2402793Slm66018 } 2412793Slm66018 2423560Snarayan #define LDC_ERR_RESET 0x1 2433560Snarayan #define LDC_ERR_PKTLOSS 0x2 2445944Sha137994 #define LDC_ERR_DQFULL 0x4 2453560Snarayan 2462793Slm66018 static boolean_t 2473560Snarayan ldc_inject_error(ldc_chan_t *ldcp, uint64_t error) 2482793Slm66018 { 2492793Slm66018 if ((ldcdbgchan != DBG_ALL_LDCS) && (ldcdbgchan != ldcp->id)) 2502793Slm66018 return (B_FALSE); 2512793Slm66018 2523560Snarayan if ((ldc_inject_err_flag & error) == 0) 2532793Slm66018 return (B_FALSE); 2542793Slm66018 2552793Slm66018 /* clear the injection state */ 2563560Snarayan ldc_inject_err_flag &= ~error; 2572793Slm66018 2582793Slm66018 return (B_TRUE); 2591991Sheppo } 2601991Sheppo 2611991Sheppo #define D1 \ 2621991Sheppo if (ldcdbg & 0x01) \ 2631991Sheppo ldcdebug 2641991Sheppo 2651991Sheppo #define D2 \ 2661991Sheppo if (ldcdbg & 0x02) \ 2671991Sheppo ldcdebug 2681991Sheppo 2691991Sheppo #define DWARN \ 2701991Sheppo if (ldcdbg & 0x04) \ 2711991Sheppo ldcdebug 2721991Sheppo 2731991Sheppo #define DUMP_PAYLOAD(id, addr) \ 2741991Sheppo { \ 2751991Sheppo char buf[65*3]; \ 2761991Sheppo int i; \ 2771991Sheppo uint8_t *src = (uint8_t *)addr; \ 2781991Sheppo for (i = 0; i < 64; i++, src++) \ 2791991Sheppo (void) sprintf(&buf[i * 3], "|%02x", *src); \ 2801991Sheppo (void) sprintf(&buf[i * 3], "|\n"); \ 2811991Sheppo D2((id), "payload: %s", buf); \ 2821991Sheppo } 2831991Sheppo 2841991Sheppo #define DUMP_LDC_PKT(c, s, addr) \ 2851991Sheppo { \ 2861991Sheppo ldc_msg_t *msg = (ldc_msg_t *)(addr); \ 2871991Sheppo uint32_t mid = ((c)->mode != LDC_MODE_RAW) ? msg->seqid : 0; \ 2881991Sheppo if (msg->type == LDC_DATA) { \ 2891991Sheppo D2((c)->id, "%s: msg%d (/%x/%x/%x/,env[%c%c,sz=%d])", \ 2901991Sheppo (s), mid, msg->type, msg->stype, msg->ctrl, \ 2911991Sheppo (msg->env & LDC_FRAG_START) ? 'B' : ' ', \ 2921991Sheppo (msg->env & LDC_FRAG_STOP) ? 'E' : ' ', \ 2931991Sheppo (msg->env & LDC_LEN_MASK)); \ 2941991Sheppo } else { \ 2951991Sheppo D2((c)->id, "%s: msg%d (/%x/%x/%x/,env=%x)", (s), \ 2961991Sheppo mid, msg->type, msg->stype, msg->ctrl, msg->env); \ 2971991Sheppo } \ 2981991Sheppo } 2991991Sheppo 3003560Snarayan #define LDC_INJECT_RESET(_ldcp) ldc_inject_error(_ldcp, LDC_ERR_RESET) 3013560Snarayan #define LDC_INJECT_PKTLOSS(_ldcp) ldc_inject_error(_ldcp, LDC_ERR_PKTLOSS) 3025944Sha137994 #define LDC_INJECT_DQFULL(_ldcp) ldc_inject_error(_ldcp, LDC_ERR_DQFULL) 3032793Slm66018 3041991Sheppo #else 3051991Sheppo 3061991Sheppo #define DBG_ALL_LDCS -1 3071991Sheppo 3081991Sheppo #define D1 3091991Sheppo #define D2 3101991Sheppo #define DWARN 3111991Sheppo 3121991Sheppo #define DUMP_PAYLOAD(id, addr) 3131991Sheppo #define DUMP_LDC_PKT(c, s, addr) 3141991Sheppo 3152793Slm66018 #define LDC_INJECT_RESET(_ldcp) (B_FALSE) 3163560Snarayan #define LDC_INJECT_PKTLOSS(_ldcp) (B_FALSE) 3175944Sha137994 #define LDC_INJECT_DQFULL(_ldcp) (B_FALSE) 3182793Slm66018 3191991Sheppo #endif 3201991Sheppo 3215944Sha137994 /* 3225944Sha137994 * dtrace SDT probes to ease tracing of the rx data queue and HV queue 3235944Sha137994 * lengths. Just pass the head, tail, and entries values so that the 3245944Sha137994 * length can be calculated in a dtrace script when the probe is enabled. 3255944Sha137994 */ 3265944Sha137994 #define TRACE_RXDQ_LENGTH(ldcp) \ 3275944Sha137994 DTRACE_PROBE4(rxdq__size, \ 3285944Sha137994 uint64_t, ldcp->id, \ 3295944Sha137994 uint64_t, ldcp->rx_dq_head, \ 3305944Sha137994 uint64_t, ldcp->rx_dq_tail, \ 3315944Sha137994 uint64_t, ldcp->rx_dq_entries) 3325944Sha137994 3335944Sha137994 #define TRACE_RXHVQ_LENGTH(ldcp, head, tail) \ 3345944Sha137994 DTRACE_PROBE4(rxhvq__size, \ 3355944Sha137994 uint64_t, ldcp->id, \ 3365944Sha137994 uint64_t, head, \ 3375944Sha137994 uint64_t, tail, \ 3385944Sha137994 uint64_t, ldcp->rx_q_entries) 3395944Sha137994 3405944Sha137994 /* A dtrace SDT probe to ease tracing of data queue copy operations */ 3415944Sha137994 #define TRACE_RXDQ_COPY(ldcp, bytes) \ 3425944Sha137994 DTRACE_PROBE2(rxdq__copy, uint64_t, ldcp->id, uint64_t, bytes) \ 3435944Sha137994 3445944Sha137994 /* The amount of contiguous space at the tail of the queue */ 3455944Sha137994 #define Q_CONTIG_SPACE(head, tail, size) \ 3465944Sha137994 ((head) <= (tail) ? ((size) - (tail)) : \ 3475944Sha137994 ((head) - (tail) - LDC_PACKET_SIZE)) 3485944Sha137994 3491991Sheppo #define ZERO_PKT(p) \ 3501991Sheppo bzero((p), sizeof (ldc_msg_t)); 3511991Sheppo 3521991Sheppo #define IDX2COOKIE(idx, pg_szc, pg_shift) \ 3531991Sheppo (((pg_szc) << LDC_COOKIE_PGSZC_SHIFT) | ((idx) << (pg_shift))) 3541991Sheppo 3551991Sheppo int 3561991Sheppo _init(void) 3571991Sheppo { 3581991Sheppo int status; 3591991Sheppo 3601991Sheppo status = hsvc_register(&ldc_hsvc, &ldc_sup_minor); 3611991Sheppo if (status != 0) { 3624423Sjb145095 cmn_err(CE_NOTE, "!%s: cannot negotiate hypervisor LDC services" 3631991Sheppo " group: 0x%lx major: %ld minor: %ld errno: %d", 3641991Sheppo ldc_hsvc.hsvc_modname, ldc_hsvc.hsvc_group, 3651991Sheppo ldc_hsvc.hsvc_major, ldc_hsvc.hsvc_minor, status); 3661991Sheppo return (-1); 3671991Sheppo } 3681991Sheppo 3691991Sheppo /* allocate soft state structure */ 3701991Sheppo ldcssp = kmem_zalloc(sizeof (ldc_soft_state_t), KM_SLEEP); 3711991Sheppo 3721991Sheppo /* Link the module into the system */ 3731991Sheppo status = mod_install(&ml); 3741991Sheppo if (status != 0) { 3751991Sheppo kmem_free(ldcssp, sizeof (ldc_soft_state_t)); 3761991Sheppo return (status); 3771991Sheppo } 3781991Sheppo 3791991Sheppo /* Initialize the LDC state structure */ 3801991Sheppo mutex_init(&ldcssp->lock, NULL, MUTEX_DRIVER, NULL); 3811991Sheppo 3821991Sheppo mutex_enter(&ldcssp->lock); 3831991Sheppo 3842531Snarayan /* Create a cache for memory handles */ 3852531Snarayan ldcssp->memhdl_cache = kmem_cache_create("ldc_memhdl_cache", 3862531Snarayan sizeof (ldc_mhdl_t), 0, NULL, NULL, NULL, NULL, NULL, 0); 3872531Snarayan if (ldcssp->memhdl_cache == NULL) { 3882531Snarayan DWARN(DBG_ALL_LDCS, "_init: ldc_memhdl cache create failed\n"); 3892531Snarayan mutex_exit(&ldcssp->lock); 3902531Snarayan return (-1); 3912531Snarayan } 3922531Snarayan 3932531Snarayan /* Create cache for memory segment structures */ 3942531Snarayan ldcssp->memseg_cache = kmem_cache_create("ldc_memseg_cache", 3952531Snarayan sizeof (ldc_memseg_t), 0, NULL, NULL, NULL, NULL, NULL, 0); 3962531Snarayan if (ldcssp->memseg_cache == NULL) { 3972531Snarayan DWARN(DBG_ALL_LDCS, "_init: ldc_memseg cache create failed\n"); 3982531Snarayan mutex_exit(&ldcssp->lock); 3992531Snarayan return (-1); 4002531Snarayan } 4012531Snarayan 4022531Snarayan 4031991Sheppo ldcssp->channel_count = 0; 4041991Sheppo ldcssp->channels_open = 0; 4051991Sheppo ldcssp->chan_list = NULL; 4061991Sheppo ldcssp->dring_list = NULL; 4071991Sheppo 4081991Sheppo mutex_exit(&ldcssp->lock); 4091991Sheppo 4101991Sheppo return (0); 4111991Sheppo } 4121991Sheppo 4131991Sheppo int 4141991Sheppo _info(struct modinfo *modinfop) 4151991Sheppo { 4161991Sheppo /* Report status of the dynamically loadable driver module */ 4171991Sheppo return (mod_info(&ml, modinfop)); 4181991Sheppo } 4191991Sheppo 4201991Sheppo int 4211991Sheppo _fini(void) 4221991Sheppo { 4231991Sheppo int rv, status; 4244690Snarayan ldc_chan_t *tmp_ldcp, *ldcp; 4254690Snarayan ldc_dring_t *tmp_dringp, *dringp; 4261991Sheppo ldc_mem_info_t minfo; 4271991Sheppo 4281991Sheppo /* Unlink the driver module from the system */ 4291991Sheppo status = mod_remove(&ml); 4301991Sheppo if (status) { 4311991Sheppo DWARN(DBG_ALL_LDCS, "_fini: mod_remove failed\n"); 4321991Sheppo return (EIO); 4331991Sheppo } 4341991Sheppo 4351991Sheppo /* Free descriptor rings */ 4361991Sheppo dringp = ldcssp->dring_list; 4371991Sheppo while (dringp != NULL) { 4384690Snarayan tmp_dringp = dringp->next; 4391991Sheppo 4401991Sheppo rv = ldc_mem_dring_info((ldc_dring_handle_t)dringp, &minfo); 4411991Sheppo if (rv == 0 && minfo.status != LDC_UNBOUND) { 4421991Sheppo if (minfo.status == LDC_BOUND) { 4431991Sheppo (void) ldc_mem_dring_unbind( 4444690Snarayan (ldc_dring_handle_t)dringp); 4451991Sheppo } 4461991Sheppo if (minfo.status == LDC_MAPPED) { 4471991Sheppo (void) ldc_mem_dring_unmap( 4484690Snarayan (ldc_dring_handle_t)dringp); 4491991Sheppo } 4501991Sheppo } 4511991Sheppo 4521991Sheppo (void) ldc_mem_dring_destroy((ldc_dring_handle_t)dringp); 4534690Snarayan dringp = tmp_dringp; 4541991Sheppo } 4551991Sheppo ldcssp->dring_list = NULL; 4561991Sheppo 4574690Snarayan /* close and finalize channels */ 4584690Snarayan ldcp = ldcssp->chan_list; 4594690Snarayan while (ldcp != NULL) { 4604690Snarayan tmp_ldcp = ldcp->next; 4614690Snarayan 4624690Snarayan (void) ldc_close((ldc_handle_t)ldcp); 4634690Snarayan (void) ldc_fini((ldc_handle_t)ldcp); 4644690Snarayan 4654690Snarayan ldcp = tmp_ldcp; 4664690Snarayan } 4674690Snarayan ldcssp->chan_list = NULL; 4684690Snarayan 4692531Snarayan /* Destroy kmem caches */ 4702531Snarayan kmem_cache_destroy(ldcssp->memhdl_cache); 4712531Snarayan kmem_cache_destroy(ldcssp->memseg_cache); 4722531Snarayan 4731991Sheppo /* 4741991Sheppo * We have successfully "removed" the driver. 4751991Sheppo * Destroying soft states 4761991Sheppo */ 4771991Sheppo mutex_destroy(&ldcssp->lock); 4781991Sheppo kmem_free(ldcssp, sizeof (ldc_soft_state_t)); 4791991Sheppo 4801991Sheppo (void) hsvc_unregister(&ldc_hsvc); 4811991Sheppo 4821991Sheppo return (status); 4831991Sheppo } 4841991Sheppo 4851991Sheppo /* -------------------------------------------------------------------------- */ 4861991Sheppo 4871991Sheppo /* 4882410Slm66018 * LDC Link Layer Internal Functions 4891991Sheppo */ 4901991Sheppo 4911991Sheppo /* 4921991Sheppo * Translate HV Errors to sun4v error codes 4931991Sheppo */ 494*6408Sha137994 int 4951991Sheppo i_ldc_h2v_error(int h_error) 4961991Sheppo { 4971991Sheppo switch (h_error) { 4981991Sheppo 4991991Sheppo case H_EOK: 5001991Sheppo return (0); 5011991Sheppo 5021991Sheppo case H_ENORADDR: 5031991Sheppo return (EFAULT); 5041991Sheppo 5051991Sheppo case H_EBADPGSZ: 5061991Sheppo case H_EINVAL: 5071991Sheppo return (EINVAL); 5081991Sheppo 5091991Sheppo case H_EWOULDBLOCK: 5101991Sheppo return (EWOULDBLOCK); 5111991Sheppo 5121991Sheppo case H_ENOACCESS: 5131991Sheppo case H_ENOMAP: 5141991Sheppo return (EACCES); 5151991Sheppo 5161991Sheppo case H_EIO: 5171991Sheppo case H_ECPUERROR: 5181991Sheppo return (EIO); 5191991Sheppo 5201991Sheppo case H_ENOTSUPPORTED: 5211991Sheppo return (ENOTSUP); 5221991Sheppo 5231991Sheppo case H_ETOOMANY: 5241991Sheppo return (ENOSPC); 5251991Sheppo 5261991Sheppo case H_ECHANNEL: 5271991Sheppo return (ECHRNG); 5281991Sheppo default: 5291991Sheppo break; 5301991Sheppo } 5311991Sheppo 5321991Sheppo return (EIO); 5331991Sheppo } 5341991Sheppo 5351991Sheppo /* 5361991Sheppo * Reconfigure the transmit queue 5371991Sheppo */ 5381991Sheppo static int 5391991Sheppo i_ldc_txq_reconf(ldc_chan_t *ldcp) 5401991Sheppo { 5411991Sheppo int rv; 5421991Sheppo 5431991Sheppo ASSERT(MUTEX_HELD(&ldcp->lock)); 5442336Snarayan ASSERT(MUTEX_HELD(&ldcp->tx_lock)); 5452336Snarayan 5461991Sheppo rv = hv_ldc_tx_qconf(ldcp->id, ldcp->tx_q_ra, ldcp->tx_q_entries); 5471991Sheppo if (rv) { 5481991Sheppo cmn_err(CE_WARN, 5492793Slm66018 "i_ldc_txq_reconf: (0x%lx) cannot set qconf", ldcp->id); 5501991Sheppo return (EIO); 5511991Sheppo } 5521991Sheppo rv = hv_ldc_tx_get_state(ldcp->id, &(ldcp->tx_head), 5531991Sheppo &(ldcp->tx_tail), &(ldcp->link_state)); 5541991Sheppo if (rv) { 5551991Sheppo cmn_err(CE_WARN, 5562793Slm66018 "i_ldc_txq_reconf: (0x%lx) cannot get qptrs", ldcp->id); 5571991Sheppo return (EIO); 5581991Sheppo } 5592793Slm66018 D1(ldcp->id, "i_ldc_txq_reconf: (0x%llx) h=0x%llx,t=0x%llx," 5601991Sheppo "s=0x%llx\n", ldcp->id, ldcp->tx_head, ldcp->tx_tail, 5611991Sheppo ldcp->link_state); 5621991Sheppo 5631991Sheppo return (0); 5641991Sheppo } 5651991Sheppo 5661991Sheppo /* 5671991Sheppo * Reconfigure the receive queue 5681991Sheppo */ 5691991Sheppo static int 5702793Slm66018 i_ldc_rxq_reconf(ldc_chan_t *ldcp, boolean_t force_reset) 5711991Sheppo { 5721991Sheppo int rv; 5731991Sheppo uint64_t rx_head, rx_tail; 5741991Sheppo 5751991Sheppo ASSERT(MUTEX_HELD(&ldcp->lock)); 5761991Sheppo rv = hv_ldc_rx_get_state(ldcp->id, &rx_head, &rx_tail, 5771991Sheppo &(ldcp->link_state)); 5781991Sheppo if (rv) { 5791991Sheppo cmn_err(CE_WARN, 5802793Slm66018 "i_ldc_rxq_reconf: (0x%lx) cannot get state", 5811991Sheppo ldcp->id); 5821991Sheppo return (EIO); 5831991Sheppo } 5841991Sheppo 5852793Slm66018 if (force_reset || (ldcp->tstate & ~TS_IN_RESET) == TS_UP) { 5861991Sheppo rv = hv_ldc_rx_qconf(ldcp->id, ldcp->rx_q_ra, 5874690Snarayan ldcp->rx_q_entries); 5881991Sheppo if (rv) { 5891991Sheppo cmn_err(CE_WARN, 5902793Slm66018 "i_ldc_rxq_reconf: (0x%lx) cannot set qconf", 5911991Sheppo ldcp->id); 5921991Sheppo return (EIO); 5931991Sheppo } 5942793Slm66018 D1(ldcp->id, "i_ldc_rxq_reconf: (0x%llx) completed q reconf", 5951991Sheppo ldcp->id); 5961991Sheppo } 5971991Sheppo 5981991Sheppo return (0); 5991991Sheppo } 6001991Sheppo 6012841Snarayan 6022841Snarayan /* 6032841Snarayan * Drain the contents of the receive queue 6042841Snarayan */ 6052841Snarayan static int 6062841Snarayan i_ldc_rxq_drain(ldc_chan_t *ldcp) 6072841Snarayan { 6082841Snarayan int rv; 6092841Snarayan uint64_t rx_head, rx_tail; 6102841Snarayan 6112841Snarayan ASSERT(MUTEX_HELD(&ldcp->lock)); 6122841Snarayan rv = hv_ldc_rx_get_state(ldcp->id, &rx_head, &rx_tail, 6132841Snarayan &(ldcp->link_state)); 6142841Snarayan if (rv) { 6152841Snarayan cmn_err(CE_WARN, "i_ldc_rxq_drain: (0x%lx) cannot get state", 6162841Snarayan ldcp->id); 6172841Snarayan return (EIO); 6182841Snarayan } 6192841Snarayan 6202841Snarayan /* flush contents by setting the head = tail */ 6212841Snarayan return (i_ldc_set_rx_head(ldcp, rx_tail)); 6222841Snarayan } 6232841Snarayan 6242841Snarayan 6251991Sheppo /* 6261991Sheppo * Reset LDC state structure and its contents 6271991Sheppo */ 6281991Sheppo static void 6291991Sheppo i_ldc_reset_state(ldc_chan_t *ldcp) 6301991Sheppo { 6311991Sheppo ASSERT(MUTEX_HELD(&ldcp->lock)); 6321991Sheppo ldcp->last_msg_snt = LDC_INIT_SEQID; 6331991Sheppo ldcp->last_ack_rcd = 0; 6341991Sheppo ldcp->last_msg_rcd = 0; 6351991Sheppo ldcp->tx_ackd_head = ldcp->tx_head; 6365944Sha137994 ldcp->stream_remains = 0; 6371991Sheppo ldcp->next_vidx = 0; 6381991Sheppo ldcp->hstate = 0; 6391991Sheppo ldcp->tstate = TS_OPEN; 6401991Sheppo ldcp->status = LDC_OPEN; 6415944Sha137994 ldcp->rx_ack_head = ACKPEEK_HEAD_INVALID; 6425944Sha137994 ldcp->rx_dq_head = 0; 6435944Sha137994 ldcp->rx_dq_tail = 0; 6441991Sheppo 6451991Sheppo if (ldcp->link_state == LDC_CHANNEL_UP || 6461991Sheppo ldcp->link_state == LDC_CHANNEL_RESET) { 6471991Sheppo 6481991Sheppo if (ldcp->mode == LDC_MODE_RAW) { 6491991Sheppo ldcp->status = LDC_UP; 6501991Sheppo ldcp->tstate = TS_UP; 6511991Sheppo } else { 6521991Sheppo ldcp->status = LDC_READY; 6531991Sheppo ldcp->tstate |= TS_LINK_READY; 6541991Sheppo } 6551991Sheppo } 6561991Sheppo } 6571991Sheppo 6581991Sheppo /* 6591991Sheppo * Reset a LDC channel 6601991Sheppo */ 661*6408Sha137994 void 6622793Slm66018 i_ldc_reset(ldc_chan_t *ldcp, boolean_t force_reset) 6631991Sheppo { 6643560Snarayan DWARN(ldcp->id, "i_ldc_reset: (0x%llx) channel reset\n", ldcp->id); 6651991Sheppo 6662336Snarayan ASSERT(MUTEX_HELD(&ldcp->lock)); 6672336Snarayan ASSERT(MUTEX_HELD(&ldcp->tx_lock)); 6682336Snarayan 6692793Slm66018 /* reconfig Tx and Rx queues */ 6701991Sheppo (void) i_ldc_txq_reconf(ldcp); 6712793Slm66018 (void) i_ldc_rxq_reconf(ldcp, force_reset); 6722793Slm66018 6732793Slm66018 /* Clear Tx and Rx interrupts */ 6742793Slm66018 (void) i_ldc_clear_intr(ldcp, CNEX_TX_INTR); 6752793Slm66018 (void) i_ldc_clear_intr(ldcp, CNEX_RX_INTR); 6762793Slm66018 6772793Slm66018 /* Reset channel state */ 6781991Sheppo i_ldc_reset_state(ldcp); 6792793Slm66018 6802793Slm66018 /* Mark channel in reset */ 6812793Slm66018 ldcp->tstate |= TS_IN_RESET; 6821991Sheppo } 6831991Sheppo 6842531Snarayan 6851991Sheppo /* 6861991Sheppo * Clear pending interrupts 6871991Sheppo */ 6881991Sheppo static void 6891991Sheppo i_ldc_clear_intr(ldc_chan_t *ldcp, cnex_intrtype_t itype) 6901991Sheppo { 6911991Sheppo ldc_cnex_t *cinfo = &ldcssp->cinfo; 6921991Sheppo 6931991Sheppo ASSERT(MUTEX_HELD(&ldcp->lock)); 6942793Slm66018 ASSERT(cinfo->dip != NULL); 6952793Slm66018 6962793Slm66018 switch (itype) { 6972793Slm66018 case CNEX_TX_INTR: 6982531Snarayan /* check Tx interrupt */ 6992793Slm66018 if (ldcp->tx_intr_state) 7002793Slm66018 ldcp->tx_intr_state = LDC_INTR_NONE; 7012793Slm66018 else 7022793Slm66018 return; 7032793Slm66018 break; 7042793Slm66018 7052793Slm66018 case CNEX_RX_INTR: 7062531Snarayan /* check Rx interrupt */ 7072793Slm66018 if (ldcp->rx_intr_state) 7082793Slm66018 ldcp->rx_intr_state = LDC_INTR_NONE; 7092793Slm66018 else 7102793Slm66018 return; 7112793Slm66018 break; 7122793Slm66018 } 7132793Slm66018 7142793Slm66018 (void) cinfo->clr_intr(cinfo->dip, ldcp->id, itype); 7152793Slm66018 D2(ldcp->id, 7162793Slm66018 "i_ldc_clear_intr: (0x%llx) cleared 0x%x intr\n", 7172793Slm66018 ldcp->id, itype); 7181991Sheppo } 7191991Sheppo 7201991Sheppo /* 7211991Sheppo * Set the receive queue head 7222032Slm66018 * Resets connection and returns an error if it fails. 7231991Sheppo */ 7241991Sheppo static int 7251991Sheppo i_ldc_set_rx_head(ldc_chan_t *ldcp, uint64_t head) 7261991Sheppo { 7272032Slm66018 int rv; 7282032Slm66018 int retries; 7291991Sheppo 7301991Sheppo ASSERT(MUTEX_HELD(&ldcp->lock)); 7312032Slm66018 for (retries = 0; retries < ldc_max_retries; retries++) { 7322032Slm66018 7332032Slm66018 if ((rv = hv_ldc_rx_set_qhead(ldcp->id, head)) == 0) 7342032Slm66018 return (0); 7352032Slm66018 7362032Slm66018 if (rv != H_EWOULDBLOCK) 7372032Slm66018 break; 7382032Slm66018 7392032Slm66018 /* wait for ldc_delay usecs */ 7402032Slm66018 drv_usecwait(ldc_delay); 7412032Slm66018 } 7422032Slm66018 7432032Slm66018 cmn_err(CE_WARN, "ldc_rx_set_qhead: (0x%lx) cannot set qhead 0x%lx", 7444690Snarayan ldcp->id, head); 7452336Snarayan mutex_enter(&ldcp->tx_lock); 7462793Slm66018 i_ldc_reset(ldcp, B_TRUE); 7472336Snarayan mutex_exit(&ldcp->tx_lock); 7482032Slm66018 7492032Slm66018 return (ECONNRESET); 7501991Sheppo } 7511991Sheppo 7524690Snarayan /* 7534690Snarayan * Returns the tx_head to be used for transfer 7544690Snarayan */ 7554690Snarayan static void 7564690Snarayan i_ldc_get_tx_head(ldc_chan_t *ldcp, uint64_t *head) 7574690Snarayan { 7584690Snarayan ldc_msg_t *pkt; 7594690Snarayan 7604690Snarayan ASSERT(MUTEX_HELD(&ldcp->tx_lock)); 7614690Snarayan 7624690Snarayan /* get current Tx head */ 7634690Snarayan *head = ldcp->tx_head; 7644690Snarayan 7654690Snarayan /* 7664690Snarayan * Reliable mode will use the ACKd head instead of the regular tx_head. 7674690Snarayan * Also in Reliable mode, advance ackd_head for all non DATA/INFO pkts, 7684690Snarayan * up to the current location of tx_head. This needs to be done 7694690Snarayan * as the peer will only ACK DATA/INFO pkts. 7704690Snarayan */ 771*6408Sha137994 if (ldcp->mode == LDC_MODE_RELIABLE) { 7724690Snarayan while (ldcp->tx_ackd_head != ldcp->tx_head) { 7734690Snarayan pkt = (ldc_msg_t *)(ldcp->tx_q_va + ldcp->tx_ackd_head); 7744690Snarayan if ((pkt->type & LDC_DATA) && (pkt->stype & LDC_INFO)) { 7754690Snarayan break; 7764690Snarayan } 7774690Snarayan /* advance ACKd head */ 7784690Snarayan ldcp->tx_ackd_head = 7794690Snarayan (ldcp->tx_ackd_head + LDC_PACKET_SIZE) % 7804690Snarayan (ldcp->tx_q_entries << LDC_PACKET_SHIFT); 7814690Snarayan } 7824690Snarayan *head = ldcp->tx_ackd_head; 7834690Snarayan } 7844690Snarayan } 7851991Sheppo 7861991Sheppo /* 7871991Sheppo * Returns the tx_tail to be used for transfer 7881991Sheppo * Re-reads the TX queue ptrs if and only if the 7891991Sheppo * the cached head and tail are equal (queue is full) 7901991Sheppo */ 7911991Sheppo static int 7921991Sheppo i_ldc_get_tx_tail(ldc_chan_t *ldcp, uint64_t *tail) 7931991Sheppo { 7941991Sheppo int rv; 7951991Sheppo uint64_t current_head, new_tail; 7961991Sheppo 7972336Snarayan ASSERT(MUTEX_HELD(&ldcp->tx_lock)); 7981991Sheppo /* Read the head and tail ptrs from HV */ 7991991Sheppo rv = hv_ldc_tx_get_state(ldcp->id, 8001991Sheppo &ldcp->tx_head, &ldcp->tx_tail, &ldcp->link_state); 8011991Sheppo if (rv) { 8021991Sheppo cmn_err(CE_WARN, 8031991Sheppo "i_ldc_get_tx_tail: (0x%lx) cannot read qptrs\n", 8041991Sheppo ldcp->id); 8051991Sheppo return (EIO); 8061991Sheppo } 8071991Sheppo if (ldcp->link_state == LDC_CHANNEL_DOWN) { 8083010Slm66018 D1(ldcp->id, "i_ldc_get_tx_tail: (0x%llx) channel not ready\n", 8091991Sheppo ldcp->id); 8101991Sheppo return (ECONNRESET); 8111991Sheppo } 8121991Sheppo 8134690Snarayan i_ldc_get_tx_head(ldcp, ¤t_head); 8141991Sheppo 8151991Sheppo /* increment the tail */ 8161991Sheppo new_tail = (ldcp->tx_tail + LDC_PACKET_SIZE) % 8174690Snarayan (ldcp->tx_q_entries << LDC_PACKET_SHIFT); 8181991Sheppo 8191991Sheppo if (new_tail == current_head) { 8201991Sheppo DWARN(ldcp->id, 8211991Sheppo "i_ldc_get_tx_tail: (0x%llx) TX queue is full\n", 8221991Sheppo ldcp->id); 8231991Sheppo return (EWOULDBLOCK); 8241991Sheppo } 8251991Sheppo 8261991Sheppo D2(ldcp->id, "i_ldc_get_tx_tail: (0x%llx) head=0x%llx, tail=0x%llx\n", 8271991Sheppo ldcp->id, ldcp->tx_head, ldcp->tx_tail); 8281991Sheppo 8291991Sheppo *tail = ldcp->tx_tail; 8301991Sheppo return (0); 8311991Sheppo } 8321991Sheppo 8331991Sheppo /* 8341991Sheppo * Set the tail pointer. If HV returns EWOULDBLOCK, it will back off 8352032Slm66018 * and retry ldc_max_retries times before returning an error. 8361991Sheppo * Returns 0, EWOULDBLOCK or EIO 8371991Sheppo */ 8381991Sheppo static int 8391991Sheppo i_ldc_set_tx_tail(ldc_chan_t *ldcp, uint64_t tail) 8401991Sheppo { 8411991Sheppo int rv, retval = EWOULDBLOCK; 8422032Slm66018 int retries; 8431991Sheppo 8442336Snarayan ASSERT(MUTEX_HELD(&ldcp->tx_lock)); 8452032Slm66018 for (retries = 0; retries < ldc_max_retries; retries++) { 8461991Sheppo 8471991Sheppo if ((rv = hv_ldc_tx_set_qtail(ldcp->id, tail)) == 0) { 8481991Sheppo retval = 0; 8491991Sheppo break; 8501991Sheppo } 8511991Sheppo if (rv != H_EWOULDBLOCK) { 8521991Sheppo DWARN(ldcp->id, "i_ldc_set_tx_tail: (0x%llx) set " 8531991Sheppo "qtail=0x%llx failed, rv=%d\n", ldcp->id, tail, rv); 8541991Sheppo retval = EIO; 8551991Sheppo break; 8561991Sheppo } 8571991Sheppo 8582032Slm66018 /* wait for ldc_delay usecs */ 8592032Slm66018 drv_usecwait(ldc_delay); 8601991Sheppo } 8611991Sheppo return (retval); 8621991Sheppo } 8631991Sheppo 8641991Sheppo /* 8655944Sha137994 * Copy a data packet from the HV receive queue to the data queue. 8665944Sha137994 * Caller must ensure that the data queue is not already full. 8675944Sha137994 * 8685944Sha137994 * The *head argument represents the current head pointer for the HV 8695944Sha137994 * receive queue. After copying a packet from the HV receive queue, 8705944Sha137994 * the *head pointer will be updated. This allows the caller to update 8715944Sha137994 * the head pointer in HV using the returned *head value. 8725944Sha137994 */ 8735944Sha137994 void 8745944Sha137994 i_ldc_rxdq_copy(ldc_chan_t *ldcp, uint64_t *head) 8755944Sha137994 { 8765944Sha137994 uint64_t q_size, dq_size; 8775944Sha137994 8785944Sha137994 ASSERT(MUTEX_HELD(&ldcp->lock)); 8795944Sha137994 8805944Sha137994 q_size = ldcp->rx_q_entries << LDC_PACKET_SHIFT; 8815944Sha137994 dq_size = ldcp->rx_dq_entries << LDC_PACKET_SHIFT; 8825944Sha137994 8835944Sha137994 ASSERT(Q_CONTIG_SPACE(ldcp->rx_dq_head, ldcp->rx_dq_tail, 8845944Sha137994 dq_size) >= LDC_PACKET_SIZE); 8855944Sha137994 8865944Sha137994 bcopy((void *)(ldcp->rx_q_va + *head), 8875944Sha137994 (void *)(ldcp->rx_dq_va + ldcp->rx_dq_tail), LDC_PACKET_SIZE); 8885944Sha137994 TRACE_RXDQ_COPY(ldcp, LDC_PACKET_SIZE); 8895944Sha137994 8905944Sha137994 /* Update rx head */ 8915944Sha137994 *head = (*head + LDC_PACKET_SIZE) % q_size; 8925944Sha137994 8935944Sha137994 /* Update dq tail */ 8945944Sha137994 ldcp->rx_dq_tail = (ldcp->rx_dq_tail + LDC_PACKET_SIZE) % dq_size; 8955944Sha137994 } 8965944Sha137994 8975944Sha137994 /* 8985944Sha137994 * Update the Rx data queue head pointer 8995944Sha137994 */ 9005944Sha137994 static int 9015944Sha137994 i_ldc_set_rxdq_head(ldc_chan_t *ldcp, uint64_t head) 9025944Sha137994 { 9035944Sha137994 ldcp->rx_dq_head = head; 9045944Sha137994 return (0); 9055944Sha137994 } 9065944Sha137994 9075944Sha137994 /* 9085944Sha137994 * Get the Rx data queue head and tail pointers 9095944Sha137994 */ 9105944Sha137994 static uint64_t 9115944Sha137994 i_ldc_dq_rx_get_state(ldc_chan_t *ldcp, uint64_t *head, uint64_t *tail, 9125944Sha137994 uint64_t *link_state) 9135944Sha137994 { 9145944Sha137994 _NOTE(ARGUNUSED(link_state)) 9155944Sha137994 *head = ldcp->rx_dq_head; 9165944Sha137994 *tail = ldcp->rx_dq_tail; 9175944Sha137994 return (0); 9185944Sha137994 } 9195944Sha137994 9205944Sha137994 /* 9215944Sha137994 * Wrapper for the Rx HV queue set head function. Giving the 9225944Sha137994 * data queue and HV queue set head functions the same type. 9235944Sha137994 */ 9245944Sha137994 static uint64_t 9255944Sha137994 i_ldc_hvq_rx_get_state(ldc_chan_t *ldcp, uint64_t *head, uint64_t *tail, 9265944Sha137994 uint64_t *link_state) 9275944Sha137994 { 9285944Sha137994 return (i_ldc_h2v_error(hv_ldc_rx_get_state(ldcp->id, head, tail, 9295944Sha137994 link_state))); 9305944Sha137994 } 9315944Sha137994 9325944Sha137994 /* 9335944Sha137994 * LDC receive interrupt handler 9345944Sha137994 * triggered for channel with data pending to read 9355944Sha137994 * i.e. Rx queue content changes 9365944Sha137994 */ 9375944Sha137994 static uint_t 9385944Sha137994 i_ldc_rx_hdlr(caddr_t arg1, caddr_t arg2) 9395944Sha137994 { 9405944Sha137994 _NOTE(ARGUNUSED(arg2)) 9415944Sha137994 9425944Sha137994 ldc_chan_t *ldcp; 9435944Sha137994 boolean_t notify; 9445944Sha137994 uint64_t event; 9455944Sha137994 int rv; 9465944Sha137994 9475944Sha137994 /* Get the channel for which interrupt was received */ 9485944Sha137994 if (arg1 == NULL) { 9495944Sha137994 cmn_err(CE_WARN, "i_ldc_rx_hdlr: invalid arg\n"); 9505944Sha137994 return (DDI_INTR_UNCLAIMED); 9515944Sha137994 } 9525944Sha137994 9535944Sha137994 ldcp = (ldc_chan_t *)arg1; 9545944Sha137994 9555944Sha137994 D1(ldcp->id, "i_ldc_rx_hdlr: (0x%llx) Received intr, ldcp=0x%p\n", 9565944Sha137994 ldcp->id, ldcp); 9575944Sha137994 D1(ldcp->id, "i_ldc_rx_hdlr: (%llx) USR%lx/TS%lx/HS%lx, LSTATE=%lx\n", 9585944Sha137994 ldcp->id, ldcp->status, ldcp->tstate, ldcp->hstate, 9595944Sha137994 ldcp->link_state); 9605944Sha137994 9615944Sha137994 /* Lock channel */ 9625944Sha137994 mutex_enter(&ldcp->lock); 9635944Sha137994 9645944Sha137994 /* Mark the interrupt as being actively handled */ 9655944Sha137994 ldcp->rx_intr_state = LDC_INTR_ACTIVE; 9665944Sha137994 9675944Sha137994 (void) i_ldc_rx_process_hvq(ldcp, ¬ify, &event); 9685944Sha137994 969*6408Sha137994 if (ldcp->mode != LDC_MODE_RELIABLE) { 9705944Sha137994 /* 9715944Sha137994 * If there are no data packets on the queue, clear 9725944Sha137994 * the interrupt. Otherwise, the ldc_read will clear 9735944Sha137994 * interrupts after draining the queue. To indicate the 9745944Sha137994 * interrupt has not yet been cleared, it is marked 9755944Sha137994 * as pending. 9765944Sha137994 */ 9775944Sha137994 if ((event & LDC_EVT_READ) == 0) { 9785944Sha137994 i_ldc_clear_intr(ldcp, CNEX_RX_INTR); 9795944Sha137994 } else { 9805944Sha137994 ldcp->rx_intr_state = LDC_INTR_PEND; 9815944Sha137994 } 9825944Sha137994 } 9835944Sha137994 9845944Sha137994 /* if callbacks are disabled, do not notify */ 9855944Sha137994 if (notify && ldcp->cb_enabled) { 9865944Sha137994 ldcp->cb_inprogress = B_TRUE; 9875944Sha137994 mutex_exit(&ldcp->lock); 9885944Sha137994 rv = ldcp->cb(event, ldcp->cb_arg); 9895944Sha137994 if (rv) { 9905944Sha137994 DWARN(ldcp->id, 9915944Sha137994 "i_ldc_rx_hdlr: (0x%llx) callback failure", 9925944Sha137994 ldcp->id); 9935944Sha137994 } 9945944Sha137994 mutex_enter(&ldcp->lock); 9955944Sha137994 ldcp->cb_inprogress = B_FALSE; 9965944Sha137994 } 9975944Sha137994 998*6408Sha137994 if (ldcp->mode == LDC_MODE_RELIABLE) { 9995944Sha137994 /* 10005944Sha137994 * If we are using a secondary data queue, clear the 10015944Sha137994 * interrupt. We should have processed all CTRL packets 10025944Sha137994 * and copied all DATA packets to the secondary queue. 10035944Sha137994 * Even if secondary queue filled up, clear the interrupts, 10045944Sha137994 * this will trigger another interrupt and force the 10055944Sha137994 * handler to copy more data. 10065944Sha137994 */ 10075944Sha137994 i_ldc_clear_intr(ldcp, CNEX_RX_INTR); 10085944Sha137994 } 10095944Sha137994 10105944Sha137994 mutex_exit(&ldcp->lock); 10115944Sha137994 10125944Sha137994 D1(ldcp->id, "i_ldc_rx_hdlr: (0x%llx) exiting handler", ldcp->id); 10135944Sha137994 10145944Sha137994 return (DDI_INTR_CLAIMED); 10155944Sha137994 } 10165944Sha137994 10175944Sha137994 /* 10185944Sha137994 * Wrapper for the Rx HV queue processing function to be used when 10195944Sha137994 * checking the Rx HV queue for data packets. Unlike the interrupt 10205944Sha137994 * handler code flow, the Rx interrupt is not cleared here and 10215944Sha137994 * callbacks are not made. 10225944Sha137994 */ 10235944Sha137994 static uint_t 10245944Sha137994 i_ldc_chkq(ldc_chan_t *ldcp) 10255944Sha137994 { 10265944Sha137994 boolean_t notify; 10275944Sha137994 uint64_t event; 10285944Sha137994 10295944Sha137994 return (i_ldc_rx_process_hvq(ldcp, ¬ify, &event)); 10305944Sha137994 } 10315944Sha137994 10325944Sha137994 /* 10331991Sheppo * Send a LDC message 10341991Sheppo */ 10351991Sheppo static int 10361991Sheppo i_ldc_send_pkt(ldc_chan_t *ldcp, uint8_t pkttype, uint8_t subtype, 10371991Sheppo uint8_t ctrlmsg) 10381991Sheppo { 10391991Sheppo int rv; 10401991Sheppo ldc_msg_t *pkt; 10411991Sheppo uint64_t tx_tail; 10424690Snarayan uint32_t curr_seqid; 10431991Sheppo 10442336Snarayan /* Obtain Tx lock */ 10452336Snarayan mutex_enter(&ldcp->tx_lock); 10462336Snarayan 10474690Snarayan curr_seqid = ldcp->last_msg_snt; 10484690Snarayan 10491991Sheppo /* get the current tail for the message */ 10501991Sheppo rv = i_ldc_get_tx_tail(ldcp, &tx_tail); 10511991Sheppo if (rv) { 10521991Sheppo DWARN(ldcp->id, 10531991Sheppo "i_ldc_send_pkt: (0x%llx) error sending pkt, " 10541991Sheppo "type=0x%x,subtype=0x%x,ctrl=0x%x\n", 10551991Sheppo ldcp->id, pkttype, subtype, ctrlmsg); 10562336Snarayan mutex_exit(&ldcp->tx_lock); 10571991Sheppo return (rv); 10581991Sheppo } 10591991Sheppo 10601991Sheppo pkt = (ldc_msg_t *)(ldcp->tx_q_va + tx_tail); 10611991Sheppo ZERO_PKT(pkt); 10621991Sheppo 10631991Sheppo /* Initialize the packet */ 10641991Sheppo pkt->type = pkttype; 10651991Sheppo pkt->stype = subtype; 10661991Sheppo pkt->ctrl = ctrlmsg; 10671991Sheppo 10681991Sheppo /* Store ackid/seqid iff it is RELIABLE mode & not a RTS/RTR message */ 10691991Sheppo if (((ctrlmsg & LDC_CTRL_MASK) != LDC_RTS) && 10701991Sheppo ((ctrlmsg & LDC_CTRL_MASK) != LDC_RTR)) { 10711991Sheppo curr_seqid++; 10721991Sheppo if (ldcp->mode != LDC_MODE_RAW) { 10731991Sheppo pkt->seqid = curr_seqid; 10741991Sheppo pkt->ackid = ldcp->last_msg_rcd; 10751991Sheppo } 10761991Sheppo } 10771991Sheppo DUMP_LDC_PKT(ldcp, "i_ldc_send_pkt", (uint64_t)pkt); 10781991Sheppo 10791991Sheppo /* initiate the send by calling into HV and set the new tail */ 10801991Sheppo tx_tail = (tx_tail + LDC_PACKET_SIZE) % 10814690Snarayan (ldcp->tx_q_entries << LDC_PACKET_SHIFT); 10821991Sheppo 10831991Sheppo rv = i_ldc_set_tx_tail(ldcp, tx_tail); 10841991Sheppo if (rv) { 10851991Sheppo DWARN(ldcp->id, 10861991Sheppo "i_ldc_send_pkt:(0x%llx) error sending pkt, " 10871991Sheppo "type=0x%x,stype=0x%x,ctrl=0x%x\n", 10881991Sheppo ldcp->id, pkttype, subtype, ctrlmsg); 10892336Snarayan mutex_exit(&ldcp->tx_lock); 10901991Sheppo return (EIO); 10911991Sheppo } 10921991Sheppo 10931991Sheppo ldcp->last_msg_snt = curr_seqid; 10941991Sheppo ldcp->tx_tail = tx_tail; 10951991Sheppo 10962336Snarayan mutex_exit(&ldcp->tx_lock); 10971991Sheppo return (0); 10981991Sheppo } 10991991Sheppo 11001991Sheppo /* 11011991Sheppo * Checks if packet was received in right order 11022410Slm66018 * in the case of a reliable link. 11031991Sheppo * Returns 0 if in order, else EIO 11041991Sheppo */ 11051991Sheppo static int 11061991Sheppo i_ldc_check_seqid(ldc_chan_t *ldcp, ldc_msg_t *msg) 11071991Sheppo { 11081991Sheppo /* No seqid checking for RAW mode */ 11091991Sheppo if (ldcp->mode == LDC_MODE_RAW) 11101991Sheppo return (0); 11111991Sheppo 11121991Sheppo /* No seqid checking for version, RTS, RTR message */ 11131991Sheppo if (msg->ctrl == LDC_VER || 11141991Sheppo msg->ctrl == LDC_RTS || 11151991Sheppo msg->ctrl == LDC_RTR) 11161991Sheppo return (0); 11171991Sheppo 11181991Sheppo /* Initial seqid to use is sent in RTS/RTR and saved in last_msg_rcd */ 11191991Sheppo if (msg->seqid != (ldcp->last_msg_rcd + 1)) { 11201991Sheppo DWARN(ldcp->id, 11211991Sheppo "i_ldc_check_seqid: (0x%llx) out-of-order pkt, got 0x%x, " 11221991Sheppo "expecting 0x%x\n", ldcp->id, msg->seqid, 11231991Sheppo (ldcp->last_msg_rcd + 1)); 11241991Sheppo return (EIO); 11251991Sheppo } 11261991Sheppo 11273560Snarayan #ifdef DEBUG 11283560Snarayan if (LDC_INJECT_PKTLOSS(ldcp)) { 11293560Snarayan DWARN(ldcp->id, 11303560Snarayan "i_ldc_check_seqid: (0x%llx) inject pkt loss\n", ldcp->id); 11313560Snarayan return (EIO); 11323560Snarayan } 11333560Snarayan #endif 11343560Snarayan 11351991Sheppo return (0); 11361991Sheppo } 11371991Sheppo 11381991Sheppo 11391991Sheppo /* 11401991Sheppo * Process an incoming version ctrl message 11411991Sheppo */ 11421991Sheppo static int 11431991Sheppo i_ldc_process_VER(ldc_chan_t *ldcp, ldc_msg_t *msg) 11441991Sheppo { 11451991Sheppo int rv = 0, idx = ldcp->next_vidx; 11461991Sheppo ldc_msg_t *pkt; 11471991Sheppo uint64_t tx_tail; 11481991Sheppo ldc_ver_t *rcvd_ver; 11491991Sheppo 11501991Sheppo /* get the received version */ 11511991Sheppo rcvd_ver = (ldc_ver_t *)((uint64_t)msg + LDC_PAYLOAD_VER_OFF); 11521991Sheppo 11531991Sheppo D2(ldcp->id, "i_ldc_process_VER: (0x%llx) received VER v%u.%u\n", 11541991Sheppo ldcp->id, rcvd_ver->major, rcvd_ver->minor); 11551991Sheppo 11562336Snarayan /* Obtain Tx lock */ 11572336Snarayan mutex_enter(&ldcp->tx_lock); 11582336Snarayan 11591991Sheppo switch (msg->stype) { 11601991Sheppo case LDC_INFO: 11611991Sheppo 11622793Slm66018 if ((ldcp->tstate & ~TS_IN_RESET) == TS_VREADY) { 11632793Slm66018 (void) i_ldc_txq_reconf(ldcp); 11642793Slm66018 i_ldc_reset_state(ldcp); 11652793Slm66018 mutex_exit(&ldcp->tx_lock); 11662793Slm66018 return (EAGAIN); 11672793Slm66018 } 11682793Slm66018 11691991Sheppo /* get the current tail and pkt for the response */ 11701991Sheppo rv = i_ldc_get_tx_tail(ldcp, &tx_tail); 11711991Sheppo if (rv != 0) { 11721991Sheppo DWARN(ldcp->id, 11731991Sheppo "i_ldc_process_VER: (0x%llx) err sending " 11741991Sheppo "version ACK/NACK\n", ldcp->id); 11752793Slm66018 i_ldc_reset(ldcp, B_TRUE); 11762336Snarayan mutex_exit(&ldcp->tx_lock); 11771991Sheppo return (ECONNRESET); 11781991Sheppo } 11791991Sheppo 11801991Sheppo pkt = (ldc_msg_t *)(ldcp->tx_q_va + tx_tail); 11811991Sheppo ZERO_PKT(pkt); 11821991Sheppo 11831991Sheppo /* initialize the packet */ 11841991Sheppo pkt->type = LDC_CTRL; 11851991Sheppo pkt->ctrl = LDC_VER; 11861991Sheppo 11871991Sheppo for (;;) { 11881991Sheppo 11891991Sheppo D1(ldcp->id, "i_ldc_process_VER: got %u.%u chk %u.%u\n", 11901991Sheppo rcvd_ver->major, rcvd_ver->minor, 11911991Sheppo ldc_versions[idx].major, ldc_versions[idx].minor); 11921991Sheppo 11931991Sheppo if (rcvd_ver->major == ldc_versions[idx].major) { 11941991Sheppo /* major version match - ACK version */ 11951991Sheppo pkt->stype = LDC_ACK; 11961991Sheppo 11971991Sheppo /* 11981991Sheppo * lower minor version to the one this endpt 11991991Sheppo * supports, if necessary 12001991Sheppo */ 12011991Sheppo if (rcvd_ver->minor > ldc_versions[idx].minor) 12021991Sheppo rcvd_ver->minor = 12034690Snarayan ldc_versions[idx].minor; 12041991Sheppo bcopy(rcvd_ver, pkt->udata, sizeof (*rcvd_ver)); 12051991Sheppo 12061991Sheppo break; 12071991Sheppo } 12081991Sheppo 12091991Sheppo if (rcvd_ver->major > ldc_versions[idx].major) { 12101991Sheppo 12111991Sheppo D1(ldcp->id, "i_ldc_process_VER: using next" 12121991Sheppo " lower idx=%d, v%u.%u\n", idx, 12131991Sheppo ldc_versions[idx].major, 12141991Sheppo ldc_versions[idx].minor); 12151991Sheppo 12161991Sheppo /* nack with next lower version */ 12171991Sheppo pkt->stype = LDC_NACK; 12181991Sheppo bcopy(&ldc_versions[idx], pkt->udata, 12191991Sheppo sizeof (ldc_versions[idx])); 12201991Sheppo ldcp->next_vidx = idx; 12211991Sheppo break; 12221991Sheppo } 12231991Sheppo 12241991Sheppo /* next major version */ 12251991Sheppo idx++; 12261991Sheppo 12271991Sheppo D1(ldcp->id, "i_ldc_process_VER: inc idx %x\n", idx); 12281991Sheppo 12291991Sheppo if (idx == LDC_NUM_VERS) { 12301991Sheppo /* no version match - send NACK */ 12311991Sheppo pkt->stype = LDC_NACK; 12321991Sheppo bzero(pkt->udata, sizeof (ldc_ver_t)); 12331991Sheppo ldcp->next_vidx = 0; 12341991Sheppo break; 12351991Sheppo } 12361991Sheppo } 12371991Sheppo 12381991Sheppo /* initiate the send by calling into HV and set the new tail */ 12391991Sheppo tx_tail = (tx_tail + LDC_PACKET_SIZE) % 12404690Snarayan (ldcp->tx_q_entries << LDC_PACKET_SHIFT); 12411991Sheppo 12421991Sheppo rv = i_ldc_set_tx_tail(ldcp, tx_tail); 12431991Sheppo if (rv == 0) { 12441991Sheppo ldcp->tx_tail = tx_tail; 12451991Sheppo if (pkt->stype == LDC_ACK) { 12461991Sheppo D2(ldcp->id, "i_ldc_process_VER: (0x%llx) sent" 12471991Sheppo " version ACK\n", ldcp->id); 12481991Sheppo /* Save the ACK'd version */ 12491991Sheppo ldcp->version.major = rcvd_ver->major; 12501991Sheppo ldcp->version.minor = rcvd_ver->minor; 12512032Slm66018 ldcp->hstate |= TS_RCVD_VER; 12521991Sheppo ldcp->tstate |= TS_VER_DONE; 12533560Snarayan D1(DBG_ALL_LDCS, 12542793Slm66018 "(0x%llx) Sent ACK, " 12552793Slm66018 "Agreed on version v%u.%u\n", 12561991Sheppo ldcp->id, rcvd_ver->major, rcvd_ver->minor); 12571991Sheppo } 12581991Sheppo } else { 12591991Sheppo DWARN(ldcp->id, 12601991Sheppo "i_ldc_process_VER: (0x%llx) error sending " 12611991Sheppo "ACK/NACK\n", ldcp->id); 12622793Slm66018 i_ldc_reset(ldcp, B_TRUE); 12632336Snarayan mutex_exit(&ldcp->tx_lock); 12641991Sheppo return (ECONNRESET); 12651991Sheppo } 12661991Sheppo 12671991Sheppo break; 12681991Sheppo 12691991Sheppo case LDC_ACK: 12702793Slm66018 if ((ldcp->tstate & ~TS_IN_RESET) == TS_VREADY) { 12712793Slm66018 if (ldcp->version.major != rcvd_ver->major || 12724690Snarayan ldcp->version.minor != rcvd_ver->minor) { 12732793Slm66018 12742793Slm66018 /* mismatched version - reset connection */ 12752793Slm66018 DWARN(ldcp->id, 12764690Snarayan "i_ldc_process_VER: (0x%llx) recvd" 12774690Snarayan " ACK ver != sent ACK ver\n", ldcp->id); 12782793Slm66018 i_ldc_reset(ldcp, B_TRUE); 12792793Slm66018 mutex_exit(&ldcp->tx_lock); 12802793Slm66018 return (ECONNRESET); 12812793Slm66018 } 12822793Slm66018 } else { 12832793Slm66018 /* SUCCESS - we have agreed on a version */ 12842793Slm66018 ldcp->version.major = rcvd_ver->major; 12852793Slm66018 ldcp->version.minor = rcvd_ver->minor; 12862793Slm66018 ldcp->tstate |= TS_VER_DONE; 12872793Slm66018 } 12882793Slm66018 12893010Slm66018 D1(ldcp->id, "(0x%llx) Got ACK, Agreed on version v%u.%u\n", 12901991Sheppo ldcp->id, rcvd_ver->major, rcvd_ver->minor); 12911991Sheppo 12921991Sheppo /* initiate RTS-RTR-RDX handshake */ 12931991Sheppo rv = i_ldc_get_tx_tail(ldcp, &tx_tail); 12941991Sheppo if (rv) { 12951991Sheppo DWARN(ldcp->id, 12962793Slm66018 "i_ldc_process_VER: (0x%llx) cannot send RTS\n", 12971991Sheppo ldcp->id); 12982793Slm66018 i_ldc_reset(ldcp, B_TRUE); 12992336Snarayan mutex_exit(&ldcp->tx_lock); 13001991Sheppo return (ECONNRESET); 13011991Sheppo } 13021991Sheppo 13031991Sheppo pkt = (ldc_msg_t *)(ldcp->tx_q_va + tx_tail); 13041991Sheppo ZERO_PKT(pkt); 13051991Sheppo 13061991Sheppo pkt->type = LDC_CTRL; 13071991Sheppo pkt->stype = LDC_INFO; 13081991Sheppo pkt->ctrl = LDC_RTS; 13091991Sheppo pkt->env = ldcp->mode; 13101991Sheppo if (ldcp->mode != LDC_MODE_RAW) 13111991Sheppo pkt->seqid = LDC_INIT_SEQID; 13121991Sheppo 13131991Sheppo ldcp->last_msg_rcd = LDC_INIT_SEQID; 13141991Sheppo 13151991Sheppo DUMP_LDC_PKT(ldcp, "i_ldc_process_VER snd rts", (uint64_t)pkt); 13161991Sheppo 13171991Sheppo /* initiate the send by calling into HV and set the new tail */ 13181991Sheppo tx_tail = (tx_tail + LDC_PACKET_SIZE) % 13194690Snarayan (ldcp->tx_q_entries << LDC_PACKET_SHIFT); 13201991Sheppo 13211991Sheppo rv = i_ldc_set_tx_tail(ldcp, tx_tail); 13221991Sheppo if (rv) { 13231991Sheppo D2(ldcp->id, 13241991Sheppo "i_ldc_process_VER: (0x%llx) no listener\n", 13251991Sheppo ldcp->id); 13262793Slm66018 i_ldc_reset(ldcp, B_TRUE); 13272336Snarayan mutex_exit(&ldcp->tx_lock); 13281991Sheppo return (ECONNRESET); 13291991Sheppo } 13301991Sheppo 13311991Sheppo ldcp->tx_tail = tx_tail; 13321991Sheppo ldcp->hstate |= TS_SENT_RTS; 13331991Sheppo 13341991Sheppo break; 13351991Sheppo 13361991Sheppo case LDC_NACK: 13371991Sheppo /* check if version in NACK is zero */ 13381991Sheppo if (rcvd_ver->major == 0 && rcvd_ver->minor == 0) { 13391991Sheppo /* version handshake failure */ 13401991Sheppo DWARN(DBG_ALL_LDCS, 13411991Sheppo "i_ldc_process_VER: (0x%llx) no version match\n", 13421991Sheppo ldcp->id); 13432793Slm66018 i_ldc_reset(ldcp, B_TRUE); 13442336Snarayan mutex_exit(&ldcp->tx_lock); 13451991Sheppo return (ECONNRESET); 13461991Sheppo } 13471991Sheppo 13481991Sheppo /* get the current tail and pkt for the response */ 13491991Sheppo rv = i_ldc_get_tx_tail(ldcp, &tx_tail); 13501991Sheppo if (rv != 0) { 13511991Sheppo cmn_err(CE_NOTE, 13521991Sheppo "i_ldc_process_VER: (0x%lx) err sending " 13531991Sheppo "version ACK/NACK\n", ldcp->id); 13542793Slm66018 i_ldc_reset(ldcp, B_TRUE); 13552336Snarayan mutex_exit(&ldcp->tx_lock); 13561991Sheppo return (ECONNRESET); 13571991Sheppo } 13581991Sheppo 13591991Sheppo pkt = (ldc_msg_t *)(ldcp->tx_q_va + tx_tail); 13601991Sheppo ZERO_PKT(pkt); 13611991Sheppo 13621991Sheppo /* initialize the packet */ 13631991Sheppo pkt->type = LDC_CTRL; 13641991Sheppo pkt->ctrl = LDC_VER; 13651991Sheppo pkt->stype = LDC_INFO; 13661991Sheppo 13671991Sheppo /* check ver in NACK msg has a match */ 13681991Sheppo for (;;) { 13691991Sheppo if (rcvd_ver->major == ldc_versions[idx].major) { 13701991Sheppo /* 13711991Sheppo * major version match - resubmit request 13721991Sheppo * if lower minor version to the one this endpt 13731991Sheppo * supports, if necessary 13741991Sheppo */ 13751991Sheppo if (rcvd_ver->minor > ldc_versions[idx].minor) 13761991Sheppo rcvd_ver->minor = 13774690Snarayan ldc_versions[idx].minor; 13781991Sheppo bcopy(rcvd_ver, pkt->udata, sizeof (*rcvd_ver)); 13791991Sheppo break; 13801991Sheppo } 13811991Sheppo 13821991Sheppo if (rcvd_ver->major > ldc_versions[idx].major) { 13831991Sheppo 13841991Sheppo D1(ldcp->id, "i_ldc_process_VER: using next" 13851991Sheppo " lower idx=%d, v%u.%u\n", idx, 13861991Sheppo ldc_versions[idx].major, 13871991Sheppo ldc_versions[idx].minor); 13881991Sheppo 13891991Sheppo /* send next lower version */ 13901991Sheppo bcopy(&ldc_versions[idx], pkt->udata, 13911991Sheppo sizeof (ldc_versions[idx])); 13921991Sheppo ldcp->next_vidx = idx; 13931991Sheppo break; 13941991Sheppo } 13951991Sheppo 13961991Sheppo /* next version */ 13971991Sheppo idx++; 13981991Sheppo 13991991Sheppo D1(ldcp->id, "i_ldc_process_VER: inc idx %x\n", idx); 14001991Sheppo 14011991Sheppo if (idx == LDC_NUM_VERS) { 14021991Sheppo /* no version match - terminate */ 14031991Sheppo ldcp->next_vidx = 0; 14042336Snarayan mutex_exit(&ldcp->tx_lock); 14051991Sheppo return (ECONNRESET); 14061991Sheppo } 14071991Sheppo } 14081991Sheppo 14091991Sheppo /* initiate the send by calling into HV and set the new tail */ 14101991Sheppo tx_tail = (tx_tail + LDC_PACKET_SIZE) % 14114690Snarayan (ldcp->tx_q_entries << LDC_PACKET_SHIFT); 14121991Sheppo 14131991Sheppo rv = i_ldc_set_tx_tail(ldcp, tx_tail); 14141991Sheppo if (rv == 0) { 14151991Sheppo D2(ldcp->id, "i_ldc_process_VER: (0x%llx) sent version" 14161991Sheppo "INFO v%u.%u\n", ldcp->id, ldc_versions[idx].major, 14171991Sheppo ldc_versions[idx].minor); 14181991Sheppo ldcp->tx_tail = tx_tail; 14191991Sheppo } else { 14201991Sheppo cmn_err(CE_NOTE, 14211991Sheppo "i_ldc_process_VER: (0x%lx) error sending version" 14221991Sheppo "INFO\n", ldcp->id); 14232793Slm66018 i_ldc_reset(ldcp, B_TRUE); 14242336Snarayan mutex_exit(&ldcp->tx_lock); 14251991Sheppo return (ECONNRESET); 14261991Sheppo } 14271991Sheppo 14281991Sheppo break; 14291991Sheppo } 14301991Sheppo 14312336Snarayan mutex_exit(&ldcp->tx_lock); 14321991Sheppo return (rv); 14331991Sheppo } 14341991Sheppo 14351991Sheppo 14361991Sheppo /* 14371991Sheppo * Process an incoming RTS ctrl message 14381991Sheppo */ 14391991Sheppo static int 14401991Sheppo i_ldc_process_RTS(ldc_chan_t *ldcp, ldc_msg_t *msg) 14411991Sheppo { 14421991Sheppo int rv = 0; 14431991Sheppo ldc_msg_t *pkt; 14441991Sheppo uint64_t tx_tail; 14451991Sheppo boolean_t sent_NACK = B_FALSE; 14461991Sheppo 14471991Sheppo D2(ldcp->id, "i_ldc_process_RTS: (0x%llx) received RTS\n", ldcp->id); 14481991Sheppo 14491991Sheppo switch (msg->stype) { 14501991Sheppo case LDC_NACK: 14511991Sheppo DWARN(ldcp->id, 14521991Sheppo "i_ldc_process_RTS: (0x%llx) RTS NACK received\n", 14531991Sheppo ldcp->id); 14541991Sheppo 14551991Sheppo /* Reset the channel -- as we cannot continue */ 14562336Snarayan mutex_enter(&ldcp->tx_lock); 14572793Slm66018 i_ldc_reset(ldcp, B_TRUE); 14582336Snarayan mutex_exit(&ldcp->tx_lock); 14591991Sheppo rv = ECONNRESET; 14601991Sheppo break; 14611991Sheppo 14621991Sheppo case LDC_INFO: 14631991Sheppo 14641991Sheppo /* check mode */ 14651991Sheppo if (ldcp->mode != (ldc_mode_t)msg->env) { 14661991Sheppo cmn_err(CE_NOTE, 14671991Sheppo "i_ldc_process_RTS: (0x%lx) mode mismatch\n", 14681991Sheppo ldcp->id); 14691991Sheppo /* 14701991Sheppo * send NACK in response to MODE message 14711991Sheppo * get the current tail for the response 14721991Sheppo */ 14731991Sheppo rv = i_ldc_send_pkt(ldcp, LDC_CTRL, LDC_NACK, LDC_RTS); 14741991Sheppo if (rv) { 14751991Sheppo /* if cannot send NACK - reset channel */ 14762336Snarayan mutex_enter(&ldcp->tx_lock); 14772793Slm66018 i_ldc_reset(ldcp, B_TRUE); 14782336Snarayan mutex_exit(&ldcp->tx_lock); 14791991Sheppo rv = ECONNRESET; 14801991Sheppo break; 14811991Sheppo } 14821991Sheppo sent_NACK = B_TRUE; 14831991Sheppo } 14841991Sheppo break; 14851991Sheppo default: 14861991Sheppo DWARN(ldcp->id, "i_ldc_process_RTS: (0x%llx) unexp ACK\n", 14871991Sheppo ldcp->id); 14882336Snarayan mutex_enter(&ldcp->tx_lock); 14892793Slm66018 i_ldc_reset(ldcp, B_TRUE); 14902336Snarayan mutex_exit(&ldcp->tx_lock); 14911991Sheppo rv = ECONNRESET; 14921991Sheppo break; 14931991Sheppo } 14941991Sheppo 14951991Sheppo /* 14961991Sheppo * If either the connection was reset (when rv != 0) or 14971991Sheppo * a NACK was sent, we return. In the case of a NACK 14981991Sheppo * we dont want to consume the packet that came in but 14991991Sheppo * not record that we received the RTS 15001991Sheppo */ 15011991Sheppo if (rv || sent_NACK) 15021991Sheppo return (rv); 15031991Sheppo 15041991Sheppo /* record RTS received */ 15051991Sheppo ldcp->hstate |= TS_RCVD_RTS; 15061991Sheppo 15071991Sheppo /* store initial SEQID info */ 15081991Sheppo ldcp->last_msg_snt = msg->seqid; 15091991Sheppo 15102336Snarayan /* Obtain Tx lock */ 15112336Snarayan mutex_enter(&ldcp->tx_lock); 15122336Snarayan 15131991Sheppo /* get the current tail for the response */ 15141991Sheppo rv = i_ldc_get_tx_tail(ldcp, &tx_tail); 15151991Sheppo if (rv != 0) { 15161991Sheppo cmn_err(CE_NOTE, 15171991Sheppo "i_ldc_process_RTS: (0x%lx) err sending RTR\n", 15181991Sheppo ldcp->id); 15192793Slm66018 i_ldc_reset(ldcp, B_TRUE); 15202336Snarayan mutex_exit(&ldcp->tx_lock); 15211991Sheppo return (ECONNRESET); 15221991Sheppo } 15231991Sheppo 15241991Sheppo pkt = (ldc_msg_t *)(ldcp->tx_q_va + tx_tail); 15251991Sheppo ZERO_PKT(pkt); 15261991Sheppo 15271991Sheppo /* initialize the packet */ 15281991Sheppo pkt->type = LDC_CTRL; 15291991Sheppo pkt->stype = LDC_INFO; 15301991Sheppo pkt->ctrl = LDC_RTR; 15311991Sheppo pkt->env = ldcp->mode; 15321991Sheppo if (ldcp->mode != LDC_MODE_RAW) 15331991Sheppo pkt->seqid = LDC_INIT_SEQID; 15341991Sheppo 15351991Sheppo ldcp->last_msg_rcd = msg->seqid; 15361991Sheppo 15371991Sheppo /* initiate the send by calling into HV and set the new tail */ 15381991Sheppo tx_tail = (tx_tail + LDC_PACKET_SIZE) % 15394690Snarayan (ldcp->tx_q_entries << LDC_PACKET_SHIFT); 15401991Sheppo 15411991Sheppo rv = i_ldc_set_tx_tail(ldcp, tx_tail); 15421991Sheppo if (rv == 0) { 15431991Sheppo D2(ldcp->id, 15441991Sheppo "i_ldc_process_RTS: (0x%llx) sent RTR\n", ldcp->id); 15451991Sheppo DUMP_LDC_PKT(ldcp, "i_ldc_process_RTS sent rtr", (uint64_t)pkt); 15461991Sheppo 15471991Sheppo ldcp->tx_tail = tx_tail; 15481991Sheppo ldcp->hstate |= TS_SENT_RTR; 15491991Sheppo 15501991Sheppo } else { 15511991Sheppo cmn_err(CE_NOTE, 15521991Sheppo "i_ldc_process_RTS: (0x%lx) error sending RTR\n", 15531991Sheppo ldcp->id); 15542793Slm66018 i_ldc_reset(ldcp, B_TRUE); 15552336Snarayan mutex_exit(&ldcp->tx_lock); 15561991Sheppo return (ECONNRESET); 15571991Sheppo } 15581991Sheppo 15592336Snarayan mutex_exit(&ldcp->tx_lock); 15601991Sheppo return (0); 15611991Sheppo } 15621991Sheppo 15631991Sheppo /* 15641991Sheppo * Process an incoming RTR ctrl message 15651991Sheppo */ 15661991Sheppo static int 15671991Sheppo i_ldc_process_RTR(ldc_chan_t *ldcp, ldc_msg_t *msg) 15681991Sheppo { 15691991Sheppo int rv = 0; 15701991Sheppo boolean_t sent_NACK = B_FALSE; 15711991Sheppo 15721991Sheppo D2(ldcp->id, "i_ldc_process_RTR: (0x%llx) received RTR\n", ldcp->id); 15731991Sheppo 15741991Sheppo switch (msg->stype) { 15751991Sheppo case LDC_NACK: 15761991Sheppo /* RTR NACK received */ 15771991Sheppo DWARN(ldcp->id, 15781991Sheppo "i_ldc_process_RTR: (0x%llx) RTR NACK received\n", 15791991Sheppo ldcp->id); 15801991Sheppo 15811991Sheppo /* Reset the channel -- as we cannot continue */ 15822336Snarayan mutex_enter(&ldcp->tx_lock); 15832793Slm66018 i_ldc_reset(ldcp, B_TRUE); 15842336Snarayan mutex_exit(&ldcp->tx_lock); 15851991Sheppo rv = ECONNRESET; 15861991Sheppo 15871991Sheppo break; 15881991Sheppo 15891991Sheppo case LDC_INFO: 15901991Sheppo 15911991Sheppo /* check mode */ 15921991Sheppo if (ldcp->mode != (ldc_mode_t)msg->env) { 15931991Sheppo DWARN(ldcp->id, 15943010Slm66018 "i_ldc_process_RTR: (0x%llx) mode mismatch, " 15953010Slm66018 "expecting 0x%x, got 0x%x\n", 15963010Slm66018 ldcp->id, ldcp->mode, (ldc_mode_t)msg->env); 15971991Sheppo /* 15981991Sheppo * send NACK in response to MODE message 15991991Sheppo * get the current tail for the response 16001991Sheppo */ 16011991Sheppo rv = i_ldc_send_pkt(ldcp, LDC_CTRL, LDC_NACK, LDC_RTR); 16021991Sheppo if (rv) { 16031991Sheppo /* if cannot send NACK - reset channel */ 16042336Snarayan mutex_enter(&ldcp->tx_lock); 16052793Slm66018 i_ldc_reset(ldcp, B_TRUE); 16062336Snarayan mutex_exit(&ldcp->tx_lock); 16071991Sheppo rv = ECONNRESET; 16081991Sheppo break; 16091991Sheppo } 16101991Sheppo sent_NACK = B_TRUE; 16111991Sheppo } 16121991Sheppo break; 16131991Sheppo 16141991Sheppo default: 16151991Sheppo DWARN(ldcp->id, "i_ldc_process_RTR: (0x%llx) unexp ACK\n", 16161991Sheppo ldcp->id); 16171991Sheppo 16181991Sheppo /* Reset the channel -- as we cannot continue */ 16192336Snarayan mutex_enter(&ldcp->tx_lock); 16202793Slm66018 i_ldc_reset(ldcp, B_TRUE); 16212336Snarayan mutex_exit(&ldcp->tx_lock); 16221991Sheppo rv = ECONNRESET; 16231991Sheppo break; 16241991Sheppo } 16251991Sheppo 16261991Sheppo /* 16271991Sheppo * If either the connection was reset (when rv != 0) or 16281991Sheppo * a NACK was sent, we return. In the case of a NACK 16291991Sheppo * we dont want to consume the packet that came in but 16301991Sheppo * not record that we received the RTR 16311991Sheppo */ 16321991Sheppo if (rv || sent_NACK) 16331991Sheppo return (rv); 16341991Sheppo 16351991Sheppo ldcp->last_msg_snt = msg->seqid; 16361991Sheppo ldcp->hstate |= TS_RCVD_RTR; 16371991Sheppo 16381991Sheppo rv = i_ldc_send_pkt(ldcp, LDC_CTRL, LDC_INFO, LDC_RDX); 16391991Sheppo if (rv) { 16401991Sheppo cmn_err(CE_NOTE, 16411991Sheppo "i_ldc_process_RTR: (0x%lx) cannot send RDX\n", 16421991Sheppo ldcp->id); 16432336Snarayan mutex_enter(&ldcp->tx_lock); 16442793Slm66018 i_ldc_reset(ldcp, B_TRUE); 16452336Snarayan mutex_exit(&ldcp->tx_lock); 16461991Sheppo return (ECONNRESET); 16471991Sheppo } 16481991Sheppo D2(ldcp->id, 16491991Sheppo "i_ldc_process_RTR: (0x%llx) sent RDX\n", ldcp->id); 16501991Sheppo 16511991Sheppo ldcp->hstate |= TS_SENT_RDX; 16521991Sheppo ldcp->tstate |= TS_HSHAKE_DONE; 16532793Slm66018 if ((ldcp->tstate & TS_IN_RESET) == 0) 16542793Slm66018 ldcp->status = LDC_UP; 16551991Sheppo 16563010Slm66018 D1(ldcp->id, "(0x%llx) Handshake Complete\n", ldcp->id); 16571991Sheppo 16581991Sheppo return (0); 16591991Sheppo } 16601991Sheppo 16611991Sheppo 16621991Sheppo /* 16631991Sheppo * Process an incoming RDX ctrl message 16641991Sheppo */ 16651991Sheppo static int 16661991Sheppo i_ldc_process_RDX(ldc_chan_t *ldcp, ldc_msg_t *msg) 16671991Sheppo { 16681991Sheppo int rv = 0; 16691991Sheppo 16701991Sheppo D2(ldcp->id, "i_ldc_process_RDX: (0x%llx) received RDX\n", ldcp->id); 16711991Sheppo 16721991Sheppo switch (msg->stype) { 16731991Sheppo case LDC_NACK: 16741991Sheppo /* RDX NACK received */ 16751991Sheppo DWARN(ldcp->id, 16761991Sheppo "i_ldc_process_RDX: (0x%llx) RDX NACK received\n", 16771991Sheppo ldcp->id); 16781991Sheppo 16791991Sheppo /* Reset the channel -- as we cannot continue */ 16802336Snarayan mutex_enter(&ldcp->tx_lock); 16812793Slm66018 i_ldc_reset(ldcp, B_TRUE); 16822336Snarayan mutex_exit(&ldcp->tx_lock); 16831991Sheppo rv = ECONNRESET; 16841991Sheppo 16851991Sheppo break; 16861991Sheppo 16871991Sheppo case LDC_INFO: 16881991Sheppo 16891991Sheppo /* 16901991Sheppo * if channel is UP and a RDX received after data transmission 16911991Sheppo * has commenced it is an error 16921991Sheppo */ 16931991Sheppo if ((ldcp->tstate == TS_UP) && (ldcp->hstate & TS_RCVD_RDX)) { 16941991Sheppo DWARN(DBG_ALL_LDCS, 16951991Sheppo "i_ldc_process_RDX: (0x%llx) unexpected RDX" 16961991Sheppo " - LDC reset\n", ldcp->id); 16972336Snarayan mutex_enter(&ldcp->tx_lock); 16982793Slm66018 i_ldc_reset(ldcp, B_TRUE); 16992336Snarayan mutex_exit(&ldcp->tx_lock); 17001991Sheppo return (ECONNRESET); 17011991Sheppo } 17021991Sheppo 17031991Sheppo ldcp->hstate |= TS_RCVD_RDX; 17041991Sheppo ldcp->tstate |= TS_HSHAKE_DONE; 17052793Slm66018 if ((ldcp->tstate & TS_IN_RESET) == 0) 17062793Slm66018 ldcp->status = LDC_UP; 17071991Sheppo 17081991Sheppo D1(DBG_ALL_LDCS, "(0x%llx) Handshake Complete\n", ldcp->id); 17091991Sheppo break; 17101991Sheppo 17111991Sheppo default: 17121991Sheppo DWARN(ldcp->id, "i_ldc_process_RDX: (0x%llx) unexp ACK\n", 17131991Sheppo ldcp->id); 17141991Sheppo 17151991Sheppo /* Reset the channel -- as we cannot continue */ 17162336Snarayan mutex_enter(&ldcp->tx_lock); 17172793Slm66018 i_ldc_reset(ldcp, B_TRUE); 17182336Snarayan mutex_exit(&ldcp->tx_lock); 17191991Sheppo rv = ECONNRESET; 17201991Sheppo break; 17211991Sheppo } 17221991Sheppo 17231991Sheppo return (rv); 17241991Sheppo } 17251991Sheppo 17261991Sheppo /* 17271991Sheppo * Process an incoming ACK for a data packet 17281991Sheppo */ 17291991Sheppo static int 17301991Sheppo i_ldc_process_data_ACK(ldc_chan_t *ldcp, ldc_msg_t *msg) 17311991Sheppo { 17321991Sheppo int rv; 17331991Sheppo uint64_t tx_head; 17341991Sheppo ldc_msg_t *pkt; 17351991Sheppo 17362336Snarayan /* Obtain Tx lock */ 17372336Snarayan mutex_enter(&ldcp->tx_lock); 17382336Snarayan 17391991Sheppo /* 17402336Snarayan * Read the current Tx head and tail 17411991Sheppo */ 17421991Sheppo rv = hv_ldc_tx_get_state(ldcp->id, 17431991Sheppo &ldcp->tx_head, &ldcp->tx_tail, &ldcp->link_state); 17441991Sheppo if (rv != 0) { 17451991Sheppo cmn_err(CE_WARN, 17461991Sheppo "i_ldc_process_data_ACK: (0x%lx) cannot read qptrs\n", 17471991Sheppo ldcp->id); 17482336Snarayan 17492336Snarayan /* Reset the channel -- as we cannot continue */ 17502793Slm66018 i_ldc_reset(ldcp, B_TRUE); 17512336Snarayan mutex_exit(&ldcp->tx_lock); 17522336Snarayan return (ECONNRESET); 17531991Sheppo } 17541991Sheppo 17551991Sheppo /* 17561991Sheppo * loop from where the previous ACK location was to the 17571991Sheppo * current head location. This is how far the HV has 17581991Sheppo * actually send pkts. Pkts between head and tail are 17591991Sheppo * yet to be sent by HV. 17601991Sheppo */ 17611991Sheppo tx_head = ldcp->tx_ackd_head; 17621991Sheppo for (;;) { 17631991Sheppo pkt = (ldc_msg_t *)(ldcp->tx_q_va + tx_head); 17641991Sheppo tx_head = (tx_head + LDC_PACKET_SIZE) % 17654690Snarayan (ldcp->tx_q_entries << LDC_PACKET_SHIFT); 17661991Sheppo 17671991Sheppo if (pkt->seqid == msg->ackid) { 17681991Sheppo D2(ldcp->id, 17691991Sheppo "i_ldc_process_data_ACK: (0x%llx) found packet\n", 17701991Sheppo ldcp->id); 17711991Sheppo ldcp->last_ack_rcd = msg->ackid; 17721991Sheppo ldcp->tx_ackd_head = tx_head; 17731991Sheppo break; 17741991Sheppo } 17751991Sheppo if (tx_head == ldcp->tx_head) { 17761991Sheppo /* could not find packet */ 17771991Sheppo DWARN(ldcp->id, 17781991Sheppo "i_ldc_process_data_ACK: (0x%llx) invalid ACKid\n", 17791991Sheppo ldcp->id); 17802336Snarayan 17812336Snarayan /* Reset the channel -- as we cannot continue */ 17822793Slm66018 i_ldc_reset(ldcp, B_TRUE); 17832336Snarayan mutex_exit(&ldcp->tx_lock); 17842336Snarayan return (ECONNRESET); 17851991Sheppo } 17861991Sheppo } 17871991Sheppo 17882336Snarayan mutex_exit(&ldcp->tx_lock); 17891991Sheppo return (0); 17901991Sheppo } 17911991Sheppo 17921991Sheppo /* 17931991Sheppo * Process incoming control message 17941991Sheppo * Return 0 - session can continue 17951991Sheppo * EAGAIN - reprocess packet - state was changed 17961991Sheppo * ECONNRESET - channel was reset 17971991Sheppo */ 17981991Sheppo static int 17991991Sheppo i_ldc_ctrlmsg(ldc_chan_t *ldcp, ldc_msg_t *msg) 18001991Sheppo { 18011991Sheppo int rv = 0; 18021991Sheppo 18032793Slm66018 D1(ldcp->id, "i_ldc_ctrlmsg: (%llx) tstate = %lx, hstate = %lx\n", 18042793Slm66018 ldcp->id, ldcp->tstate, ldcp->hstate); 18052793Slm66018 18062793Slm66018 switch (ldcp->tstate & ~TS_IN_RESET) { 18071991Sheppo 18081991Sheppo case TS_OPEN: 18091991Sheppo case TS_READY: 18101991Sheppo 18111991Sheppo switch (msg->ctrl & LDC_CTRL_MASK) { 18121991Sheppo case LDC_VER: 18131991Sheppo /* process version message */ 18141991Sheppo rv = i_ldc_process_VER(ldcp, msg); 18151991Sheppo break; 18161991Sheppo default: 18171991Sheppo DWARN(ldcp->id, 18181991Sheppo "i_ldc_ctrlmsg: (0x%llx) unexp ctrl 0x%x " 18191991Sheppo "tstate=0x%x\n", ldcp->id, 18201991Sheppo (msg->ctrl & LDC_CTRL_MASK), ldcp->tstate); 18211991Sheppo break; 18221991Sheppo } 18231991Sheppo 18241991Sheppo break; 18251991Sheppo 18261991Sheppo case TS_VREADY: 18271991Sheppo 18281991Sheppo switch (msg->ctrl & LDC_CTRL_MASK) { 18291991Sheppo case LDC_VER: 18302793Slm66018 /* process version message */ 18312793Slm66018 rv = i_ldc_process_VER(ldcp, msg); 18321991Sheppo break; 18331991Sheppo case LDC_RTS: 18341991Sheppo /* process RTS message */ 18351991Sheppo rv = i_ldc_process_RTS(ldcp, msg); 18361991Sheppo break; 18371991Sheppo case LDC_RTR: 18381991Sheppo /* process RTR message */ 18391991Sheppo rv = i_ldc_process_RTR(ldcp, msg); 18401991Sheppo break; 18411991Sheppo case LDC_RDX: 18421991Sheppo /* process RDX message */ 18431991Sheppo rv = i_ldc_process_RDX(ldcp, msg); 18441991Sheppo break; 18451991Sheppo default: 18461991Sheppo DWARN(ldcp->id, 18471991Sheppo "i_ldc_ctrlmsg: (0x%llx) unexp ctrl 0x%x " 18481991Sheppo "tstate=0x%x\n", ldcp->id, 18491991Sheppo (msg->ctrl & LDC_CTRL_MASK), ldcp->tstate); 18501991Sheppo break; 18511991Sheppo } 18521991Sheppo 18531991Sheppo break; 18541991Sheppo 18551991Sheppo case TS_UP: 18561991Sheppo 18571991Sheppo switch (msg->ctrl & LDC_CTRL_MASK) { 18581991Sheppo case LDC_VER: 18591991Sheppo DWARN(ldcp->id, 18601991Sheppo "i_ldc_ctrlmsg: (0x%llx) unexpected VER " 18611991Sheppo "- LDC reset\n", ldcp->id); 18621991Sheppo /* peer is redoing version negotiation */ 18632336Snarayan mutex_enter(&ldcp->tx_lock); 18641991Sheppo (void) i_ldc_txq_reconf(ldcp); 18651991Sheppo i_ldc_reset_state(ldcp); 18662336Snarayan mutex_exit(&ldcp->tx_lock); 18671991Sheppo rv = EAGAIN; 18681991Sheppo break; 18691991Sheppo 18701991Sheppo case LDC_RDX: 18711991Sheppo /* process RDX message */ 18721991Sheppo rv = i_ldc_process_RDX(ldcp, msg); 18731991Sheppo break; 18741991Sheppo 18751991Sheppo default: 18761991Sheppo DWARN(ldcp->id, 18771991Sheppo "i_ldc_ctrlmsg: (0x%llx) unexp ctrl 0x%x " 18781991Sheppo "tstate=0x%x\n", ldcp->id, 18791991Sheppo (msg->ctrl & LDC_CTRL_MASK), ldcp->tstate); 18801991Sheppo break; 18811991Sheppo } 18821991Sheppo } 18831991Sheppo 18841991Sheppo return (rv); 18851991Sheppo } 18861991Sheppo 18871991Sheppo /* 18881991Sheppo * Register channel with the channel nexus 18891991Sheppo */ 18901991Sheppo static int 18911991Sheppo i_ldc_register_channel(ldc_chan_t *ldcp) 18921991Sheppo { 18931991Sheppo int rv = 0; 18941991Sheppo ldc_cnex_t *cinfo = &ldcssp->cinfo; 18951991Sheppo 18961991Sheppo if (cinfo->dip == NULL) { 18971991Sheppo DWARN(ldcp->id, 18981991Sheppo "i_ldc_register_channel: cnex has not registered\n"); 18991991Sheppo return (EAGAIN); 19001991Sheppo } 19011991Sheppo 19021991Sheppo rv = cinfo->reg_chan(cinfo->dip, ldcp->id, ldcp->devclass); 19031991Sheppo if (rv) { 19041991Sheppo DWARN(ldcp->id, 19051991Sheppo "i_ldc_register_channel: cannot register channel\n"); 19061991Sheppo return (rv); 19071991Sheppo } 19081991Sheppo 19091991Sheppo rv = cinfo->add_intr(cinfo->dip, ldcp->id, CNEX_TX_INTR, 19101991Sheppo i_ldc_tx_hdlr, ldcp, NULL); 19111991Sheppo if (rv) { 19121991Sheppo DWARN(ldcp->id, 19131991Sheppo "i_ldc_register_channel: cannot add Tx interrupt\n"); 19141991Sheppo (void) cinfo->unreg_chan(cinfo->dip, ldcp->id); 19151991Sheppo return (rv); 19161991Sheppo } 19171991Sheppo 19181991Sheppo rv = cinfo->add_intr(cinfo->dip, ldcp->id, CNEX_RX_INTR, 19191991Sheppo i_ldc_rx_hdlr, ldcp, NULL); 19201991Sheppo if (rv) { 19211991Sheppo DWARN(ldcp->id, 19221991Sheppo "i_ldc_register_channel: cannot add Rx interrupt\n"); 19231991Sheppo (void) cinfo->rem_intr(cinfo->dip, ldcp->id, CNEX_TX_INTR); 19241991Sheppo (void) cinfo->unreg_chan(cinfo->dip, ldcp->id); 19251991Sheppo return (rv); 19261991Sheppo } 19271991Sheppo 19281991Sheppo ldcp->tstate |= TS_CNEX_RDY; 19291991Sheppo 19301991Sheppo return (0); 19311991Sheppo } 19321991Sheppo 19331991Sheppo /* 19341991Sheppo * Unregister a channel with the channel nexus 19351991Sheppo */ 19361991Sheppo static int 19371991Sheppo i_ldc_unregister_channel(ldc_chan_t *ldcp) 19381991Sheppo { 19391991Sheppo int rv = 0; 19401991Sheppo ldc_cnex_t *cinfo = &ldcssp->cinfo; 19411991Sheppo 19421991Sheppo if (cinfo->dip == NULL) { 19431991Sheppo DWARN(ldcp->id, 19441991Sheppo "i_ldc_unregister_channel: cnex has not registered\n"); 19451991Sheppo return (EAGAIN); 19461991Sheppo } 19471991Sheppo 19481991Sheppo if (ldcp->tstate & TS_CNEX_RDY) { 19491991Sheppo 19502336Snarayan /* Remove the Rx interrupt */ 19511991Sheppo rv = cinfo->rem_intr(cinfo->dip, ldcp->id, CNEX_RX_INTR); 19521991Sheppo if (rv) { 19532793Slm66018 if (rv != EAGAIN) { 19542793Slm66018 DWARN(ldcp->id, 19552793Slm66018 "i_ldc_unregister_channel: err removing " 19562793Slm66018 "Rx intr\n"); 19572793Slm66018 return (rv); 19582793Slm66018 } 19592793Slm66018 19602793Slm66018 /* 19612793Slm66018 * If interrupts are pending and handler has 19622793Slm66018 * finished running, clear interrupt and try 19632793Slm66018 * again 19642793Slm66018 */ 19652793Slm66018 if (ldcp->rx_intr_state != LDC_INTR_PEND) 19662793Slm66018 return (rv); 19672793Slm66018 19682793Slm66018 (void) i_ldc_clear_intr(ldcp, CNEX_RX_INTR); 19692793Slm66018 rv = cinfo->rem_intr(cinfo->dip, ldcp->id, 19702793Slm66018 CNEX_RX_INTR); 19712793Slm66018 if (rv) { 19722793Slm66018 DWARN(ldcp->id, "i_ldc_unregister_channel: " 19732793Slm66018 "err removing Rx interrupt\n"); 19742793Slm66018 return (rv); 19752793Slm66018 } 19761991Sheppo } 19772336Snarayan 19782336Snarayan /* Remove the Tx interrupt */ 19791991Sheppo rv = cinfo->rem_intr(cinfo->dip, ldcp->id, CNEX_TX_INTR); 19801991Sheppo if (rv) { 19811991Sheppo DWARN(ldcp->id, 19821991Sheppo "i_ldc_unregister_channel: err removing Tx intr\n"); 19832336Snarayan return (rv); 19841991Sheppo } 19852336Snarayan 19862336Snarayan /* Unregister the channel */ 19871991Sheppo rv = cinfo->unreg_chan(ldcssp->cinfo.dip, ldcp->id); 19881991Sheppo if (rv) { 19891991Sheppo DWARN(ldcp->id, 19901991Sheppo "i_ldc_unregister_channel: cannot unreg channel\n"); 19912336Snarayan return (rv); 19921991Sheppo } 19931991Sheppo 19941991Sheppo ldcp->tstate &= ~TS_CNEX_RDY; 19951991Sheppo } 19961991Sheppo 19971991Sheppo return (0); 19981991Sheppo } 19991991Sheppo 20001991Sheppo 20011991Sheppo /* 20021991Sheppo * LDC transmit interrupt handler 20031991Sheppo * triggered for chanel up/down/reset events 20041991Sheppo * and Tx queue content changes 20051991Sheppo */ 20061991Sheppo static uint_t 20071991Sheppo i_ldc_tx_hdlr(caddr_t arg1, caddr_t arg2) 20081991Sheppo { 20091991Sheppo _NOTE(ARGUNUSED(arg2)) 20101991Sheppo 20111991Sheppo int rv; 20121991Sheppo ldc_chan_t *ldcp; 20131991Sheppo boolean_t notify_client = B_FALSE; 20142793Slm66018 uint64_t notify_event = 0, link_state; 20151991Sheppo 20161991Sheppo /* Get the channel for which interrupt was received */ 20171991Sheppo ASSERT(arg1 != NULL); 20181991Sheppo ldcp = (ldc_chan_t *)arg1; 20191991Sheppo 20201991Sheppo D1(ldcp->id, "i_ldc_tx_hdlr: (0x%llx) Received intr, ldcp=0x%p\n", 20211991Sheppo ldcp->id, ldcp); 20221991Sheppo 20231991Sheppo /* Lock channel */ 20241991Sheppo mutex_enter(&ldcp->lock); 20251991Sheppo 20262336Snarayan /* Obtain Tx lock */ 20272336Snarayan mutex_enter(&ldcp->tx_lock); 20282336Snarayan 20292531Snarayan /* mark interrupt as pending */ 20302793Slm66018 ldcp->tx_intr_state = LDC_INTR_ACTIVE; 20312793Slm66018 20322793Slm66018 /* save current link state */ 20332793Slm66018 link_state = ldcp->link_state; 20342531Snarayan 20351991Sheppo rv = hv_ldc_tx_get_state(ldcp->id, &ldcp->tx_head, &ldcp->tx_tail, 20361991Sheppo &ldcp->link_state); 20371991Sheppo if (rv) { 20381991Sheppo cmn_err(CE_WARN, 20391991Sheppo "i_ldc_tx_hdlr: (0x%lx) cannot read queue ptrs rv=0x%d\n", 20401991Sheppo ldcp->id, rv); 20412531Snarayan i_ldc_clear_intr(ldcp, CNEX_TX_INTR); 20422336Snarayan mutex_exit(&ldcp->tx_lock); 20431991Sheppo mutex_exit(&ldcp->lock); 20441991Sheppo return (DDI_INTR_CLAIMED); 20451991Sheppo } 20461991Sheppo 20471991Sheppo /* 20481991Sheppo * reset the channel state if the channel went down 20491991Sheppo * (other side unconfigured queue) or channel was reset 20501991Sheppo * (other side reconfigured its queue) 20511991Sheppo */ 20522793Slm66018 if (link_state != ldcp->link_state && 20532793Slm66018 ldcp->link_state == LDC_CHANNEL_DOWN) { 20541991Sheppo D1(ldcp->id, "i_ldc_tx_hdlr: channel link down\n", ldcp->id); 20552793Slm66018 i_ldc_reset(ldcp, B_FALSE); 20561991Sheppo notify_client = B_TRUE; 20571991Sheppo notify_event = LDC_EVT_DOWN; 20581991Sheppo } 20591991Sheppo 20602793Slm66018 if (link_state != ldcp->link_state && 20612793Slm66018 ldcp->link_state == LDC_CHANNEL_RESET) { 20621991Sheppo D1(ldcp->id, "i_ldc_tx_hdlr: channel link reset\n", ldcp->id); 20632793Slm66018 i_ldc_reset(ldcp, B_FALSE); 20641991Sheppo notify_client = B_TRUE; 20651991Sheppo notify_event = LDC_EVT_RESET; 20661991Sheppo } 20671991Sheppo 20682793Slm66018 if (link_state != ldcp->link_state && 20692793Slm66018 (ldcp->tstate & ~TS_IN_RESET) == TS_OPEN && 20702793Slm66018 ldcp->link_state == LDC_CHANNEL_UP) { 20711991Sheppo D1(ldcp->id, "i_ldc_tx_hdlr: channel link up\n", ldcp->id); 20721991Sheppo notify_client = B_TRUE; 20731991Sheppo notify_event = LDC_EVT_RESET; 20741991Sheppo ldcp->tstate |= TS_LINK_READY; 20751991Sheppo ldcp->status = LDC_READY; 20761991Sheppo } 20771991Sheppo 20781991Sheppo /* if callbacks are disabled, do not notify */ 20791991Sheppo if (!ldcp->cb_enabled) 20801991Sheppo notify_client = B_FALSE; 20811991Sheppo 20823151Ssg70180 i_ldc_clear_intr(ldcp, CNEX_TX_INTR); 20834690Snarayan mutex_exit(&ldcp->tx_lock); 20841991Sheppo 20851991Sheppo if (notify_client) { 20862793Slm66018 ldcp->cb_inprogress = B_TRUE; 20872793Slm66018 mutex_exit(&ldcp->lock); 20881991Sheppo rv = ldcp->cb(notify_event, ldcp->cb_arg); 20891991Sheppo if (rv) { 20901991Sheppo DWARN(ldcp->id, "i_ldc_tx_hdlr: (0x%llx) callback " 20911991Sheppo "failure", ldcp->id); 20921991Sheppo } 20931991Sheppo mutex_enter(&ldcp->lock); 20941991Sheppo ldcp->cb_inprogress = B_FALSE; 20952793Slm66018 } 20962793Slm66018 20971991Sheppo mutex_exit(&ldcp->lock); 20981991Sheppo 20991991Sheppo D1(ldcp->id, "i_ldc_tx_hdlr: (0x%llx) exiting handler", ldcp->id); 21001991Sheppo 21011991Sheppo return (DDI_INTR_CLAIMED); 21021991Sheppo } 21031991Sheppo 21041991Sheppo /* 21055944Sha137994 * Process the Rx HV queue. 21065944Sha137994 * 21075944Sha137994 * Returns 0 if data packets were found and no errors were encountered, 21085944Sha137994 * otherwise returns an error. In either case, the *notify argument is 21095944Sha137994 * set to indicate whether or not the client callback function should 21105944Sha137994 * be invoked. The *event argument is set to contain the callback event. 21115944Sha137994 * 21125944Sha137994 * Depending on the channel mode, packets are handled differently: 21135944Sha137994 * 21145944Sha137994 * RAW MODE 21155944Sha137994 * For raw mode channels, when a data packet is encountered, 21165944Sha137994 * processing stops and all packets are left on the queue to be removed 21175944Sha137994 * and processed by the ldc_read code path. 21185944Sha137994 * 21195944Sha137994 * UNRELIABLE MODE 21205944Sha137994 * For unreliable mode, when a data packet is encountered, processing 21215944Sha137994 * stops, and all packets are left on the queue to be removed and 21225944Sha137994 * processed by the ldc_read code path. Control packets are processed 21235944Sha137994 * inline if they are encountered before any data packets. 21245944Sha137994 * 2125*6408Sha137994 * RELIABLE MODE 2126*6408Sha137994 * For reliable mode channels, all packets on the receive queue 21275944Sha137994 * are processed: data packets are copied to the data queue and 21285944Sha137994 * control packets are processed inline. Packets are only left on 21295944Sha137994 * the receive queue when the data queue is full. 21301991Sheppo */ 21311991Sheppo static uint_t 21325944Sha137994 i_ldc_rx_process_hvq(ldc_chan_t *ldcp, boolean_t *notify_client, 21335944Sha137994 uint64_t *notify_event) 21341991Sheppo { 21351991Sheppo int rv; 21361991Sheppo uint64_t rx_head, rx_tail; 21371991Sheppo ldc_msg_t *msg; 21382793Slm66018 uint64_t link_state, first_fragment = 0; 21395944Sha137994 boolean_t trace_length = B_TRUE; 21405944Sha137994 21415944Sha137994 ASSERT(MUTEX_HELD(&ldcp->lock)); 21425944Sha137994 *notify_client = B_FALSE; 21435944Sha137994 *notify_event = 0; 21441991Sheppo 21451991Sheppo /* 21461991Sheppo * Read packet(s) from the queue 21471991Sheppo */ 21481991Sheppo for (;;) { 21491991Sheppo 21502793Slm66018 link_state = ldcp->link_state; 21511991Sheppo rv = hv_ldc_rx_get_state(ldcp->id, &rx_head, &rx_tail, 21521991Sheppo &ldcp->link_state); 21531991Sheppo if (rv) { 21541991Sheppo cmn_err(CE_WARN, 21555944Sha137994 "i_ldc_rx_process_hvq: (0x%lx) cannot read " 21561991Sheppo "queue ptrs, rv=0x%d\n", ldcp->id, rv); 21571991Sheppo i_ldc_clear_intr(ldcp, CNEX_RX_INTR); 21585944Sha137994 return (EIO); 21591991Sheppo } 21601991Sheppo 21611991Sheppo /* 21621991Sheppo * reset the channel state if the channel went down 21631991Sheppo * (other side unconfigured queue) or channel was reset 21642793Slm66018 * (other side reconfigured its queue) 21651991Sheppo */ 21662793Slm66018 21672793Slm66018 if (link_state != ldcp->link_state) { 21683010Slm66018 21692793Slm66018 switch (ldcp->link_state) { 21702793Slm66018 case LDC_CHANNEL_DOWN: 21715944Sha137994 D1(ldcp->id, "i_ldc_rx_process_hvq: channel " 21722793Slm66018 "link down\n", ldcp->id); 21732793Slm66018 mutex_enter(&ldcp->tx_lock); 21742793Slm66018 i_ldc_reset(ldcp, B_FALSE); 21752793Slm66018 mutex_exit(&ldcp->tx_lock); 21765944Sha137994 *notify_client = B_TRUE; 21775944Sha137994 *notify_event = LDC_EVT_DOWN; 21782793Slm66018 goto loop_exit; 21792793Slm66018 21802793Slm66018 case LDC_CHANNEL_UP: 21815944Sha137994 D1(ldcp->id, "i_ldc_rx_process_hvq: " 21822793Slm66018 "channel link up\n", ldcp->id); 21832793Slm66018 21842793Slm66018 if ((ldcp->tstate & ~TS_IN_RESET) == TS_OPEN) { 21855944Sha137994 *notify_client = B_TRUE; 21865944Sha137994 *notify_event = LDC_EVT_RESET; 21872793Slm66018 ldcp->tstate |= TS_LINK_READY; 21882793Slm66018 ldcp->status = LDC_READY; 21892793Slm66018 } 21902793Slm66018 break; 21912793Slm66018 21922793Slm66018 case LDC_CHANNEL_RESET: 21932793Slm66018 default: 21942793Slm66018 #ifdef DEBUG 21952793Slm66018 force_reset: 21962793Slm66018 #endif 21975944Sha137994 D1(ldcp->id, "i_ldc_rx_process_hvq: channel " 21982793Slm66018 "link reset\n", ldcp->id); 21992793Slm66018 mutex_enter(&ldcp->tx_lock); 22002793Slm66018 i_ldc_reset(ldcp, B_FALSE); 22012793Slm66018 mutex_exit(&ldcp->tx_lock); 22025944Sha137994 *notify_client = B_TRUE; 22035944Sha137994 *notify_event = LDC_EVT_RESET; 22042793Slm66018 break; 22052793Slm66018 } 22061991Sheppo } 22072793Slm66018 22082793Slm66018 #ifdef DEBUG 22092793Slm66018 if (LDC_INJECT_RESET(ldcp)) 22102793Slm66018 goto force_reset; 22112793Slm66018 #endif 22125944Sha137994 if (trace_length) { 22135944Sha137994 TRACE_RXHVQ_LENGTH(ldcp, rx_head, rx_tail); 22145944Sha137994 trace_length = B_FALSE; 22155944Sha137994 } 22161991Sheppo 22171991Sheppo if (rx_head == rx_tail) { 22185944Sha137994 D2(ldcp->id, "i_ldc_rx_process_hvq: (0x%llx) " 22195944Sha137994 "No packets\n", ldcp->id); 22201991Sheppo break; 22211991Sheppo } 22222793Slm66018 22235944Sha137994 D2(ldcp->id, "i_ldc_rx_process_hvq: head=0x%llx, " 22245944Sha137994 "tail=0x%llx\n", rx_head, rx_tail); 22255944Sha137994 DUMP_LDC_PKT(ldcp, "i_ldc_rx_process_hvq rcd", 22261991Sheppo ldcp->rx_q_va + rx_head); 22271991Sheppo 22281991Sheppo /* get the message */ 22291991Sheppo msg = (ldc_msg_t *)(ldcp->rx_q_va + rx_head); 22301991Sheppo 22311991Sheppo /* if channel is in RAW mode or data pkt, notify and return */ 22321991Sheppo if (ldcp->mode == LDC_MODE_RAW) { 22335944Sha137994 *notify_client = B_TRUE; 22345944Sha137994 *notify_event |= LDC_EVT_READ; 22351991Sheppo break; 22361991Sheppo } 22371991Sheppo 22381991Sheppo if ((msg->type & LDC_DATA) && (msg->stype & LDC_INFO)) { 22391991Sheppo 22401991Sheppo /* discard packet if channel is not up */ 22412793Slm66018 if ((ldcp->tstate & ~TS_IN_RESET) != TS_UP) { 22421991Sheppo 22431991Sheppo /* move the head one position */ 22441991Sheppo rx_head = (rx_head + LDC_PACKET_SIZE) % 22454690Snarayan (ldcp->rx_q_entries << LDC_PACKET_SHIFT); 22461991Sheppo 22471991Sheppo if (rv = i_ldc_set_rx_head(ldcp, rx_head)) 22481991Sheppo break; 22491991Sheppo 22501991Sheppo continue; 22511991Sheppo } else { 22525944Sha137994 uint64_t dq_head, dq_tail; 22535944Sha137994 2254*6408Sha137994 /* process only RELIABLE mode data packets */ 2255*6408Sha137994 if (ldcp->mode != LDC_MODE_RELIABLE) { 22565944Sha137994 if ((ldcp->tstate & TS_IN_RESET) == 0) 22575944Sha137994 *notify_client = B_TRUE; 22585944Sha137994 *notify_event |= LDC_EVT_READ; 22595944Sha137994 break; 22605944Sha137994 } 22615944Sha137994 22625944Sha137994 /* don't process packet if queue full */ 22635944Sha137994 (void) i_ldc_dq_rx_get_state(ldcp, &dq_head, 22645944Sha137994 &dq_tail, NULL); 22655944Sha137994 dq_tail = (dq_tail + LDC_PACKET_SIZE) % 22665944Sha137994 (ldcp->rx_dq_entries << LDC_PACKET_SHIFT); 22675944Sha137994 if (dq_tail == dq_head || 22685944Sha137994 LDC_INJECT_DQFULL(ldcp)) { 22695944Sha137994 rv = ENOSPC; 22705944Sha137994 break; 22715944Sha137994 } 22721991Sheppo } 22731991Sheppo } 22741991Sheppo 22751991Sheppo /* Check the sequence ID for the message received */ 22762793Slm66018 rv = i_ldc_check_seqid(ldcp, msg); 22772793Slm66018 if (rv != 0) { 22781991Sheppo 22795944Sha137994 DWARN(ldcp->id, "i_ldc_rx_process_hvq: (0x%llx) " 22805944Sha137994 "seqid error, q_ptrs=0x%lx,0x%lx", ldcp->id, 22815944Sha137994 rx_head, rx_tail); 22821991Sheppo 22831991Sheppo /* Reset last_msg_rcd to start of message */ 22842336Snarayan if (first_fragment != 0) { 22852336Snarayan ldcp->last_msg_rcd = first_fragment - 1; 22862336Snarayan first_fragment = 0; 22871991Sheppo } 22882336Snarayan 22891991Sheppo /* 22901991Sheppo * Send a NACK due to seqid mismatch 22911991Sheppo */ 22924690Snarayan rv = i_ldc_send_pkt(ldcp, msg->type, LDC_NACK, 22931991Sheppo (msg->ctrl & LDC_CTRL_MASK)); 22941991Sheppo 22951991Sheppo if (rv) { 22965944Sha137994 cmn_err(CE_NOTE, "i_ldc_rx_process_hvq: " 22975944Sha137994 "(0x%lx) err sending CTRL/DATA NACK msg\n", 22985944Sha137994 ldcp->id); 22992336Snarayan 23002336Snarayan /* if cannot send NACK - reset channel */ 23012336Snarayan mutex_enter(&ldcp->tx_lock); 23022793Slm66018 i_ldc_reset(ldcp, B_TRUE); 23032336Snarayan mutex_exit(&ldcp->tx_lock); 23043560Snarayan 23055944Sha137994 *notify_client = B_TRUE; 23065944Sha137994 *notify_event = LDC_EVT_RESET; 23072336Snarayan break; 23081991Sheppo } 23091991Sheppo 23101991Sheppo /* purge receive queue */ 23111991Sheppo (void) i_ldc_set_rx_head(ldcp, rx_tail); 23121991Sheppo break; 23131991Sheppo } 23141991Sheppo 23151991Sheppo /* record the message ID */ 23161991Sheppo ldcp->last_msg_rcd = msg->seqid; 23171991Sheppo 23181991Sheppo /* process control messages */ 23191991Sheppo if (msg->type & LDC_CTRL) { 23201991Sheppo /* save current internal state */ 23211991Sheppo uint64_t tstate = ldcp->tstate; 23221991Sheppo 23231991Sheppo rv = i_ldc_ctrlmsg(ldcp, msg); 23241991Sheppo if (rv == EAGAIN) { 23251991Sheppo /* re-process pkt - state was adjusted */ 23261991Sheppo continue; 23271991Sheppo } 23281991Sheppo if (rv == ECONNRESET) { 23295944Sha137994 *notify_client = B_TRUE; 23305944Sha137994 *notify_event = LDC_EVT_RESET; 23311991Sheppo break; 23321991Sheppo } 23331991Sheppo 23341991Sheppo /* 23351991Sheppo * control message processing was successful 23361991Sheppo * channel transitioned to ready for communication 23371991Sheppo */ 23381991Sheppo if (rv == 0 && ldcp->tstate == TS_UP && 23392793Slm66018 (tstate & ~TS_IN_RESET) != 23402793Slm66018 (ldcp->tstate & ~TS_IN_RESET)) { 23415944Sha137994 *notify_client = B_TRUE; 23425944Sha137994 *notify_event = LDC_EVT_UP; 23431991Sheppo } 23441991Sheppo } 23451991Sheppo 23463560Snarayan /* process data NACKs */ 23473560Snarayan if ((msg->type & LDC_DATA) && (msg->stype & LDC_NACK)) { 23483560Snarayan DWARN(ldcp->id, 23495944Sha137994 "i_ldc_rx_process_hvq: (0x%llx) received DATA/NACK", 23503560Snarayan ldcp->id); 23513560Snarayan mutex_enter(&ldcp->tx_lock); 23523560Snarayan i_ldc_reset(ldcp, B_TRUE); 23533560Snarayan mutex_exit(&ldcp->tx_lock); 23545944Sha137994 *notify_client = B_TRUE; 23555944Sha137994 *notify_event = LDC_EVT_RESET; 23563560Snarayan break; 23573560Snarayan } 23583560Snarayan 23591991Sheppo /* process data ACKs */ 23601991Sheppo if ((msg->type & LDC_DATA) && (msg->stype & LDC_ACK)) { 23612336Snarayan if (rv = i_ldc_process_data_ACK(ldcp, msg)) { 23625944Sha137994 *notify_client = B_TRUE; 23635944Sha137994 *notify_event = LDC_EVT_RESET; 23642336Snarayan break; 23652336Snarayan } 23661991Sheppo } 23671991Sheppo 23685944Sha137994 if ((msg->type & LDC_DATA) && (msg->stype & LDC_INFO)) { 2369*6408Sha137994 ASSERT(ldcp->mode == LDC_MODE_RELIABLE); 23705944Sha137994 23715944Sha137994 /* 23725944Sha137994 * Copy the data packet to the data queue. Note 23735944Sha137994 * that the copy routine updates the rx_head pointer. 23745944Sha137994 */ 23755944Sha137994 i_ldc_rxdq_copy(ldcp, &rx_head); 23765944Sha137994 23775944Sha137994 if ((ldcp->tstate & TS_IN_RESET) == 0) 23785944Sha137994 *notify_client = B_TRUE; 23795944Sha137994 *notify_event |= LDC_EVT_READ; 23805944Sha137994 } else { 23815944Sha137994 rx_head = (rx_head + LDC_PACKET_SIZE) % 23825944Sha137994 (ldcp->rx_q_entries << LDC_PACKET_SHIFT); 23835944Sha137994 } 23845944Sha137994 23851991Sheppo /* move the head one position */ 23862032Slm66018 if (rv = i_ldc_set_rx_head(ldcp, rx_head)) { 23875944Sha137994 *notify_client = B_TRUE; 23885944Sha137994 *notify_event = LDC_EVT_RESET; 23891991Sheppo break; 23902032Slm66018 } 23911991Sheppo 23921991Sheppo } /* for */ 23931991Sheppo 23942793Slm66018 loop_exit: 23952793Slm66018 2396*6408Sha137994 if (ldcp->mode == LDC_MODE_RELIABLE) { 23975944Sha137994 /* ACK data packets */ 23985944Sha137994 if ((*notify_event & 23995944Sha137994 (LDC_EVT_READ | LDC_EVT_RESET)) == LDC_EVT_READ) { 24005944Sha137994 int ack_rv; 24015944Sha137994 ack_rv = i_ldc_send_pkt(ldcp, LDC_DATA, LDC_ACK, 0); 24025944Sha137994 if (ack_rv && ack_rv != EWOULDBLOCK) { 24035944Sha137994 cmn_err(CE_NOTE, 24045944Sha137994 "i_ldc_rx_process_hvq: (0x%lx) cannot " 24055944Sha137994 "send ACK\n", ldcp->id); 24065944Sha137994 24075944Sha137994 mutex_enter(&ldcp->tx_lock); 24085944Sha137994 i_ldc_reset(ldcp, B_FALSE); 24095944Sha137994 mutex_exit(&ldcp->tx_lock); 24105944Sha137994 24115944Sha137994 *notify_client = B_TRUE; 24125944Sha137994 *notify_event = LDC_EVT_RESET; 24135944Sha137994 goto skip_ackpeek; 24145944Sha137994 } 24155944Sha137994 } 24165944Sha137994 24175944Sha137994 /* 24185944Sha137994 * If we have no more space on the data queue, make sure 24195944Sha137994 * there are no ACKs on the rx queue waiting to be processed. 24205944Sha137994 */ 24215944Sha137994 if (rv == ENOSPC) { 24225944Sha137994 if (i_ldc_rx_ackpeek(ldcp, rx_head, rx_tail) != 0) { 24235944Sha137994 ldcp->rx_ack_head = ACKPEEK_HEAD_INVALID; 24245944Sha137994 *notify_client = B_TRUE; 24255944Sha137994 *notify_event = LDC_EVT_RESET; 24265944Sha137994 } 24275944Sha137994 } else { 24285944Sha137994 ldcp->rx_ack_head = ACKPEEK_HEAD_INVALID; 24291991Sheppo } 24305944Sha137994 } 24315944Sha137994 24325944Sha137994 skip_ackpeek: 24335944Sha137994 24345944Sha137994 /* Return, indicating whether or not data packets were found */ 24355944Sha137994 if ((*notify_event & (LDC_EVT_READ | LDC_EVT_RESET)) == LDC_EVT_READ) 24365944Sha137994 return (0); 24375944Sha137994 24385944Sha137994 return (ENOMSG); 24391991Sheppo } 24401991Sheppo 24415944Sha137994 /* 24425944Sha137994 * Process any ACK packets on the HV receive queue. 24435944Sha137994 * 2444*6408Sha137994 * This function is only used by RELIABLE mode channels when the 24455944Sha137994 * secondary data queue fills up and there are packets remaining on 24465944Sha137994 * the HV receive queue. 24475944Sha137994 */ 24485944Sha137994 int 24495944Sha137994 i_ldc_rx_ackpeek(ldc_chan_t *ldcp, uint64_t rx_head, uint64_t rx_tail) 24505944Sha137994 { 24515944Sha137994 int rv = 0; 24525944Sha137994 ldc_msg_t *msg; 24535944Sha137994 24545944Sha137994 if (ldcp->rx_ack_head == ACKPEEK_HEAD_INVALID) 24555944Sha137994 ldcp->rx_ack_head = rx_head; 24565944Sha137994 24575944Sha137994 while (ldcp->rx_ack_head != rx_tail) { 24585944Sha137994 msg = (ldc_msg_t *)(ldcp->rx_q_va + ldcp->rx_ack_head); 24595944Sha137994 24605944Sha137994 if ((msg->type & LDC_DATA) && (msg->stype & LDC_ACK)) { 24615944Sha137994 if (rv = i_ldc_process_data_ACK(ldcp, msg)) 24625944Sha137994 break; 24635944Sha137994 msg->stype &= ~LDC_ACK; 24645944Sha137994 } 24655944Sha137994 24665944Sha137994 ldcp->rx_ack_head = 24675944Sha137994 (ldcp->rx_ack_head + LDC_PACKET_SIZE) % 24685944Sha137994 (ldcp->rx_q_entries << LDC_PACKET_SHIFT); 24695944Sha137994 } 24705944Sha137994 return (rv); 24715944Sha137994 } 24721991Sheppo 24731991Sheppo /* -------------------------------------------------------------------------- */ 24741991Sheppo 24751991Sheppo /* 24761991Sheppo * LDC API functions 24771991Sheppo */ 24781991Sheppo 24791991Sheppo /* 24801991Sheppo * Initialize the channel. Allocate internal structure and memory for 24811991Sheppo * TX/RX queues, and initialize locks. 24821991Sheppo */ 24831991Sheppo int 24841991Sheppo ldc_init(uint64_t id, ldc_attr_t *attr, ldc_handle_t *handle) 24851991Sheppo { 24861991Sheppo ldc_chan_t *ldcp; 24871991Sheppo int rv, exit_val; 24881991Sheppo uint64_t ra_base, nentries; 24892410Slm66018 uint64_t qlen; 24901991Sheppo 24911991Sheppo exit_val = EINVAL; /* guarantee an error if exit on failure */ 24921991Sheppo 24931991Sheppo if (attr == NULL) { 24941991Sheppo DWARN(id, "ldc_init: (0x%llx) invalid attr\n", id); 24951991Sheppo return (EINVAL); 24961991Sheppo } 24971991Sheppo if (handle == NULL) { 24981991Sheppo DWARN(id, "ldc_init: (0x%llx) invalid handle\n", id); 24991991Sheppo return (EINVAL); 25001991Sheppo } 25011991Sheppo 25021991Sheppo /* check if channel is valid */ 25031991Sheppo rv = hv_ldc_tx_qinfo(id, &ra_base, &nentries); 25041991Sheppo if (rv == H_ECHANNEL) { 25051991Sheppo DWARN(id, "ldc_init: (0x%llx) invalid channel id\n", id); 25061991Sheppo return (EINVAL); 25071991Sheppo } 25081991Sheppo 25091991Sheppo /* check if the channel has already been initialized */ 25101991Sheppo mutex_enter(&ldcssp->lock); 25111991Sheppo ldcp = ldcssp->chan_list; 25121991Sheppo while (ldcp != NULL) { 25131991Sheppo if (ldcp->id == id) { 25141991Sheppo DWARN(id, "ldc_init: (0x%llx) already initialized\n", 25151991Sheppo id); 25161991Sheppo mutex_exit(&ldcssp->lock); 25171991Sheppo return (EADDRINUSE); 25181991Sheppo } 25191991Sheppo ldcp = ldcp->next; 25201991Sheppo } 25211991Sheppo mutex_exit(&ldcssp->lock); 25221991Sheppo 25231991Sheppo ASSERT(ldcp == NULL); 25241991Sheppo 25251991Sheppo *handle = 0; 25261991Sheppo 25271991Sheppo /* Allocate an ldcp structure */ 25281991Sheppo ldcp = kmem_zalloc(sizeof (ldc_chan_t), KM_SLEEP); 25291991Sheppo 25302336Snarayan /* 25312336Snarayan * Initialize the channel and Tx lock 25322336Snarayan * 25332336Snarayan * The channel 'lock' protects the entire channel and 25342336Snarayan * should be acquired before initializing, resetting, 25352336Snarayan * destroying or reading from a channel. 25362336Snarayan * 25372336Snarayan * The 'tx_lock' should be acquired prior to transmitting 25382336Snarayan * data over the channel. The lock should also be acquired 25392336Snarayan * prior to channel reconfiguration (in order to prevent 25402336Snarayan * concurrent writes). 25412336Snarayan * 25422336Snarayan * ORDERING: When both locks are being acquired, to prevent 25432336Snarayan * deadlocks, the channel lock should be always acquired prior 25442336Snarayan * to the tx_lock. 25452336Snarayan */ 25461991Sheppo mutex_init(&ldcp->lock, NULL, MUTEX_DRIVER, NULL); 25472336Snarayan mutex_init(&ldcp->tx_lock, NULL, MUTEX_DRIVER, NULL); 25481991Sheppo 25491991Sheppo /* Initialize the channel */ 25501991Sheppo ldcp->id = id; 25511991Sheppo ldcp->cb = NULL; 25521991Sheppo ldcp->cb_arg = NULL; 25531991Sheppo ldcp->cb_inprogress = B_FALSE; 25541991Sheppo ldcp->cb_enabled = B_FALSE; 25551991Sheppo ldcp->next = NULL; 25561991Sheppo 25571991Sheppo /* Read attributes */ 25581991Sheppo ldcp->mode = attr->mode; 25591991Sheppo ldcp->devclass = attr->devclass; 25601991Sheppo ldcp->devinst = attr->instance; 25612410Slm66018 ldcp->mtu = (attr->mtu > 0) ? attr->mtu : LDC_DEFAULT_MTU; 25621991Sheppo 25631991Sheppo D1(ldcp->id, 25641991Sheppo "ldc_init: (0x%llx) channel attributes, class=0x%x, " 25652410Slm66018 "instance=0x%llx, mode=%d, mtu=%d\n", 25662410Slm66018 ldcp->id, ldcp->devclass, ldcp->devinst, ldcp->mode, ldcp->mtu); 25671991Sheppo 25681991Sheppo ldcp->next_vidx = 0; 25692793Slm66018 ldcp->tstate = TS_IN_RESET; 25701991Sheppo ldcp->hstate = 0; 25711991Sheppo ldcp->last_msg_snt = LDC_INIT_SEQID; 25721991Sheppo ldcp->last_ack_rcd = 0; 25731991Sheppo ldcp->last_msg_rcd = 0; 25745944Sha137994 ldcp->rx_ack_head = ACKPEEK_HEAD_INVALID; 25751991Sheppo 25761991Sheppo ldcp->stream_bufferp = NULL; 25771991Sheppo ldcp->exp_dring_list = NULL; 25781991Sheppo ldcp->imp_dring_list = NULL; 25791991Sheppo ldcp->mhdl_list = NULL; 25801991Sheppo 25812793Slm66018 ldcp->tx_intr_state = LDC_INTR_NONE; 25822793Slm66018 ldcp->rx_intr_state = LDC_INTR_NONE; 25832793Slm66018 25841991Sheppo /* Initialize payload size depending on whether channel is reliable */ 25851991Sheppo switch (ldcp->mode) { 25861991Sheppo case LDC_MODE_RAW: 25871991Sheppo ldcp->pkt_payload = LDC_PAYLOAD_SIZE_RAW; 25881991Sheppo ldcp->read_p = i_ldc_read_raw; 25891991Sheppo ldcp->write_p = i_ldc_write_raw; 25901991Sheppo break; 25911991Sheppo case LDC_MODE_UNRELIABLE: 25921991Sheppo ldcp->pkt_payload = LDC_PAYLOAD_SIZE_UNRELIABLE; 25931991Sheppo ldcp->read_p = i_ldc_read_packet; 25941991Sheppo ldcp->write_p = i_ldc_write_packet; 25951991Sheppo break; 25961991Sheppo case LDC_MODE_RELIABLE: 25971991Sheppo ldcp->pkt_payload = LDC_PAYLOAD_SIZE_RELIABLE; 25981991Sheppo 25991991Sheppo ldcp->stream_remains = 0; 26001991Sheppo ldcp->stream_offset = 0; 26011991Sheppo ldcp->stream_bufferp = kmem_alloc(ldcp->mtu, KM_SLEEP); 26021991Sheppo ldcp->read_p = i_ldc_read_stream; 26031991Sheppo ldcp->write_p = i_ldc_write_stream; 26041991Sheppo break; 26051991Sheppo default: 26061991Sheppo exit_val = EINVAL; 26071991Sheppo goto cleanup_on_exit; 26081991Sheppo } 26091991Sheppo 26102410Slm66018 /* 26112410Slm66018 * qlen is (mtu * ldc_mtu_msgs) / pkt_payload. If this 26122410Slm66018 * value is smaller than default length of ldc_queue_entries, 26134690Snarayan * qlen is set to ldc_queue_entries. Ensure that computed 26144690Snarayan * length is a power-of-two value. 26152410Slm66018 */ 26162410Slm66018 qlen = (ldcp->mtu * ldc_mtu_msgs) / ldcp->pkt_payload; 26174690Snarayan if (!ISP2(qlen)) { 26184690Snarayan uint64_t tmp = 1; 26194690Snarayan while (qlen) { 26204690Snarayan qlen >>= 1; tmp <<= 1; 26214690Snarayan } 26224690Snarayan qlen = tmp; 26234690Snarayan } 26244690Snarayan 26252410Slm66018 ldcp->rx_q_entries = 26264690Snarayan (qlen < ldc_queue_entries) ? ldc_queue_entries : qlen; 26272410Slm66018 ldcp->tx_q_entries = ldcp->rx_q_entries; 26282410Slm66018 26294690Snarayan D1(ldcp->id, "ldc_init: queue length = 0x%llx\n", ldcp->rx_q_entries); 26302410Slm66018 26311991Sheppo /* Create a transmit queue */ 26321991Sheppo ldcp->tx_q_va = (uint64_t) 26334690Snarayan contig_mem_alloc(ldcp->tx_q_entries << LDC_PACKET_SHIFT); 26341991Sheppo if (ldcp->tx_q_va == NULL) { 26351991Sheppo cmn_err(CE_WARN, 26361991Sheppo "ldc_init: (0x%lx) TX queue allocation failed\n", 26371991Sheppo ldcp->id); 26381991Sheppo exit_val = ENOMEM; 26391991Sheppo goto cleanup_on_exit; 26401991Sheppo } 26411991Sheppo ldcp->tx_q_ra = va_to_pa((caddr_t)ldcp->tx_q_va); 26421991Sheppo 26431991Sheppo D2(ldcp->id, "ldc_init: txq_va=0x%llx, txq_ra=0x%llx, entries=0x%llx\n", 26441991Sheppo ldcp->tx_q_va, ldcp->tx_q_ra, ldcp->tx_q_entries); 26451991Sheppo 26461991Sheppo ldcp->tstate |= TS_TXQ_RDY; 26471991Sheppo 26481991Sheppo /* Create a receive queue */ 26491991Sheppo ldcp->rx_q_va = (uint64_t) 26504690Snarayan contig_mem_alloc(ldcp->rx_q_entries << LDC_PACKET_SHIFT); 26511991Sheppo if (ldcp->rx_q_va == NULL) { 26521991Sheppo cmn_err(CE_WARN, 26531991Sheppo "ldc_init: (0x%lx) RX queue allocation failed\n", 26541991Sheppo ldcp->id); 26551991Sheppo exit_val = ENOMEM; 26561991Sheppo goto cleanup_on_exit; 26571991Sheppo } 26581991Sheppo ldcp->rx_q_ra = va_to_pa((caddr_t)ldcp->rx_q_va); 26591991Sheppo 26601991Sheppo D2(ldcp->id, "ldc_init: rxq_va=0x%llx, rxq_ra=0x%llx, entries=0x%llx\n", 26611991Sheppo ldcp->rx_q_va, ldcp->rx_q_ra, ldcp->rx_q_entries); 26621991Sheppo 26631991Sheppo ldcp->tstate |= TS_RXQ_RDY; 26641991Sheppo 26655944Sha137994 /* Setup a separate read data queue */ 2666*6408Sha137994 if (ldcp->mode == LDC_MODE_RELIABLE) { 26675944Sha137994 ldcp->readq_get_state = i_ldc_dq_rx_get_state; 26685944Sha137994 ldcp->readq_set_head = i_ldc_set_rxdq_head; 26695944Sha137994 26705944Sha137994 /* Make sure the data queue multiplier is a power of 2 */ 26715944Sha137994 if (!ISP2(ldc_rxdq_multiplier)) { 26725944Sha137994 D1(ldcp->id, "ldc_init: (0x%llx) ldc_rxdq_multiplier " 26735944Sha137994 "not a power of 2, resetting", ldcp->id); 26745944Sha137994 ldc_rxdq_multiplier = LDC_RXDQ_MULTIPLIER; 26755944Sha137994 } 26765944Sha137994 26775944Sha137994 ldcp->rx_dq_entries = ldc_rxdq_multiplier * ldcp->rx_q_entries; 26785944Sha137994 ldcp->rx_dq_va = (uint64_t) 26795944Sha137994 kmem_alloc(ldcp->rx_dq_entries << LDC_PACKET_SHIFT, 26805944Sha137994 KM_SLEEP); 26815944Sha137994 if (ldcp->rx_dq_va == NULL) { 26825944Sha137994 cmn_err(CE_WARN, 26835944Sha137994 "ldc_init: (0x%lx) RX data queue " 26845944Sha137994 "allocation failed\n", ldcp->id); 26855944Sha137994 exit_val = ENOMEM; 26865944Sha137994 goto cleanup_on_exit; 26875944Sha137994 } 26885944Sha137994 26895944Sha137994 ldcp->rx_dq_head = ldcp->rx_dq_tail = 0; 26905944Sha137994 26915944Sha137994 D2(ldcp->id, "ldc_init: rx_dq_va=0x%llx, " 26925944Sha137994 "rx_dq_entries=0x%llx\n", ldcp->rx_dq_va, 26935944Sha137994 ldcp->rx_dq_entries); 26945944Sha137994 } else { 26955944Sha137994 ldcp->readq_get_state = i_ldc_hvq_rx_get_state; 26965944Sha137994 ldcp->readq_set_head = i_ldc_set_rx_head; 26975944Sha137994 } 26985944Sha137994 26991991Sheppo /* Init descriptor ring and memory handle list lock */ 27001991Sheppo mutex_init(&ldcp->exp_dlist_lock, NULL, MUTEX_DRIVER, NULL); 27011991Sheppo mutex_init(&ldcp->imp_dlist_lock, NULL, MUTEX_DRIVER, NULL); 27021991Sheppo mutex_init(&ldcp->mlist_lock, NULL, MUTEX_DRIVER, NULL); 27031991Sheppo 27041991Sheppo /* mark status as INITialized */ 27051991Sheppo ldcp->status = LDC_INIT; 27061991Sheppo 27071991Sheppo /* Add to channel list */ 27081991Sheppo mutex_enter(&ldcssp->lock); 27091991Sheppo ldcp->next = ldcssp->chan_list; 27101991Sheppo ldcssp->chan_list = ldcp; 27111991Sheppo ldcssp->channel_count++; 27121991Sheppo mutex_exit(&ldcssp->lock); 27131991Sheppo 27141991Sheppo /* set the handle */ 27151991Sheppo *handle = (ldc_handle_t)ldcp; 27161991Sheppo 27171991Sheppo D1(ldcp->id, "ldc_init: (0x%llx) channel initialized\n", ldcp->id); 27181991Sheppo 27191991Sheppo return (0); 27201991Sheppo 27211991Sheppo cleanup_on_exit: 27221991Sheppo 2723*6408Sha137994 if (ldcp->mode == LDC_MODE_RELIABLE && ldcp->stream_bufferp) 27241991Sheppo kmem_free(ldcp->stream_bufferp, ldcp->mtu); 27251991Sheppo 27261991Sheppo if (ldcp->tstate & TS_TXQ_RDY) 27271991Sheppo contig_mem_free((caddr_t)ldcp->tx_q_va, 27281991Sheppo (ldcp->tx_q_entries << LDC_PACKET_SHIFT)); 27291991Sheppo 27301991Sheppo if (ldcp->tstate & TS_RXQ_RDY) 27311991Sheppo contig_mem_free((caddr_t)ldcp->rx_q_va, 27321991Sheppo (ldcp->rx_q_entries << LDC_PACKET_SHIFT)); 27331991Sheppo 27342336Snarayan mutex_destroy(&ldcp->tx_lock); 27351991Sheppo mutex_destroy(&ldcp->lock); 27361991Sheppo 27371991Sheppo if (ldcp) 27381991Sheppo kmem_free(ldcp, sizeof (ldc_chan_t)); 27391991Sheppo 27401991Sheppo return (exit_val); 27411991Sheppo } 27421991Sheppo 27431991Sheppo /* 27441991Sheppo * Finalizes the LDC connection. It will return EBUSY if the 27451991Sheppo * channel is open. A ldc_close() has to be done prior to 27461991Sheppo * a ldc_fini operation. It frees TX/RX queues, associated 27471991Sheppo * with the channel 27481991Sheppo */ 27491991Sheppo int 27501991Sheppo ldc_fini(ldc_handle_t handle) 27511991Sheppo { 27521991Sheppo ldc_chan_t *ldcp; 27531991Sheppo ldc_chan_t *tmp_ldcp; 27541991Sheppo uint64_t id; 27551991Sheppo 27561991Sheppo if (handle == NULL) { 27571991Sheppo DWARN(DBG_ALL_LDCS, "ldc_fini: invalid channel handle\n"); 27581991Sheppo return (EINVAL); 27591991Sheppo } 27601991Sheppo ldcp = (ldc_chan_t *)handle; 27611991Sheppo id = ldcp->id; 27621991Sheppo 27631991Sheppo mutex_enter(&ldcp->lock); 27641991Sheppo 27652793Slm66018 if ((ldcp->tstate & ~TS_IN_RESET) > TS_INIT) { 27661991Sheppo DWARN(ldcp->id, "ldc_fini: (0x%llx) channel is open\n", 27671991Sheppo ldcp->id); 27681991Sheppo mutex_exit(&ldcp->lock); 27691991Sheppo return (EBUSY); 27701991Sheppo } 27711991Sheppo 27721991Sheppo /* Remove from the channel list */ 27731991Sheppo mutex_enter(&ldcssp->lock); 27741991Sheppo tmp_ldcp = ldcssp->chan_list; 27751991Sheppo if (tmp_ldcp == ldcp) { 27761991Sheppo ldcssp->chan_list = ldcp->next; 27771991Sheppo ldcp->next = NULL; 27781991Sheppo } else { 27791991Sheppo while (tmp_ldcp != NULL) { 27801991Sheppo if (tmp_ldcp->next == ldcp) { 27811991Sheppo tmp_ldcp->next = ldcp->next; 27821991Sheppo ldcp->next = NULL; 27831991Sheppo break; 27841991Sheppo } 27851991Sheppo tmp_ldcp = tmp_ldcp->next; 27861991Sheppo } 27871991Sheppo if (tmp_ldcp == NULL) { 27881991Sheppo DWARN(DBG_ALL_LDCS, "ldc_fini: invalid channel hdl\n"); 27891991Sheppo mutex_exit(&ldcssp->lock); 27901991Sheppo mutex_exit(&ldcp->lock); 27911991Sheppo return (EINVAL); 27921991Sheppo } 27931991Sheppo } 27941991Sheppo 27951991Sheppo ldcssp->channel_count--; 27961991Sheppo 27971991Sheppo mutex_exit(&ldcssp->lock); 27981991Sheppo 27991991Sheppo /* Free the map table for this channel */ 28001991Sheppo if (ldcp->mtbl) { 28011991Sheppo (void) hv_ldc_set_map_table(ldcp->id, NULL, NULL); 28022793Slm66018 if (ldcp->mtbl->contigmem) 28032793Slm66018 contig_mem_free(ldcp->mtbl->table, ldcp->mtbl->size); 28042793Slm66018 else 28052793Slm66018 kmem_free(ldcp->mtbl->table, ldcp->mtbl->size); 28061991Sheppo mutex_destroy(&ldcp->mtbl->lock); 28071991Sheppo kmem_free(ldcp->mtbl, sizeof (ldc_mtbl_t)); 28081991Sheppo } 28091991Sheppo 28101991Sheppo /* Destroy descriptor ring and memory handle list lock */ 28111991Sheppo mutex_destroy(&ldcp->exp_dlist_lock); 28121991Sheppo mutex_destroy(&ldcp->imp_dlist_lock); 28131991Sheppo mutex_destroy(&ldcp->mlist_lock); 28141991Sheppo 2815*6408Sha137994 /* Free the stream buffer for RELIABLE_MODE */ 2816*6408Sha137994 if (ldcp->mode == LDC_MODE_RELIABLE && ldcp->stream_bufferp) 28171991Sheppo kmem_free(ldcp->stream_bufferp, ldcp->mtu); 28181991Sheppo 28191991Sheppo /* Free the RX queue */ 28201991Sheppo contig_mem_free((caddr_t)ldcp->rx_q_va, 28211991Sheppo (ldcp->rx_q_entries << LDC_PACKET_SHIFT)); 28221991Sheppo ldcp->tstate &= ~TS_RXQ_RDY; 28231991Sheppo 28245944Sha137994 /* Free the RX data queue */ 2825*6408Sha137994 if (ldcp->mode == LDC_MODE_RELIABLE) { 28265944Sha137994 kmem_free((caddr_t)ldcp->rx_dq_va, 28275944Sha137994 (ldcp->rx_dq_entries << LDC_PACKET_SHIFT)); 28285944Sha137994 } 28295944Sha137994 28301991Sheppo /* Free the TX queue */ 28311991Sheppo contig_mem_free((caddr_t)ldcp->tx_q_va, 28321991Sheppo (ldcp->tx_q_entries << LDC_PACKET_SHIFT)); 28331991Sheppo ldcp->tstate &= ~TS_TXQ_RDY; 28341991Sheppo 28351991Sheppo mutex_exit(&ldcp->lock); 28361991Sheppo 28371991Sheppo /* Destroy mutex */ 28382336Snarayan mutex_destroy(&ldcp->tx_lock); 28391991Sheppo mutex_destroy(&ldcp->lock); 28401991Sheppo 28411991Sheppo /* free channel structure */ 28421991Sheppo kmem_free(ldcp, sizeof (ldc_chan_t)); 28431991Sheppo 28441991Sheppo D1(id, "ldc_fini: (0x%llx) channel finalized\n", id); 28451991Sheppo 28461991Sheppo return (0); 28471991Sheppo } 28481991Sheppo 28491991Sheppo /* 28501991Sheppo * Open the LDC channel for use. It registers the TX/RX queues 28511991Sheppo * with the Hypervisor. It also specifies the interrupt number 28521991Sheppo * and target CPU for this channel 28531991Sheppo */ 28541991Sheppo int 28551991Sheppo ldc_open(ldc_handle_t handle) 28561991Sheppo { 28571991Sheppo ldc_chan_t *ldcp; 28581991Sheppo int rv; 28591991Sheppo 28601991Sheppo if (handle == NULL) { 28611991Sheppo DWARN(DBG_ALL_LDCS, "ldc_open: invalid channel handle\n"); 28621991Sheppo return (EINVAL); 28631991Sheppo } 28641991Sheppo 28651991Sheppo ldcp = (ldc_chan_t *)handle; 28661991Sheppo 28671991Sheppo mutex_enter(&ldcp->lock); 28681991Sheppo 28691991Sheppo if (ldcp->tstate < TS_INIT) { 28701991Sheppo DWARN(ldcp->id, 28711991Sheppo "ldc_open: (0x%llx) channel not initialized\n", ldcp->id); 28721991Sheppo mutex_exit(&ldcp->lock); 28731991Sheppo return (EFAULT); 28741991Sheppo } 28752793Slm66018 if ((ldcp->tstate & ~TS_IN_RESET) >= TS_OPEN) { 28761991Sheppo DWARN(ldcp->id, 28771991Sheppo "ldc_open: (0x%llx) channel is already open\n", ldcp->id); 28781991Sheppo mutex_exit(&ldcp->lock); 28791991Sheppo return (EFAULT); 28801991Sheppo } 28811991Sheppo 28821991Sheppo /* 28831991Sheppo * Unregister/Register the tx queue with the hypervisor 28841991Sheppo */ 28851991Sheppo rv = hv_ldc_tx_qconf(ldcp->id, NULL, NULL); 28861991Sheppo if (rv) { 28871991Sheppo cmn_err(CE_WARN, 28881991Sheppo "ldc_open: (0x%lx) channel tx queue unconf failed\n", 28891991Sheppo ldcp->id); 28901991Sheppo mutex_exit(&ldcp->lock); 28911991Sheppo return (EIO); 28921991Sheppo } 28931991Sheppo 28941991Sheppo rv = hv_ldc_tx_qconf(ldcp->id, ldcp->tx_q_ra, ldcp->tx_q_entries); 28951991Sheppo if (rv) { 28961991Sheppo cmn_err(CE_WARN, 28971991Sheppo "ldc_open: (0x%lx) channel tx queue conf failed\n", 28981991Sheppo ldcp->id); 28991991Sheppo mutex_exit(&ldcp->lock); 29001991Sheppo return (EIO); 29011991Sheppo } 29021991Sheppo 29031991Sheppo D2(ldcp->id, "ldc_open: (0x%llx) registered tx queue with LDC\n", 29041991Sheppo ldcp->id); 29051991Sheppo 29061991Sheppo /* 29071991Sheppo * Unregister/Register the rx queue with the hypervisor 29081991Sheppo */ 29091991Sheppo rv = hv_ldc_rx_qconf(ldcp->id, NULL, NULL); 29101991Sheppo if (rv) { 29111991Sheppo cmn_err(CE_WARN, 29121991Sheppo "ldc_open: (0x%lx) channel rx queue unconf failed\n", 29131991Sheppo ldcp->id); 29141991Sheppo mutex_exit(&ldcp->lock); 29151991Sheppo return (EIO); 29161991Sheppo } 29171991Sheppo 29181991Sheppo rv = hv_ldc_rx_qconf(ldcp->id, ldcp->rx_q_ra, ldcp->rx_q_entries); 29191991Sheppo if (rv) { 29201991Sheppo cmn_err(CE_WARN, 29211991Sheppo "ldc_open: (0x%lx) channel rx queue conf failed\n", 29221991Sheppo ldcp->id); 29231991Sheppo mutex_exit(&ldcp->lock); 29241991Sheppo return (EIO); 29251991Sheppo } 29261991Sheppo 29271991Sheppo D2(ldcp->id, "ldc_open: (0x%llx) registered rx queue with LDC\n", 29281991Sheppo ldcp->id); 29291991Sheppo 29301991Sheppo ldcp->tstate |= TS_QCONF_RDY; 29311991Sheppo 29321991Sheppo /* Register the channel with the channel nexus */ 29331991Sheppo rv = i_ldc_register_channel(ldcp); 29341991Sheppo if (rv && rv != EAGAIN) { 29351991Sheppo cmn_err(CE_WARN, 29361991Sheppo "ldc_open: (0x%lx) channel register failed\n", ldcp->id); 29371991Sheppo (void) hv_ldc_tx_qconf(ldcp->id, NULL, NULL); 29381991Sheppo (void) hv_ldc_rx_qconf(ldcp->id, NULL, NULL); 29391991Sheppo mutex_exit(&ldcp->lock); 29401991Sheppo return (EIO); 29411991Sheppo } 29421991Sheppo 29431991Sheppo /* mark channel in OPEN state */ 29441991Sheppo ldcp->status = LDC_OPEN; 29451991Sheppo 29461991Sheppo /* Read channel state */ 29471991Sheppo rv = hv_ldc_tx_get_state(ldcp->id, 29481991Sheppo &ldcp->tx_head, &ldcp->tx_tail, &ldcp->link_state); 29491991Sheppo if (rv) { 29501991Sheppo cmn_err(CE_WARN, 29511991Sheppo "ldc_open: (0x%lx) cannot read channel state\n", 29521991Sheppo ldcp->id); 29531991Sheppo (void) i_ldc_unregister_channel(ldcp); 29541991Sheppo (void) hv_ldc_tx_qconf(ldcp->id, NULL, NULL); 29551991Sheppo (void) hv_ldc_rx_qconf(ldcp->id, NULL, NULL); 29561991Sheppo mutex_exit(&ldcp->lock); 29571991Sheppo return (EIO); 29581991Sheppo } 29591991Sheppo 29601991Sheppo /* 2961*6408Sha137994 * set the ACKd head to current head location for reliable 29621991Sheppo */ 29631991Sheppo ldcp->tx_ackd_head = ldcp->tx_head; 29641991Sheppo 29651991Sheppo /* mark channel ready if HV report link is UP (peer alloc'd Rx queue) */ 29661991Sheppo if (ldcp->link_state == LDC_CHANNEL_UP || 29671991Sheppo ldcp->link_state == LDC_CHANNEL_RESET) { 29681991Sheppo ldcp->tstate |= TS_LINK_READY; 29691991Sheppo ldcp->status = LDC_READY; 29701991Sheppo } 29711991Sheppo 29721991Sheppo /* 29731991Sheppo * if channel is being opened in RAW mode - no handshake is needed 29741991Sheppo * switch the channel READY and UP state 29751991Sheppo */ 29761991Sheppo if (ldcp->mode == LDC_MODE_RAW) { 29771991Sheppo ldcp->tstate = TS_UP; /* set bits associated with LDC UP */ 29781991Sheppo ldcp->status = LDC_UP; 29791991Sheppo } 29801991Sheppo 29811991Sheppo mutex_exit(&ldcp->lock); 29821991Sheppo 29831991Sheppo /* 29841991Sheppo * Increment number of open channels 29851991Sheppo */ 29861991Sheppo mutex_enter(&ldcssp->lock); 29871991Sheppo ldcssp->channels_open++; 29881991Sheppo mutex_exit(&ldcssp->lock); 29891991Sheppo 29903010Slm66018 D1(ldcp->id, 29912793Slm66018 "ldc_open: (0x%llx) channel (0x%p) open for use " 29922793Slm66018 "(tstate=0x%x, status=0x%x)\n", 29932793Slm66018 ldcp->id, ldcp, ldcp->tstate, ldcp->status); 29941991Sheppo 29951991Sheppo return (0); 29961991Sheppo } 29971991Sheppo 29981991Sheppo /* 29991991Sheppo * Close the LDC connection. It will return EBUSY if there 30001991Sheppo * are memory segments or descriptor rings either bound to or 30011991Sheppo * mapped over the channel 30021991Sheppo */ 30031991Sheppo int 30041991Sheppo ldc_close(ldc_handle_t handle) 30051991Sheppo { 30061991Sheppo ldc_chan_t *ldcp; 30072336Snarayan int rv = 0, retries = 0; 30081991Sheppo boolean_t chk_done = B_FALSE; 30091991Sheppo 30101991Sheppo if (handle == NULL) { 30111991Sheppo DWARN(DBG_ALL_LDCS, "ldc_close: invalid channel handle\n"); 30121991Sheppo return (EINVAL); 30131991Sheppo } 30141991Sheppo ldcp = (ldc_chan_t *)handle; 30151991Sheppo 30161991Sheppo mutex_enter(&ldcp->lock); 30171991Sheppo 30181991Sheppo /* return error if channel is not open */ 30192793Slm66018 if ((ldcp->tstate & ~TS_IN_RESET) < TS_OPEN) { 30201991Sheppo DWARN(ldcp->id, 30211991Sheppo "ldc_close: (0x%llx) channel is not open\n", ldcp->id); 30221991Sheppo mutex_exit(&ldcp->lock); 30231991Sheppo return (EFAULT); 30241991Sheppo } 30251991Sheppo 30261991Sheppo /* if any memory handles, drings, are bound or mapped cannot close */ 30271991Sheppo if (ldcp->mhdl_list != NULL) { 30281991Sheppo DWARN(ldcp->id, 30291991Sheppo "ldc_close: (0x%llx) channel has bound memory handles\n", 30301991Sheppo ldcp->id); 30311991Sheppo mutex_exit(&ldcp->lock); 30321991Sheppo return (EBUSY); 30331991Sheppo } 30341991Sheppo if (ldcp->exp_dring_list != NULL) { 30351991Sheppo DWARN(ldcp->id, 30361991Sheppo "ldc_close: (0x%llx) channel has bound descriptor rings\n", 30371991Sheppo ldcp->id); 30381991Sheppo mutex_exit(&ldcp->lock); 30391991Sheppo return (EBUSY); 30401991Sheppo } 30411991Sheppo if (ldcp->imp_dring_list != NULL) { 30421991Sheppo DWARN(ldcp->id, 30431991Sheppo "ldc_close: (0x%llx) channel has mapped descriptor rings\n", 30441991Sheppo ldcp->id); 30451991Sheppo mutex_exit(&ldcp->lock); 30461991Sheppo return (EBUSY); 30471991Sheppo } 30481991Sheppo 30493151Ssg70180 if (ldcp->cb_inprogress) { 30503151Ssg70180 DWARN(ldcp->id, "ldc_close: (0x%llx) callback active\n", 30513151Ssg70180 ldcp->id); 30523151Ssg70180 mutex_exit(&ldcp->lock); 30533151Ssg70180 return (EWOULDBLOCK); 30543151Ssg70180 } 30553151Ssg70180 30562336Snarayan /* Obtain Tx lock */ 30572336Snarayan mutex_enter(&ldcp->tx_lock); 30582336Snarayan 30591991Sheppo /* 30601991Sheppo * Wait for pending transmits to complete i.e Tx queue to drain 30611991Sheppo * if there are pending pkts - wait 1 ms and retry again 30621991Sheppo */ 30631991Sheppo for (;;) { 30641991Sheppo 30651991Sheppo rv = hv_ldc_tx_get_state(ldcp->id, 30661991Sheppo &ldcp->tx_head, &ldcp->tx_tail, &ldcp->link_state); 30671991Sheppo if (rv) { 30681991Sheppo cmn_err(CE_WARN, 30691991Sheppo "ldc_close: (0x%lx) cannot read qptrs\n", ldcp->id); 30702336Snarayan mutex_exit(&ldcp->tx_lock); 30711991Sheppo mutex_exit(&ldcp->lock); 30721991Sheppo return (EIO); 30731991Sheppo } 30741991Sheppo 30751991Sheppo if (ldcp->tx_head == ldcp->tx_tail || 30761991Sheppo ldcp->link_state != LDC_CHANNEL_UP) { 30771991Sheppo break; 30781991Sheppo } 30791991Sheppo 30801991Sheppo if (chk_done) { 30811991Sheppo DWARN(ldcp->id, 30821991Sheppo "ldc_close: (0x%llx) Tx queue drain timeout\n", 30831991Sheppo ldcp->id); 30841991Sheppo break; 30851991Sheppo } 30861991Sheppo 30871991Sheppo /* wait for one ms and try again */ 30881991Sheppo delay(drv_usectohz(1000)); 30891991Sheppo chk_done = B_TRUE; 30901991Sheppo } 30911991Sheppo 30921991Sheppo /* 30932841Snarayan * Drain the Tx and Rx queues as we are closing the 30942841Snarayan * channel. We dont care about any pending packets. 30952841Snarayan * We have to also drain the queue prior to clearing 30962841Snarayan * pending interrupts, otherwise the HV will trigger 30972841Snarayan * an interrupt the moment the interrupt state is 30982841Snarayan * cleared. 30992793Slm66018 */ 31002793Slm66018 (void) i_ldc_txq_reconf(ldcp); 31012841Snarayan (void) i_ldc_rxq_drain(ldcp); 31022793Slm66018 31032793Slm66018 /* 31041991Sheppo * Unregister the channel with the nexus 31051991Sheppo */ 31062336Snarayan while ((rv = i_ldc_unregister_channel(ldcp)) != 0) { 31072336Snarayan 31082336Snarayan mutex_exit(&ldcp->tx_lock); 31091991Sheppo mutex_exit(&ldcp->lock); 31102336Snarayan 31112336Snarayan /* if any error other than EAGAIN return back */ 31122841Snarayan if (rv != EAGAIN || retries >= ldc_max_retries) { 31132336Snarayan cmn_err(CE_WARN, 31142336Snarayan "ldc_close: (0x%lx) unregister failed, %d\n", 31152336Snarayan ldcp->id, rv); 31162336Snarayan return (rv); 31172336Snarayan } 31182336Snarayan 31192336Snarayan /* 31202336Snarayan * As there could be pending interrupts we need 31212336Snarayan * to wait and try again 31222336Snarayan */ 31233151Ssg70180 drv_usecwait(ldc_close_delay); 31242336Snarayan mutex_enter(&ldcp->lock); 31252336Snarayan mutex_enter(&ldcp->tx_lock); 31262336Snarayan retries++; 31271991Sheppo } 31281991Sheppo 31291991Sheppo /* 31301991Sheppo * Unregister queues 31311991Sheppo */ 31321991Sheppo rv = hv_ldc_tx_qconf(ldcp->id, NULL, NULL); 31331991Sheppo if (rv) { 31341991Sheppo cmn_err(CE_WARN, 31351991Sheppo "ldc_close: (0x%lx) channel TX queue unconf failed\n", 31361991Sheppo ldcp->id); 31372336Snarayan mutex_exit(&ldcp->tx_lock); 31381991Sheppo mutex_exit(&ldcp->lock); 31391991Sheppo return (EIO); 31401991Sheppo } 31411991Sheppo rv = hv_ldc_rx_qconf(ldcp->id, NULL, NULL); 31421991Sheppo if (rv) { 31431991Sheppo cmn_err(CE_WARN, 31441991Sheppo "ldc_close: (0x%lx) channel RX queue unconf failed\n", 31451991Sheppo ldcp->id); 31462336Snarayan mutex_exit(&ldcp->tx_lock); 31471991Sheppo mutex_exit(&ldcp->lock); 31481991Sheppo return (EIO); 31491991Sheppo } 31501991Sheppo 31511991Sheppo ldcp->tstate &= ~TS_QCONF_RDY; 31521991Sheppo 31531991Sheppo /* Reset channel state information */ 31541991Sheppo i_ldc_reset_state(ldcp); 31551991Sheppo 31561991Sheppo /* Mark channel as down and in initialized state */ 31571991Sheppo ldcp->tx_ackd_head = 0; 31581991Sheppo ldcp->tx_head = 0; 31592793Slm66018 ldcp->tstate = TS_IN_RESET|TS_INIT; 31601991Sheppo ldcp->status = LDC_INIT; 31611991Sheppo 31622336Snarayan mutex_exit(&ldcp->tx_lock); 31631991Sheppo mutex_exit(&ldcp->lock); 31641991Sheppo 31651991Sheppo /* Decrement number of open channels */ 31661991Sheppo mutex_enter(&ldcssp->lock); 31671991Sheppo ldcssp->channels_open--; 31681991Sheppo mutex_exit(&ldcssp->lock); 31691991Sheppo 31701991Sheppo D1(ldcp->id, "ldc_close: (0x%llx) channel closed\n", ldcp->id); 31711991Sheppo 31721991Sheppo return (0); 31731991Sheppo } 31741991Sheppo 31751991Sheppo /* 31761991Sheppo * Register channel callback 31771991Sheppo */ 31781991Sheppo int 31791991Sheppo ldc_reg_callback(ldc_handle_t handle, 31801991Sheppo uint_t(*cb)(uint64_t event, caddr_t arg), caddr_t arg) 31811991Sheppo { 31821991Sheppo ldc_chan_t *ldcp; 31831991Sheppo 31841991Sheppo if (handle == NULL) { 31851991Sheppo DWARN(DBG_ALL_LDCS, 31861991Sheppo "ldc_reg_callback: invalid channel handle\n"); 31871991Sheppo return (EINVAL); 31881991Sheppo } 31891991Sheppo if (((uint64_t)cb) < KERNELBASE) { 31901991Sheppo DWARN(DBG_ALL_LDCS, "ldc_reg_callback: invalid callback\n"); 31911991Sheppo return (EINVAL); 31921991Sheppo } 31931991Sheppo ldcp = (ldc_chan_t *)handle; 31941991Sheppo 31951991Sheppo mutex_enter(&ldcp->lock); 31961991Sheppo 31971991Sheppo if (ldcp->cb) { 31981991Sheppo DWARN(ldcp->id, "ldc_reg_callback: (0x%llx) callback exists\n", 31991991Sheppo ldcp->id); 32001991Sheppo mutex_exit(&ldcp->lock); 32011991Sheppo return (EIO); 32021991Sheppo } 32031991Sheppo if (ldcp->cb_inprogress) { 32041991Sheppo DWARN(ldcp->id, "ldc_reg_callback: (0x%llx) callback active\n", 32051991Sheppo ldcp->id); 32061991Sheppo mutex_exit(&ldcp->lock); 32071991Sheppo return (EWOULDBLOCK); 32081991Sheppo } 32091991Sheppo 32101991Sheppo ldcp->cb = cb; 32111991Sheppo ldcp->cb_arg = arg; 32121991Sheppo ldcp->cb_enabled = B_TRUE; 32131991Sheppo 32141991Sheppo D1(ldcp->id, 32151991Sheppo "ldc_reg_callback: (0x%llx) registered callback for channel\n", 32161991Sheppo ldcp->id); 32171991Sheppo 32181991Sheppo mutex_exit(&ldcp->lock); 32191991Sheppo 32201991Sheppo return (0); 32211991Sheppo } 32221991Sheppo 32231991Sheppo /* 32241991Sheppo * Unregister channel callback 32251991Sheppo */ 32261991Sheppo int 32271991Sheppo ldc_unreg_callback(ldc_handle_t handle) 32281991Sheppo { 32291991Sheppo ldc_chan_t *ldcp; 32301991Sheppo 32311991Sheppo if (handle == NULL) { 32321991Sheppo DWARN(DBG_ALL_LDCS, 32331991Sheppo "ldc_unreg_callback: invalid channel handle\n"); 32341991Sheppo return (EINVAL); 32351991Sheppo } 32361991Sheppo ldcp = (ldc_chan_t *)handle; 32371991Sheppo 32381991Sheppo mutex_enter(&ldcp->lock); 32391991Sheppo 32401991Sheppo if (ldcp->cb == NULL) { 32411991Sheppo DWARN(ldcp->id, 32421991Sheppo "ldc_unreg_callback: (0x%llx) no callback exists\n", 32431991Sheppo ldcp->id); 32441991Sheppo mutex_exit(&ldcp->lock); 32451991Sheppo return (EIO); 32461991Sheppo } 32471991Sheppo if (ldcp->cb_inprogress) { 32481991Sheppo DWARN(ldcp->id, 32491991Sheppo "ldc_unreg_callback: (0x%llx) callback active\n", 32501991Sheppo ldcp->id); 32511991Sheppo mutex_exit(&ldcp->lock); 32521991Sheppo return (EWOULDBLOCK); 32531991Sheppo } 32541991Sheppo 32551991Sheppo ldcp->cb = NULL; 32561991Sheppo ldcp->cb_arg = NULL; 32571991Sheppo ldcp->cb_enabled = B_FALSE; 32581991Sheppo 32591991Sheppo D1(ldcp->id, 32601991Sheppo "ldc_unreg_callback: (0x%llx) unregistered callback for channel\n", 32611991Sheppo ldcp->id); 32621991Sheppo 32631991Sheppo mutex_exit(&ldcp->lock); 32641991Sheppo 32651991Sheppo return (0); 32661991Sheppo } 32671991Sheppo 32681991Sheppo 32691991Sheppo /* 32701991Sheppo * Bring a channel up by initiating a handshake with the peer 32711991Sheppo * This call is asynchronous. It will complete at a later point 32721991Sheppo * in time when the peer responds back with an RTR. 32731991Sheppo */ 32741991Sheppo int 32751991Sheppo ldc_up(ldc_handle_t handle) 32761991Sheppo { 32771991Sheppo int rv; 32781991Sheppo ldc_chan_t *ldcp; 32791991Sheppo ldc_msg_t *ldcmsg; 32803808Ssb155480 uint64_t tx_tail, tstate, link_state; 32811991Sheppo 32821991Sheppo if (handle == NULL) { 32831991Sheppo DWARN(DBG_ALL_LDCS, "ldc_up: invalid channel handle\n"); 32841991Sheppo return (EINVAL); 32851991Sheppo } 32861991Sheppo ldcp = (ldc_chan_t *)handle; 32871991Sheppo 32881991Sheppo mutex_enter(&ldcp->lock); 32891991Sheppo 32902793Slm66018 D1(ldcp->id, "ldc_up: (0x%llx) doing channel UP\n", ldcp->id); 32912793Slm66018 32922793Slm66018 /* clear the reset state */ 32932793Slm66018 tstate = ldcp->tstate; 32942793Slm66018 ldcp->tstate &= ~TS_IN_RESET; 32952793Slm66018 32961991Sheppo if (ldcp->tstate == TS_UP) { 32972793Slm66018 DWARN(ldcp->id, 32981991Sheppo "ldc_up: (0x%llx) channel is already in UP state\n", 32991991Sheppo ldcp->id); 33002793Slm66018 33012793Slm66018 /* mark channel as up */ 33022793Slm66018 ldcp->status = LDC_UP; 33032793Slm66018 33042793Slm66018 /* 33052793Slm66018 * if channel was in reset state and there was 33062793Slm66018 * pending data clear interrupt state. this will 33072793Slm66018 * trigger an interrupt, causing the RX handler to 33082793Slm66018 * to invoke the client's callback 33092793Slm66018 */ 33102793Slm66018 if ((tstate & TS_IN_RESET) && 33112793Slm66018 ldcp->rx_intr_state == LDC_INTR_PEND) { 33123010Slm66018 D1(ldcp->id, 33132793Slm66018 "ldc_up: (0x%llx) channel has pending data, " 33142793Slm66018 "clearing interrupt\n", ldcp->id); 33152793Slm66018 i_ldc_clear_intr(ldcp, CNEX_RX_INTR); 33162793Slm66018 } 33172793Slm66018 33181991Sheppo mutex_exit(&ldcp->lock); 33191991Sheppo return (0); 33201991Sheppo } 33211991Sheppo 33221991Sheppo /* if the channel is in RAW mode - mark it as UP, if READY */ 33231991Sheppo if (ldcp->mode == LDC_MODE_RAW && ldcp->tstate >= TS_READY) { 33241991Sheppo ldcp->tstate = TS_UP; 33251991Sheppo mutex_exit(&ldcp->lock); 33261991Sheppo return (0); 33271991Sheppo } 33281991Sheppo 33291991Sheppo /* Don't start another handshake if there is one in progress */ 33301991Sheppo if (ldcp->hstate) { 33312793Slm66018 D1(ldcp->id, 33321991Sheppo "ldc_up: (0x%llx) channel handshake in progress\n", 33331991Sheppo ldcp->id); 33341991Sheppo mutex_exit(&ldcp->lock); 33351991Sheppo return (0); 33361991Sheppo } 33371991Sheppo 33382336Snarayan mutex_enter(&ldcp->tx_lock); 33392336Snarayan 33403808Ssb155480 /* save current link state */ 33413808Ssb155480 link_state = ldcp->link_state; 33423808Ssb155480 33431991Sheppo /* get the current tail for the LDC msg */ 33441991Sheppo rv = i_ldc_get_tx_tail(ldcp, &tx_tail); 33451991Sheppo if (rv) { 33463010Slm66018 D1(ldcp->id, "ldc_up: (0x%llx) cannot initiate handshake\n", 33471991Sheppo ldcp->id); 33482336Snarayan mutex_exit(&ldcp->tx_lock); 33491991Sheppo mutex_exit(&ldcp->lock); 33501991Sheppo return (ECONNREFUSED); 33511991Sheppo } 33521991Sheppo 33533808Ssb155480 /* 33543808Ssb155480 * If i_ldc_get_tx_tail() changed link_state to either RESET or UP, 33553808Ssb155480 * from a previous state of DOWN, then mark the channel as 33563808Ssb155480 * being ready for handshake. 33573808Ssb155480 */ 33583808Ssb155480 if ((link_state == LDC_CHANNEL_DOWN) && 33593808Ssb155480 (link_state != ldcp->link_state)) { 33603808Ssb155480 33613808Ssb155480 ASSERT((ldcp->link_state == LDC_CHANNEL_RESET) || 33623808Ssb155480 (ldcp->link_state == LDC_CHANNEL_UP)); 33633808Ssb155480 33643808Ssb155480 if (ldcp->mode == LDC_MODE_RAW) { 33653808Ssb155480 ldcp->status = LDC_UP; 33663808Ssb155480 ldcp->tstate = TS_UP; 33673808Ssb155480 mutex_exit(&ldcp->tx_lock); 33683808Ssb155480 mutex_exit(&ldcp->lock); 33693808Ssb155480 return (0); 33703808Ssb155480 } else { 33713808Ssb155480 ldcp->status = LDC_READY; 33723808Ssb155480 ldcp->tstate |= TS_LINK_READY; 33733808Ssb155480 } 33743808Ssb155480 33753808Ssb155480 } 33763808Ssb155480 33771991Sheppo ldcmsg = (ldc_msg_t *)(ldcp->tx_q_va + tx_tail); 33781991Sheppo ZERO_PKT(ldcmsg); 33791991Sheppo 33801991Sheppo ldcmsg->type = LDC_CTRL; 33811991Sheppo ldcmsg->stype = LDC_INFO; 33821991Sheppo ldcmsg->ctrl = LDC_VER; 33831991Sheppo ldcp->next_vidx = 0; 33841991Sheppo bcopy(&ldc_versions[0], ldcmsg->udata, sizeof (ldc_versions[0])); 33851991Sheppo 33861991Sheppo DUMP_LDC_PKT(ldcp, "ldc_up snd ver", (uint64_t)ldcmsg); 33871991Sheppo 33881991Sheppo /* initiate the send by calling into HV and set the new tail */ 33891991Sheppo tx_tail = (tx_tail + LDC_PACKET_SIZE) % 33904690Snarayan (ldcp->tx_q_entries << LDC_PACKET_SHIFT); 33911991Sheppo 33921991Sheppo rv = i_ldc_set_tx_tail(ldcp, tx_tail); 33931991Sheppo if (rv) { 33941991Sheppo DWARN(ldcp->id, 33951991Sheppo "ldc_up: (0x%llx) cannot initiate handshake rv=%d\n", 33961991Sheppo ldcp->id, rv); 33972336Snarayan mutex_exit(&ldcp->tx_lock); 33981991Sheppo mutex_exit(&ldcp->lock); 33991991Sheppo return (rv); 34001991Sheppo } 34011991Sheppo 34022032Slm66018 ldcp->hstate |= TS_SENT_VER; 34031991Sheppo ldcp->tx_tail = tx_tail; 34041991Sheppo D1(ldcp->id, "ldc_up: (0x%llx) channel up initiated\n", ldcp->id); 34051991Sheppo 34062336Snarayan mutex_exit(&ldcp->tx_lock); 34071991Sheppo mutex_exit(&ldcp->lock); 34081991Sheppo 34091991Sheppo return (rv); 34101991Sheppo } 34111991Sheppo 34121991Sheppo 34131991Sheppo /* 34142410Slm66018 * Bring a channel down by resetting its state and queues 34151991Sheppo */ 34161991Sheppo int 34172410Slm66018 ldc_down(ldc_handle_t handle) 34181991Sheppo { 34191991Sheppo ldc_chan_t *ldcp; 34201991Sheppo 34211991Sheppo if (handle == NULL) { 34222410Slm66018 DWARN(DBG_ALL_LDCS, "ldc_down: invalid channel handle\n"); 34231991Sheppo return (EINVAL); 34241991Sheppo } 34251991Sheppo ldcp = (ldc_chan_t *)handle; 34261991Sheppo mutex_enter(&ldcp->lock); 34272336Snarayan mutex_enter(&ldcp->tx_lock); 34282793Slm66018 i_ldc_reset(ldcp, B_TRUE); 34292336Snarayan mutex_exit(&ldcp->tx_lock); 34301991Sheppo mutex_exit(&ldcp->lock); 34311991Sheppo 34321991Sheppo return (0); 34331991Sheppo } 34341991Sheppo 34351991Sheppo /* 34361991Sheppo * Get the current channel status 34371991Sheppo */ 34381991Sheppo int 34391991Sheppo ldc_status(ldc_handle_t handle, ldc_status_t *status) 34401991Sheppo { 34411991Sheppo ldc_chan_t *ldcp; 34421991Sheppo 34431991Sheppo if (handle == NULL || status == NULL) { 34441991Sheppo DWARN(DBG_ALL_LDCS, "ldc_status: invalid argument\n"); 34451991Sheppo return (EINVAL); 34461991Sheppo } 34471991Sheppo ldcp = (ldc_chan_t *)handle; 34481991Sheppo 34491991Sheppo *status = ((ldc_chan_t *)handle)->status; 34501991Sheppo 34513010Slm66018 D1(ldcp->id, 34521991Sheppo "ldc_status: (0x%llx) returned status %d\n", ldcp->id, *status); 34531991Sheppo return (0); 34541991Sheppo } 34551991Sheppo 34561991Sheppo 34571991Sheppo /* 34581991Sheppo * Set the channel's callback mode - enable/disable callbacks 34591991Sheppo */ 34601991Sheppo int 34611991Sheppo ldc_set_cb_mode(ldc_handle_t handle, ldc_cb_mode_t cmode) 34621991Sheppo { 34631991Sheppo ldc_chan_t *ldcp; 34641991Sheppo 34651991Sheppo if (handle == NULL) { 34661991Sheppo DWARN(DBG_ALL_LDCS, 34671991Sheppo "ldc_set_intr_mode: invalid channel handle\n"); 34681991Sheppo return (EINVAL); 34691991Sheppo } 34701991Sheppo ldcp = (ldc_chan_t *)handle; 34711991Sheppo 34721991Sheppo /* 34731991Sheppo * Record no callbacks should be invoked 34741991Sheppo */ 34751991Sheppo mutex_enter(&ldcp->lock); 34761991Sheppo 34771991Sheppo switch (cmode) { 34781991Sheppo case LDC_CB_DISABLE: 34791991Sheppo if (!ldcp->cb_enabled) { 34801991Sheppo DWARN(ldcp->id, 34811991Sheppo "ldc_set_cb_mode: (0x%llx) callbacks disabled\n", 34821991Sheppo ldcp->id); 34831991Sheppo break; 34841991Sheppo } 34851991Sheppo ldcp->cb_enabled = B_FALSE; 34861991Sheppo 34871991Sheppo D1(ldcp->id, "ldc_set_cb_mode: (0x%llx) disabled callbacks\n", 34881991Sheppo ldcp->id); 34891991Sheppo break; 34901991Sheppo 34911991Sheppo case LDC_CB_ENABLE: 34921991Sheppo if (ldcp->cb_enabled) { 34931991Sheppo DWARN(ldcp->id, 34941991Sheppo "ldc_set_cb_mode: (0x%llx) callbacks enabled\n", 34951991Sheppo ldcp->id); 34961991Sheppo break; 34971991Sheppo } 34981991Sheppo ldcp->cb_enabled = B_TRUE; 34991991Sheppo 35001991Sheppo D1(ldcp->id, "ldc_set_cb_mode: (0x%llx) enabled callbacks\n", 35011991Sheppo ldcp->id); 35021991Sheppo break; 35031991Sheppo } 35041991Sheppo 35051991Sheppo mutex_exit(&ldcp->lock); 35061991Sheppo 35071991Sheppo return (0); 35081991Sheppo } 35091991Sheppo 35101991Sheppo /* 35111991Sheppo * Check to see if there are packets on the incoming queue 35122410Slm66018 * Will return hasdata = B_FALSE if there are no packets 35131991Sheppo */ 35141991Sheppo int 35152410Slm66018 ldc_chkq(ldc_handle_t handle, boolean_t *hasdata) 35161991Sheppo { 35171991Sheppo int rv; 35181991Sheppo uint64_t rx_head, rx_tail; 35191991Sheppo ldc_chan_t *ldcp; 35201991Sheppo 35211991Sheppo if (handle == NULL) { 35221991Sheppo DWARN(DBG_ALL_LDCS, "ldc_chkq: invalid channel handle\n"); 35231991Sheppo return (EINVAL); 35241991Sheppo } 35251991Sheppo ldcp = (ldc_chan_t *)handle; 35261991Sheppo 35272410Slm66018 *hasdata = B_FALSE; 35281991Sheppo 35291991Sheppo mutex_enter(&ldcp->lock); 35301991Sheppo 35311991Sheppo if (ldcp->tstate != TS_UP) { 35321991Sheppo D1(ldcp->id, 35331991Sheppo "ldc_chkq: (0x%llx) channel is not up\n", ldcp->id); 35341991Sheppo mutex_exit(&ldcp->lock); 35351991Sheppo return (ECONNRESET); 35361991Sheppo } 35371991Sheppo 35381991Sheppo /* Read packet(s) from the queue */ 35391991Sheppo rv = hv_ldc_rx_get_state(ldcp->id, &rx_head, &rx_tail, 35401991Sheppo &ldcp->link_state); 35411991Sheppo if (rv != 0) { 35421991Sheppo cmn_err(CE_WARN, 35431991Sheppo "ldc_chkq: (0x%lx) unable to read queue ptrs", ldcp->id); 35441991Sheppo mutex_exit(&ldcp->lock); 35451991Sheppo return (EIO); 35461991Sheppo } 35475944Sha137994 35481991Sheppo /* reset the channel state if the channel went down */ 35491991Sheppo if (ldcp->link_state == LDC_CHANNEL_DOWN || 35501991Sheppo ldcp->link_state == LDC_CHANNEL_RESET) { 35512336Snarayan mutex_enter(&ldcp->tx_lock); 35522793Slm66018 i_ldc_reset(ldcp, B_FALSE); 35532336Snarayan mutex_exit(&ldcp->tx_lock); 35541991Sheppo mutex_exit(&ldcp->lock); 35551991Sheppo return (ECONNRESET); 35561991Sheppo } 35571991Sheppo 35585944Sha137994 switch (ldcp->mode) { 35595944Sha137994 case LDC_MODE_RAW: 35605944Sha137994 /* 35615944Sha137994 * In raw mode, there are no ctrl packets, so checking 35625944Sha137994 * if the queue is non-empty is sufficient. 35635944Sha137994 */ 35645944Sha137994 *hasdata = (rx_head != rx_tail); 35655944Sha137994 break; 35665944Sha137994 35675944Sha137994 case LDC_MODE_UNRELIABLE: 35685944Sha137994 /* 35695944Sha137994 * In unreliable mode, if the queue is non-empty, we need 35705944Sha137994 * to check if it actually contains unread data packets. 35715944Sha137994 * The queue may just contain ctrl packets. 35725944Sha137994 */ 35735944Sha137994 if (rx_head != rx_tail) 35745944Sha137994 *hasdata = (i_ldc_chkq(ldcp) == 0); 35755944Sha137994 break; 35765944Sha137994 3577*6408Sha137994 case LDC_MODE_RELIABLE: 35785944Sha137994 /* 3579*6408Sha137994 * In reliable mode, first check for 'stream_remains' > 0. 35805944Sha137994 * Otherwise, if the data queue head and tail pointers 35815944Sha137994 * differ, there must be data to read. 35825944Sha137994 */ 35835944Sha137994 if (ldcp->stream_remains > 0) 35845944Sha137994 *hasdata = B_TRUE; 35855944Sha137994 else 35865944Sha137994 *hasdata = (ldcp->rx_dq_head != ldcp->rx_dq_tail); 35875944Sha137994 break; 35885944Sha137994 35895944Sha137994 default: 35905944Sha137994 cmn_err(CE_WARN, "ldc_chkq: (0x%lx) unexpected channel mode " 35915944Sha137994 "(0x%x)", ldcp->id, ldcp->mode); 35925944Sha137994 mutex_exit(&ldcp->lock); 35935944Sha137994 return (EIO); 35941991Sheppo } 35951991Sheppo 35961991Sheppo mutex_exit(&ldcp->lock); 35971991Sheppo 35981991Sheppo return (0); 35991991Sheppo } 36001991Sheppo 36011991Sheppo 36021991Sheppo /* 36031991Sheppo * Read 'size' amount of bytes or less. If incoming buffer 36041991Sheppo * is more than 'size', ENOBUFS is returned. 36051991Sheppo * 36061991Sheppo * On return, size contains the number of bytes read. 36071991Sheppo */ 36081991Sheppo int 36091991Sheppo ldc_read(ldc_handle_t handle, caddr_t bufp, size_t *sizep) 36101991Sheppo { 36111991Sheppo ldc_chan_t *ldcp; 36121991Sheppo uint64_t rx_head = 0, rx_tail = 0; 36131991Sheppo int rv = 0, exit_val; 36141991Sheppo 36151991Sheppo if (handle == NULL) { 36161991Sheppo DWARN(DBG_ALL_LDCS, "ldc_read: invalid channel handle\n"); 36171991Sheppo return (EINVAL); 36181991Sheppo } 36191991Sheppo 36201991Sheppo ldcp = (ldc_chan_t *)handle; 36211991Sheppo 36221991Sheppo /* channel lock */ 36231991Sheppo mutex_enter(&ldcp->lock); 36241991Sheppo 36251991Sheppo if (ldcp->tstate != TS_UP) { 36261991Sheppo DWARN(ldcp->id, 36271991Sheppo "ldc_read: (0x%llx) channel is not in UP state\n", 36281991Sheppo ldcp->id); 36291991Sheppo exit_val = ECONNRESET; 3630*6408Sha137994 } else if (ldcp->mode == LDC_MODE_RELIABLE) { 36315944Sha137994 TRACE_RXDQ_LENGTH(ldcp); 36325944Sha137994 exit_val = ldcp->read_p(ldcp, bufp, sizep); 36335944Sha137994 mutex_exit(&ldcp->lock); 36345944Sha137994 return (exit_val); 36351991Sheppo } else { 36361991Sheppo exit_val = ldcp->read_p(ldcp, bufp, sizep); 36371991Sheppo } 36381991Sheppo 36391991Sheppo /* 36401991Sheppo * if queue has been drained - clear interrupt 36411991Sheppo */ 36421991Sheppo rv = hv_ldc_rx_get_state(ldcp->id, &rx_head, &rx_tail, 36431991Sheppo &ldcp->link_state); 36443010Slm66018 if (rv != 0) { 36453010Slm66018 cmn_err(CE_WARN, "ldc_read: (0x%lx) unable to read queue ptrs", 36463010Slm66018 ldcp->id); 36473010Slm66018 mutex_enter(&ldcp->tx_lock); 36483010Slm66018 i_ldc_reset(ldcp, B_TRUE); 36493010Slm66018 mutex_exit(&ldcp->tx_lock); 36503653Snarayan mutex_exit(&ldcp->lock); 36513010Slm66018 return (ECONNRESET); 36523010Slm66018 } 36532793Slm66018 36542793Slm66018 if (exit_val == 0) { 36552793Slm66018 if (ldcp->link_state == LDC_CHANNEL_DOWN || 36562793Slm66018 ldcp->link_state == LDC_CHANNEL_RESET) { 36572793Slm66018 mutex_enter(&ldcp->tx_lock); 36582793Slm66018 i_ldc_reset(ldcp, B_FALSE); 36592793Slm66018 exit_val = ECONNRESET; 36602793Slm66018 mutex_exit(&ldcp->tx_lock); 36612793Slm66018 } 36622793Slm66018 if ((rv == 0) && 36632793Slm66018 (ldcp->rx_intr_state == LDC_INTR_PEND) && 36642793Slm66018 (rx_head == rx_tail)) { 36652793Slm66018 i_ldc_clear_intr(ldcp, CNEX_RX_INTR); 36662793Slm66018 } 36671991Sheppo } 36681991Sheppo 36691991Sheppo mutex_exit(&ldcp->lock); 36701991Sheppo return (exit_val); 36711991Sheppo } 36721991Sheppo 36731991Sheppo /* 36741991Sheppo * Basic raw mondo read - 36751991Sheppo * no interpretation of mondo contents at all. 36761991Sheppo * 36771991Sheppo * Enter and exit with ldcp->lock held by caller 36781991Sheppo */ 36791991Sheppo static int 36801991Sheppo i_ldc_read_raw(ldc_chan_t *ldcp, caddr_t target_bufp, size_t *sizep) 36811991Sheppo { 36821991Sheppo uint64_t q_size_mask; 36831991Sheppo ldc_msg_t *msgp; 36841991Sheppo uint8_t *msgbufp; 36851991Sheppo int rv = 0, space; 36861991Sheppo uint64_t rx_head, rx_tail; 36871991Sheppo 36881991Sheppo space = *sizep; 36891991Sheppo 36901991Sheppo if (space < LDC_PAYLOAD_SIZE_RAW) 36911991Sheppo return (ENOBUFS); 36921991Sheppo 36931991Sheppo ASSERT(mutex_owned(&ldcp->lock)); 36941991Sheppo 36951991Sheppo /* compute mask for increment */ 36961991Sheppo q_size_mask = (ldcp->rx_q_entries-1)<<LDC_PACKET_SHIFT; 36971991Sheppo 36981991Sheppo /* 36991991Sheppo * Read packet(s) from the queue 37001991Sheppo */ 37011991Sheppo rv = hv_ldc_rx_get_state(ldcp->id, &rx_head, &rx_tail, 37021991Sheppo &ldcp->link_state); 37031991Sheppo if (rv != 0) { 37041991Sheppo cmn_err(CE_WARN, 37051991Sheppo "ldc_read_raw: (0x%lx) unable to read queue ptrs", 37061991Sheppo ldcp->id); 37071991Sheppo return (EIO); 37081991Sheppo } 37091991Sheppo D1(ldcp->id, "ldc_read_raw: (0x%llx) rxh=0x%llx," 37104690Snarayan " rxt=0x%llx, st=0x%llx\n", 37114690Snarayan ldcp->id, rx_head, rx_tail, ldcp->link_state); 37121991Sheppo 37131991Sheppo /* reset the channel state if the channel went down */ 37142793Slm66018 if (ldcp->link_state == LDC_CHANNEL_DOWN || 37152793Slm66018 ldcp->link_state == LDC_CHANNEL_RESET) { 37162336Snarayan mutex_enter(&ldcp->tx_lock); 37172793Slm66018 i_ldc_reset(ldcp, B_FALSE); 37182336Snarayan mutex_exit(&ldcp->tx_lock); 37191991Sheppo return (ECONNRESET); 37201991Sheppo } 37211991Sheppo 37221991Sheppo /* 37231991Sheppo * Check for empty queue 37241991Sheppo */ 37251991Sheppo if (rx_head == rx_tail) { 37261991Sheppo *sizep = 0; 37271991Sheppo return (0); 37281991Sheppo } 37291991Sheppo 37301991Sheppo /* get the message */ 37311991Sheppo msgp = (ldc_msg_t *)(ldcp->rx_q_va + rx_head); 37321991Sheppo 37331991Sheppo /* if channel is in RAW mode, copy data and return */ 37341991Sheppo msgbufp = (uint8_t *)&(msgp->raw[0]); 37351991Sheppo 37361991Sheppo bcopy(msgbufp, target_bufp, LDC_PAYLOAD_SIZE_RAW); 37371991Sheppo 37381991Sheppo DUMP_PAYLOAD(ldcp->id, msgbufp); 37391991Sheppo 37401991Sheppo *sizep = LDC_PAYLOAD_SIZE_RAW; 37411991Sheppo 37421991Sheppo rx_head = (rx_head + LDC_PACKET_SIZE) & q_size_mask; 37432032Slm66018 rv = i_ldc_set_rx_head(ldcp, rx_head); 37441991Sheppo 37451991Sheppo return (rv); 37461991Sheppo } 37471991Sheppo 37481991Sheppo /* 37491991Sheppo * Process LDC mondos to build larger packets 37501991Sheppo * with either un-reliable or reliable delivery. 37511991Sheppo * 37521991Sheppo * Enter and exit with ldcp->lock held by caller 37531991Sheppo */ 37541991Sheppo static int 37551991Sheppo i_ldc_read_packet(ldc_chan_t *ldcp, caddr_t target_bufp, size_t *sizep) 37561991Sheppo { 37571991Sheppo int rv = 0; 37581991Sheppo uint64_t rx_head = 0, rx_tail = 0; 37591991Sheppo uint64_t curr_head = 0; 37601991Sheppo ldc_msg_t *msg; 37611991Sheppo caddr_t target; 37621991Sheppo size_t len = 0, bytes_read = 0; 37632032Slm66018 int retries = 0; 37645944Sha137994 uint64_t q_va, q_size_mask; 37652336Snarayan uint64_t first_fragment = 0; 37661991Sheppo 37671991Sheppo target = target_bufp; 37681991Sheppo 37691991Sheppo ASSERT(mutex_owned(&ldcp->lock)); 37701991Sheppo 37712793Slm66018 /* check if the buffer and size are valid */ 37722793Slm66018 if (target_bufp == NULL || *sizep == 0) { 37732793Slm66018 DWARN(ldcp->id, "ldc_read: (0x%llx) invalid buffer/size\n", 37742793Slm66018 ldcp->id); 37752793Slm66018 return (EINVAL); 37762793Slm66018 } 37772793Slm66018 37785944Sha137994 /* Set q_va and compute increment mask for the appropriate queue */ 3779*6408Sha137994 if (ldcp->mode == LDC_MODE_RELIABLE) { 37805944Sha137994 q_va = ldcp->rx_dq_va; 37815944Sha137994 q_size_mask = (ldcp->rx_dq_entries-1)<<LDC_PACKET_SHIFT; 37825944Sha137994 } else { 37835944Sha137994 q_va = ldcp->rx_q_va; 37845944Sha137994 q_size_mask = (ldcp->rx_q_entries-1)<<LDC_PACKET_SHIFT; 37855944Sha137994 } 37861991Sheppo 37871991Sheppo /* 37881991Sheppo * Read packet(s) from the queue 37891991Sheppo */ 37905944Sha137994 rv = ldcp->readq_get_state(ldcp, &curr_head, &rx_tail, 37911991Sheppo &ldcp->link_state); 37921991Sheppo if (rv != 0) { 37932793Slm66018 cmn_err(CE_WARN, "ldc_read: (0x%lx) unable to read queue ptrs", 37941991Sheppo ldcp->id); 37952793Slm66018 mutex_enter(&ldcp->tx_lock); 37962793Slm66018 i_ldc_reset(ldcp, B_TRUE); 37972793Slm66018 mutex_exit(&ldcp->tx_lock); 37982793Slm66018 return (ECONNRESET); 37991991Sheppo } 38001991Sheppo D1(ldcp->id, "ldc_read: (0x%llx) chd=0x%llx, tl=0x%llx, st=0x%llx\n", 38011991Sheppo ldcp->id, curr_head, rx_tail, ldcp->link_state); 38021991Sheppo 38031991Sheppo /* reset the channel state if the channel went down */ 38042793Slm66018 if (ldcp->link_state != LDC_CHANNEL_UP) 38052793Slm66018 goto channel_is_reset; 38061991Sheppo 38071991Sheppo for (;;) { 38081991Sheppo 38091991Sheppo if (curr_head == rx_tail) { 38105944Sha137994 /* 38115944Sha137994 * If a data queue is being used, check the Rx HV 38125944Sha137994 * queue. This will copy over any new data packets 38135944Sha137994 * that have arrived. 38145944Sha137994 */ 3815*6408Sha137994 if (ldcp->mode == LDC_MODE_RELIABLE) 38165944Sha137994 (void) i_ldc_chkq(ldcp); 38175944Sha137994 38185944Sha137994 rv = ldcp->readq_get_state(ldcp, 38191991Sheppo &rx_head, &rx_tail, &ldcp->link_state); 38201991Sheppo if (rv != 0) { 38211991Sheppo cmn_err(CE_WARN, 38221991Sheppo "ldc_read: (0x%lx) cannot read queue ptrs", 38231991Sheppo ldcp->id); 38242336Snarayan mutex_enter(&ldcp->tx_lock); 38252793Slm66018 i_ldc_reset(ldcp, B_TRUE); 38262336Snarayan mutex_exit(&ldcp->tx_lock); 38271991Sheppo return (ECONNRESET); 38281991Sheppo } 38295944Sha137994 38302793Slm66018 if (ldcp->link_state != LDC_CHANNEL_UP) 38312793Slm66018 goto channel_is_reset; 38322793Slm66018 38332793Slm66018 if (curr_head == rx_tail) { 38342793Slm66018 38352793Slm66018 /* If in the middle of a fragmented xfer */ 38362793Slm66018 if (first_fragment != 0) { 38372793Slm66018 38382793Slm66018 /* wait for ldc_delay usecs */ 38392793Slm66018 drv_usecwait(ldc_delay); 38402793Slm66018 38412793Slm66018 if (++retries < ldc_max_retries) 38422793Slm66018 continue; 38432793Slm66018 38442793Slm66018 *sizep = 0; 3845*6408Sha137994 if (ldcp->mode != LDC_MODE_RELIABLE) 38465944Sha137994 ldcp->last_msg_rcd = 38475944Sha137994 first_fragment - 1; 38482793Slm66018 DWARN(DBG_ALL_LDCS, "ldc_read: " 38494690Snarayan "(0x%llx) read timeout", ldcp->id); 38502793Slm66018 return (EAGAIN); 38512793Slm66018 } 38522032Slm66018 *sizep = 0; 38532793Slm66018 break; 38541991Sheppo } 38551991Sheppo } 38562032Slm66018 retries = 0; 38571991Sheppo 38581991Sheppo D2(ldcp->id, 38591991Sheppo "ldc_read: (0x%llx) chd=0x%llx, rxhd=0x%llx, rxtl=0x%llx\n", 38601991Sheppo ldcp->id, curr_head, rx_head, rx_tail); 38611991Sheppo 38621991Sheppo /* get the message */ 38635944Sha137994 msg = (ldc_msg_t *)(q_va + curr_head); 38641991Sheppo 38651991Sheppo DUMP_LDC_PKT(ldcp, "ldc_read received pkt", 38661991Sheppo ldcp->rx_q_va + curr_head); 38671991Sheppo 38681991Sheppo /* Check the message ID for the message received */ 3869*6408Sha137994 if (ldcp->mode != LDC_MODE_RELIABLE) { 38705944Sha137994 if ((rv = i_ldc_check_seqid(ldcp, msg)) != 0) { 38715944Sha137994 38725944Sha137994 DWARN(ldcp->id, "ldc_read: (0x%llx) seqid " 38735944Sha137994 "error, q_ptrs=0x%lx,0x%lx", 38745944Sha137994 ldcp->id, rx_head, rx_tail); 38755944Sha137994 38765944Sha137994 /* throw away data */ 38775944Sha137994 bytes_read = 0; 38785944Sha137994 38795944Sha137994 /* Reset last_msg_rcd to start of message */ 38805944Sha137994 if (first_fragment != 0) { 38815944Sha137994 ldcp->last_msg_rcd = first_fragment - 1; 38825944Sha137994 first_fragment = 0; 38835944Sha137994 } 38845944Sha137994 /* 38855944Sha137994 * Send a NACK -- invalid seqid 38865944Sha137994 * get the current tail for the response 38875944Sha137994 */ 38885944Sha137994 rv = i_ldc_send_pkt(ldcp, msg->type, LDC_NACK, 38895944Sha137994 (msg->ctrl & LDC_CTRL_MASK)); 38905944Sha137994 if (rv) { 38915944Sha137994 cmn_err(CE_NOTE, 38925944Sha137994 "ldc_read: (0x%lx) err sending " 38935944Sha137994 "NACK msg\n", ldcp->id); 38945944Sha137994 38955944Sha137994 /* if cannot send NACK - reset chan */ 38965944Sha137994 mutex_enter(&ldcp->tx_lock); 38975944Sha137994 i_ldc_reset(ldcp, B_FALSE); 38985944Sha137994 mutex_exit(&ldcp->tx_lock); 38995944Sha137994 rv = ECONNRESET; 39005944Sha137994 break; 39015944Sha137994 } 39025944Sha137994 39035944Sha137994 /* purge receive queue */ 39045944Sha137994 rv = i_ldc_set_rx_head(ldcp, rx_tail); 39055944Sha137994 39062336Snarayan break; 39071991Sheppo } 39081991Sheppo 39095944Sha137994 /* 39105944Sha137994 * Process any messages of type CTRL messages 39115944Sha137994 * Future implementations should try to pass these 39125944Sha137994 * to LDC link by resetting the intr state. 39135944Sha137994 * 39145944Sha137994 * NOTE: not done as a switch() as type can be 39155944Sha137994 * both ctrl+data 39165944Sha137994 */ 39175944Sha137994 if (msg->type & LDC_CTRL) { 39185944Sha137994 if (rv = i_ldc_ctrlmsg(ldcp, msg)) { 39195944Sha137994 if (rv == EAGAIN) 39205944Sha137994 continue; 39215944Sha137994 rv = i_ldc_set_rx_head(ldcp, rx_tail); 39225944Sha137994 *sizep = 0; 39235944Sha137994 bytes_read = 0; 39245944Sha137994 break; 39255944Sha137994 } 39261991Sheppo } 39275944Sha137994 39285944Sha137994 /* process data ACKs */ 39295944Sha137994 if ((msg->type & LDC_DATA) && (msg->stype & LDC_ACK)) { 39305944Sha137994 if (rv = i_ldc_process_data_ACK(ldcp, msg)) { 39315944Sha137994 *sizep = 0; 39325944Sha137994 bytes_read = 0; 39335944Sha137994 break; 39345944Sha137994 } 39352336Snarayan } 39365944Sha137994 39375944Sha137994 /* process data NACKs */ 39385944Sha137994 if ((msg->type & LDC_DATA) && (msg->stype & LDC_NACK)) { 39395944Sha137994 DWARN(ldcp->id, 39405944Sha137994 "ldc_read: (0x%llx) received DATA/NACK", 39415944Sha137994 ldcp->id); 39425944Sha137994 mutex_enter(&ldcp->tx_lock); 39435944Sha137994 i_ldc_reset(ldcp, B_TRUE); 39445944Sha137994 mutex_exit(&ldcp->tx_lock); 39455944Sha137994 return (ECONNRESET); 39465944Sha137994 } 39473560Snarayan } 39483560Snarayan 39491991Sheppo /* process data messages */ 39501991Sheppo if ((msg->type & LDC_DATA) && (msg->stype & LDC_INFO)) { 39511991Sheppo 39521991Sheppo uint8_t *msgbuf = (uint8_t *)( 3953*6408Sha137994 (ldcp->mode == LDC_MODE_RELIABLE) ? 39544690Snarayan msg->rdata : msg->udata); 39551991Sheppo 39561991Sheppo D2(ldcp->id, 39571991Sheppo "ldc_read: (0x%llx) received data msg\n", ldcp->id); 39581991Sheppo 39591991Sheppo /* get the packet length */ 39601991Sheppo len = (msg->env & LDC_LEN_MASK); 39611991Sheppo 39621991Sheppo /* 39631991Sheppo * FUTURE OPTIMIZATION: 39641991Sheppo * dont need to set q head for every 39651991Sheppo * packet we read just need to do this when 39661991Sheppo * we are done or need to wait for more 39671991Sheppo * mondos to make a full packet - this is 39681991Sheppo * currently expensive. 39691991Sheppo */ 39701991Sheppo 39712336Snarayan if (first_fragment == 0) { 39721991Sheppo 39731991Sheppo /* 39741991Sheppo * first packets should always have the start 39751991Sheppo * bit set (even for a single packet). If not 39761991Sheppo * throw away the packet 39771991Sheppo */ 39781991Sheppo if (!(msg->env & LDC_FRAG_START)) { 39791991Sheppo 39801991Sheppo DWARN(DBG_ALL_LDCS, 39811991Sheppo "ldc_read: (0x%llx) not start - " 39821991Sheppo "frag=%x\n", ldcp->id, 39831991Sheppo (msg->env) & LDC_FRAG_MASK); 39841991Sheppo 39851991Sheppo /* toss pkt, inc head, cont reading */ 39861991Sheppo bytes_read = 0; 39871991Sheppo target = target_bufp; 39881991Sheppo curr_head = 39894690Snarayan (curr_head + LDC_PACKET_SIZE) 39904690Snarayan & q_size_mask; 39915944Sha137994 if (rv = ldcp->readq_set_head(ldcp, 39924690Snarayan curr_head)) 39931991Sheppo break; 39941991Sheppo 39951991Sheppo continue; 39961991Sheppo } 39971991Sheppo 39982336Snarayan first_fragment = msg->seqid; 39991991Sheppo } else { 40001991Sheppo /* check to see if this is a pkt w/ START bit */ 40011991Sheppo if (msg->env & LDC_FRAG_START) { 40021991Sheppo DWARN(DBG_ALL_LDCS, 40031991Sheppo "ldc_read:(0x%llx) unexpected pkt" 40041991Sheppo " env=0x%x discarding %d bytes," 40051991Sheppo " lastmsg=%d, currentmsg=%d\n", 40061991Sheppo ldcp->id, msg->env&LDC_FRAG_MASK, 40071991Sheppo bytes_read, ldcp->last_msg_rcd, 40081991Sheppo msg->seqid); 40091991Sheppo 40101991Sheppo /* throw data we have read so far */ 40111991Sheppo bytes_read = 0; 40121991Sheppo target = target_bufp; 40132336Snarayan first_fragment = msg->seqid; 40141991Sheppo 40155944Sha137994 if (rv = ldcp->readq_set_head(ldcp, 40164690Snarayan curr_head)) 40171991Sheppo break; 40181991Sheppo } 40191991Sheppo } 40201991Sheppo 40211991Sheppo /* copy (next) pkt into buffer */ 40221991Sheppo if (len <= (*sizep - bytes_read)) { 40231991Sheppo bcopy(msgbuf, target, len); 40241991Sheppo target += len; 40251991Sheppo bytes_read += len; 40261991Sheppo } else { 40271991Sheppo /* 40281991Sheppo * there is not enough space in the buffer to 40291991Sheppo * read this pkt. throw message away & continue 40301991Sheppo * reading data from queue 40311991Sheppo */ 40321991Sheppo DWARN(DBG_ALL_LDCS, 40331991Sheppo "ldc_read: (0x%llx) buffer too small, " 40341991Sheppo "head=0x%lx, expect=%d, got=%d\n", ldcp->id, 40351991Sheppo curr_head, *sizep, bytes_read+len); 40361991Sheppo 40372336Snarayan first_fragment = 0; 40381991Sheppo target = target_bufp; 40391991Sheppo bytes_read = 0; 40401991Sheppo 40411991Sheppo /* throw away everything received so far */ 40425944Sha137994 if (rv = ldcp->readq_set_head(ldcp, curr_head)) 40431991Sheppo break; 40441991Sheppo 40451991Sheppo /* continue reading remaining pkts */ 40461991Sheppo continue; 40471991Sheppo } 40481991Sheppo } 40491991Sheppo 40501991Sheppo /* set the message id */ 4051*6408Sha137994 if (ldcp->mode != LDC_MODE_RELIABLE) 40525944Sha137994 ldcp->last_msg_rcd = msg->seqid; 40531991Sheppo 40541991Sheppo /* move the head one position */ 40551991Sheppo curr_head = (curr_head + LDC_PACKET_SIZE) & q_size_mask; 40561991Sheppo 40571991Sheppo if (msg->env & LDC_FRAG_STOP) { 40581991Sheppo 40591991Sheppo /* 40601991Sheppo * All pkts that are part of this fragmented transfer 40611991Sheppo * have been read or this was a single pkt read 40621991Sheppo * or there was an error 40631991Sheppo */ 40641991Sheppo 40651991Sheppo /* set the queue head */ 40665944Sha137994 if (rv = ldcp->readq_set_head(ldcp, curr_head)) 40671991Sheppo bytes_read = 0; 40681991Sheppo 40691991Sheppo *sizep = bytes_read; 40701991Sheppo 40711991Sheppo break; 40721991Sheppo } 40731991Sheppo 40744890Snarayan /* advance head if it is a CTRL packet or a DATA ACK packet */ 40754890Snarayan if ((msg->type & LDC_CTRL) || 40764890Snarayan ((msg->type & LDC_DATA) && (msg->stype & LDC_ACK))) { 40771991Sheppo 40781991Sheppo /* set the queue head */ 40795944Sha137994 if (rv = ldcp->readq_set_head(ldcp, curr_head)) { 40801991Sheppo bytes_read = 0; 40811991Sheppo break; 40821991Sheppo } 40831991Sheppo 40841991Sheppo D2(ldcp->id, "ldc_read: (0x%llx) set ACK qhead 0x%llx", 40851991Sheppo ldcp->id, curr_head); 40861991Sheppo } 40871991Sheppo 40881991Sheppo } /* for (;;) */ 40891991Sheppo 40901991Sheppo D2(ldcp->id, "ldc_read: (0x%llx) end size=%d", ldcp->id, *sizep); 40911991Sheppo 40921991Sheppo return (rv); 40932793Slm66018 40942793Slm66018 channel_is_reset: 40952793Slm66018 mutex_enter(&ldcp->tx_lock); 40962793Slm66018 i_ldc_reset(ldcp, B_FALSE); 40972793Slm66018 mutex_exit(&ldcp->tx_lock); 40982793Slm66018 return (ECONNRESET); 40991991Sheppo } 41001991Sheppo 41011991Sheppo /* 4102*6408Sha137994 * Fetch and buffer incoming packets so we can hand them back as 41031991Sheppo * a basic byte stream. 41041991Sheppo * 41051991Sheppo * Enter and exit with ldcp->lock held by caller 41061991Sheppo */ 41071991Sheppo static int 41081991Sheppo i_ldc_read_stream(ldc_chan_t *ldcp, caddr_t target_bufp, size_t *sizep) 41091991Sheppo { 41101991Sheppo int rv; 41111991Sheppo size_t size; 41121991Sheppo 41131991Sheppo ASSERT(mutex_owned(&ldcp->lock)); 41141991Sheppo 41151991Sheppo D2(ldcp->id, "i_ldc_read_stream: (0x%llx) buffer size=%d", 41164690Snarayan ldcp->id, *sizep); 41171991Sheppo 41181991Sheppo if (ldcp->stream_remains == 0) { 41191991Sheppo size = ldcp->mtu; 41201991Sheppo rv = i_ldc_read_packet(ldcp, 41214690Snarayan (caddr_t)ldcp->stream_bufferp, &size); 41221991Sheppo D2(ldcp->id, "i_ldc_read_stream: read packet (0x%llx) size=%d", 41234690Snarayan ldcp->id, size); 41241991Sheppo 41251991Sheppo if (rv != 0) 41261991Sheppo return (rv); 41271991Sheppo 41281991Sheppo ldcp->stream_remains = size; 41291991Sheppo ldcp->stream_offset = 0; 41301991Sheppo } 41311991Sheppo 41321991Sheppo size = MIN(ldcp->stream_remains, *sizep); 41331991Sheppo 41341991Sheppo bcopy(ldcp->stream_bufferp + ldcp->stream_offset, target_bufp, size); 41351991Sheppo ldcp->stream_offset += size; 41361991Sheppo ldcp->stream_remains -= size; 41371991Sheppo 41381991Sheppo D2(ldcp->id, "i_ldc_read_stream: (0x%llx) fill from buffer size=%d", 41394690Snarayan ldcp->id, size); 41401991Sheppo 41411991Sheppo *sizep = size; 41421991Sheppo return (0); 41431991Sheppo } 41441991Sheppo 41451991Sheppo /* 41461991Sheppo * Write specified amount of bytes to the channel 41471991Sheppo * in multiple pkts of pkt_payload size. Each 41481991Sheppo * packet is tagged with an unique packet ID in 41492410Slm66018 * the case of a reliable link. 41501991Sheppo * 41511991Sheppo * On return, size contains the number of bytes written. 41521991Sheppo */ 41531991Sheppo int 41541991Sheppo ldc_write(ldc_handle_t handle, caddr_t buf, size_t *sizep) 41551991Sheppo { 41561991Sheppo ldc_chan_t *ldcp; 41571991Sheppo int rv = 0; 41581991Sheppo 41591991Sheppo if (handle == NULL) { 41601991Sheppo DWARN(DBG_ALL_LDCS, "ldc_write: invalid channel handle\n"); 41611991Sheppo return (EINVAL); 41621991Sheppo } 41631991Sheppo ldcp = (ldc_chan_t *)handle; 41641991Sheppo 41652336Snarayan /* check if writes can occur */ 41662336Snarayan if (!mutex_tryenter(&ldcp->tx_lock)) { 41672336Snarayan /* 41682336Snarayan * Could not get the lock - channel could 41692336Snarayan * be in the process of being unconfigured 41702336Snarayan * or reader has encountered an error 41712336Snarayan */ 41722336Snarayan return (EAGAIN); 41732336Snarayan } 41741991Sheppo 41751991Sheppo /* check if non-zero data to write */ 41761991Sheppo if (buf == NULL || sizep == NULL) { 41771991Sheppo DWARN(ldcp->id, "ldc_write: (0x%llx) invalid data write\n", 41781991Sheppo ldcp->id); 41792336Snarayan mutex_exit(&ldcp->tx_lock); 41801991Sheppo return (EINVAL); 41811991Sheppo } 41821991Sheppo 41831991Sheppo if (*sizep == 0) { 41841991Sheppo DWARN(ldcp->id, "ldc_write: (0x%llx) write size of zero\n", 41851991Sheppo ldcp->id); 41862336Snarayan mutex_exit(&ldcp->tx_lock); 41871991Sheppo return (0); 41881991Sheppo } 41891991Sheppo 41901991Sheppo /* Check if channel is UP for data exchange */ 41911991Sheppo if (ldcp->tstate != TS_UP) { 41921991Sheppo DWARN(ldcp->id, 41931991Sheppo "ldc_write: (0x%llx) channel is not in UP state\n", 41941991Sheppo ldcp->id); 41951991Sheppo *sizep = 0; 41961991Sheppo rv = ECONNRESET; 41971991Sheppo } else { 41981991Sheppo rv = ldcp->write_p(ldcp, buf, sizep); 41991991Sheppo } 42001991Sheppo 42012336Snarayan mutex_exit(&ldcp->tx_lock); 42021991Sheppo 42031991Sheppo return (rv); 42041991Sheppo } 42051991Sheppo 42061991Sheppo /* 42071991Sheppo * Write a raw packet to the channel 42081991Sheppo * On return, size contains the number of bytes written. 42091991Sheppo */ 42101991Sheppo static int 42111991Sheppo i_ldc_write_raw(ldc_chan_t *ldcp, caddr_t buf, size_t *sizep) 42121991Sheppo { 42131991Sheppo ldc_msg_t *ldcmsg; 42141991Sheppo uint64_t tx_head, tx_tail, new_tail; 42151991Sheppo int rv = 0; 42161991Sheppo size_t size; 42171991Sheppo 42182336Snarayan ASSERT(MUTEX_HELD(&ldcp->tx_lock)); 42191991Sheppo ASSERT(ldcp->mode == LDC_MODE_RAW); 42201991Sheppo 42211991Sheppo size = *sizep; 42221991Sheppo 42231991Sheppo /* 42241991Sheppo * Check to see if the packet size is less than or 42251991Sheppo * equal to packet size support in raw mode 42261991Sheppo */ 42271991Sheppo if (size > ldcp->pkt_payload) { 42281991Sheppo DWARN(ldcp->id, 42291991Sheppo "ldc_write: (0x%llx) invalid size (0x%llx) for RAW mode\n", 42301991Sheppo ldcp->id, *sizep); 42311991Sheppo *sizep = 0; 42321991Sheppo return (EMSGSIZE); 42331991Sheppo } 42341991Sheppo 42351991Sheppo /* get the qptrs for the tx queue */ 42361991Sheppo rv = hv_ldc_tx_get_state(ldcp->id, 42371991Sheppo &ldcp->tx_head, &ldcp->tx_tail, &ldcp->link_state); 42381991Sheppo if (rv != 0) { 42391991Sheppo cmn_err(CE_WARN, 42401991Sheppo "ldc_write: (0x%lx) cannot read queue ptrs\n", ldcp->id); 42411991Sheppo *sizep = 0; 42421991Sheppo return (EIO); 42431991Sheppo } 42441991Sheppo 42451991Sheppo if (ldcp->link_state == LDC_CHANNEL_DOWN || 42461991Sheppo ldcp->link_state == LDC_CHANNEL_RESET) { 42471991Sheppo DWARN(ldcp->id, 42481991Sheppo "ldc_write: (0x%llx) channel down/reset\n", ldcp->id); 42492336Snarayan 42501991Sheppo *sizep = 0; 42512336Snarayan if (mutex_tryenter(&ldcp->lock)) { 42522793Slm66018 i_ldc_reset(ldcp, B_FALSE); 42532336Snarayan mutex_exit(&ldcp->lock); 42542336Snarayan } else { 42552336Snarayan /* 42562336Snarayan * Release Tx lock, and then reacquire channel 42572336Snarayan * and Tx lock in correct order 42582336Snarayan */ 42592336Snarayan mutex_exit(&ldcp->tx_lock); 42602336Snarayan mutex_enter(&ldcp->lock); 42612336Snarayan mutex_enter(&ldcp->tx_lock); 42622793Slm66018 i_ldc_reset(ldcp, B_FALSE); 42632336Snarayan mutex_exit(&ldcp->lock); 42642336Snarayan } 42651991Sheppo return (ECONNRESET); 42661991Sheppo } 42671991Sheppo 42681991Sheppo tx_tail = ldcp->tx_tail; 42691991Sheppo tx_head = ldcp->tx_head; 42701991Sheppo new_tail = (tx_tail + LDC_PACKET_SIZE) & 42714690Snarayan ((ldcp->tx_q_entries-1) << LDC_PACKET_SHIFT); 42721991Sheppo 42731991Sheppo if (new_tail == tx_head) { 42741991Sheppo DWARN(DBG_ALL_LDCS, 42751991Sheppo "ldc_write: (0x%llx) TX queue is full\n", ldcp->id); 42761991Sheppo *sizep = 0; 42771991Sheppo return (EWOULDBLOCK); 42781991Sheppo } 42791991Sheppo 42801991Sheppo D2(ldcp->id, "ldc_write: (0x%llx) start xfer size=%d", 42811991Sheppo ldcp->id, size); 42821991Sheppo 42831991Sheppo /* Send the data now */ 42841991Sheppo ldcmsg = (ldc_msg_t *)(ldcp->tx_q_va + tx_tail); 42851991Sheppo 42862336Snarayan /* copy the data into pkt */ 42871991Sheppo bcopy((uint8_t *)buf, ldcmsg, size); 42881991Sheppo 42892336Snarayan /* increment tail */ 42901991Sheppo tx_tail = new_tail; 42911991Sheppo 42921991Sheppo /* 42931991Sheppo * All packets have been copied into the TX queue 42941991Sheppo * update the tail ptr in the HV 42951991Sheppo */ 42961991Sheppo rv = i_ldc_set_tx_tail(ldcp, tx_tail); 42971991Sheppo if (rv) { 42981991Sheppo if (rv == EWOULDBLOCK) { 42991991Sheppo DWARN(ldcp->id, "ldc_write: (0x%llx) write timed out\n", 43001991Sheppo ldcp->id); 43011991Sheppo *sizep = 0; 43021991Sheppo return (EWOULDBLOCK); 43031991Sheppo } 43041991Sheppo 43051991Sheppo *sizep = 0; 43062336Snarayan if (mutex_tryenter(&ldcp->lock)) { 43072793Slm66018 i_ldc_reset(ldcp, B_FALSE); 43082336Snarayan mutex_exit(&ldcp->lock); 43092336Snarayan } else { 43102336Snarayan /* 43112336Snarayan * Release Tx lock, and then reacquire channel 43122336Snarayan * and Tx lock in correct order 43132336Snarayan */ 43142336Snarayan mutex_exit(&ldcp->tx_lock); 43152336Snarayan mutex_enter(&ldcp->lock); 43162336Snarayan mutex_enter(&ldcp->tx_lock); 43172793Slm66018 i_ldc_reset(ldcp, B_FALSE); 43182336Snarayan mutex_exit(&ldcp->lock); 43192336Snarayan } 43201991Sheppo return (ECONNRESET); 43211991Sheppo } 43221991Sheppo 43231991Sheppo ldcp->tx_tail = tx_tail; 43241991Sheppo *sizep = size; 43251991Sheppo 43261991Sheppo D2(ldcp->id, "ldc_write: (0x%llx) end xfer size=%d", ldcp->id, size); 43271991Sheppo 43281991Sheppo return (rv); 43291991Sheppo } 43301991Sheppo 43311991Sheppo 43321991Sheppo /* 43331991Sheppo * Write specified amount of bytes to the channel 43341991Sheppo * in multiple pkts of pkt_payload size. Each 43351991Sheppo * packet is tagged with an unique packet ID in 43362410Slm66018 * the case of a reliable link. 43371991Sheppo * 43381991Sheppo * On return, size contains the number of bytes written. 43391991Sheppo * This function needs to ensure that the write size is < MTU size 43401991Sheppo */ 43411991Sheppo static int 43421991Sheppo i_ldc_write_packet(ldc_chan_t *ldcp, caddr_t buf, size_t *size) 43431991Sheppo { 43441991Sheppo ldc_msg_t *ldcmsg; 43451991Sheppo uint64_t tx_head, tx_tail, new_tail, start; 43461991Sheppo uint64_t txq_size_mask, numavail; 43471991Sheppo uint8_t *msgbuf, *source = (uint8_t *)buf; 43481991Sheppo size_t len, bytes_written = 0, remaining; 43491991Sheppo int rv; 43501991Sheppo uint32_t curr_seqid; 43511991Sheppo 43522336Snarayan ASSERT(MUTEX_HELD(&ldcp->tx_lock)); 43531991Sheppo 43541991Sheppo ASSERT(ldcp->mode == LDC_MODE_RELIABLE || 4355*6408Sha137994 ldcp->mode == LDC_MODE_UNRELIABLE); 43561991Sheppo 43571991Sheppo /* compute mask for increment */ 43581991Sheppo txq_size_mask = (ldcp->tx_q_entries - 1) << LDC_PACKET_SHIFT; 43591991Sheppo 43601991Sheppo /* get the qptrs for the tx queue */ 43611991Sheppo rv = hv_ldc_tx_get_state(ldcp->id, 43621991Sheppo &ldcp->tx_head, &ldcp->tx_tail, &ldcp->link_state); 43631991Sheppo if (rv != 0) { 43641991Sheppo cmn_err(CE_WARN, 43651991Sheppo "ldc_write: (0x%lx) cannot read queue ptrs\n", ldcp->id); 43661991Sheppo *size = 0; 43671991Sheppo return (EIO); 43681991Sheppo } 43691991Sheppo 43701991Sheppo if (ldcp->link_state == LDC_CHANNEL_DOWN || 43711991Sheppo ldcp->link_state == LDC_CHANNEL_RESET) { 43721991Sheppo DWARN(ldcp->id, 43731991Sheppo "ldc_write: (0x%llx) channel down/reset\n", ldcp->id); 43741991Sheppo *size = 0; 43752336Snarayan if (mutex_tryenter(&ldcp->lock)) { 43762793Slm66018 i_ldc_reset(ldcp, B_FALSE); 43772336Snarayan mutex_exit(&ldcp->lock); 43782336Snarayan } else { 43792336Snarayan /* 43802336Snarayan * Release Tx lock, and then reacquire channel 43812336Snarayan * and Tx lock in correct order 43822336Snarayan */ 43832336Snarayan mutex_exit(&ldcp->tx_lock); 43842336Snarayan mutex_enter(&ldcp->lock); 43852336Snarayan mutex_enter(&ldcp->tx_lock); 43862793Slm66018 i_ldc_reset(ldcp, B_FALSE); 43872336Snarayan mutex_exit(&ldcp->lock); 43882336Snarayan } 43891991Sheppo return (ECONNRESET); 43901991Sheppo } 43911991Sheppo 43921991Sheppo tx_tail = ldcp->tx_tail; 43931991Sheppo new_tail = (tx_tail + LDC_PACKET_SIZE) % 43944690Snarayan (ldcp->tx_q_entries << LDC_PACKET_SHIFT); 43951991Sheppo 43961991Sheppo /* 43974690Snarayan * Check to see if the queue is full. The check is done using 43984690Snarayan * the appropriate head based on the link mode. 43991991Sheppo */ 44004690Snarayan i_ldc_get_tx_head(ldcp, &tx_head); 44014690Snarayan 44021991Sheppo if (new_tail == tx_head) { 44031991Sheppo DWARN(DBG_ALL_LDCS, 44041991Sheppo "ldc_write: (0x%llx) TX queue is full\n", ldcp->id); 44051991Sheppo *size = 0; 44061991Sheppo return (EWOULDBLOCK); 44071991Sheppo } 44081991Sheppo 44091991Sheppo /* 44101991Sheppo * Make sure that the LDC Tx queue has enough space 44111991Sheppo */ 44121991Sheppo numavail = (tx_head >> LDC_PACKET_SHIFT) - (tx_tail >> LDC_PACKET_SHIFT) 44134690Snarayan + ldcp->tx_q_entries - 1; 44141991Sheppo numavail %= ldcp->tx_q_entries; 44151991Sheppo 44161991Sheppo if (*size > (numavail * ldcp->pkt_payload)) { 44171991Sheppo DWARN(DBG_ALL_LDCS, 44181991Sheppo "ldc_write: (0x%llx) TX queue has no space\n", ldcp->id); 44191991Sheppo return (EWOULDBLOCK); 44201991Sheppo } 44211991Sheppo 44221991Sheppo D2(ldcp->id, "ldc_write: (0x%llx) start xfer size=%d", 44231991Sheppo ldcp->id, *size); 44241991Sheppo 44251991Sheppo /* Send the data now */ 44261991Sheppo bytes_written = 0; 44271991Sheppo curr_seqid = ldcp->last_msg_snt; 44281991Sheppo start = tx_tail; 44291991Sheppo 44301991Sheppo while (*size > bytes_written) { 44311991Sheppo 44321991Sheppo ldcmsg = (ldc_msg_t *)(ldcp->tx_q_va + tx_tail); 44331991Sheppo 4434*6408Sha137994 msgbuf = (uint8_t *)((ldcp->mode == LDC_MODE_RELIABLE) ? 44354690Snarayan ldcmsg->rdata : ldcmsg->udata); 44361991Sheppo 44371991Sheppo ldcmsg->type = LDC_DATA; 44381991Sheppo ldcmsg->stype = LDC_INFO; 44391991Sheppo ldcmsg->ctrl = 0; 44401991Sheppo 44411991Sheppo remaining = *size - bytes_written; 44421991Sheppo len = min(ldcp->pkt_payload, remaining); 44431991Sheppo ldcmsg->env = (uint8_t)len; 44441991Sheppo 44451991Sheppo curr_seqid++; 44461991Sheppo ldcmsg->seqid = curr_seqid; 44471991Sheppo 44481991Sheppo /* copy the data into pkt */ 44491991Sheppo bcopy(source, msgbuf, len); 44501991Sheppo 44511991Sheppo source += len; 44521991Sheppo bytes_written += len; 44531991Sheppo 44541991Sheppo /* increment tail */ 44551991Sheppo tx_tail = (tx_tail + LDC_PACKET_SIZE) & txq_size_mask; 44561991Sheppo 44571991Sheppo ASSERT(tx_tail != tx_head); 44581991Sheppo } 44591991Sheppo 44601991Sheppo /* Set the start and stop bits */ 44611991Sheppo ldcmsg->env |= LDC_FRAG_STOP; 44621991Sheppo ldcmsg = (ldc_msg_t *)(ldcp->tx_q_va + start); 44631991Sheppo ldcmsg->env |= LDC_FRAG_START; 44641991Sheppo 44651991Sheppo /* 44661991Sheppo * All packets have been copied into the TX queue 44671991Sheppo * update the tail ptr in the HV 44681991Sheppo */ 44691991Sheppo rv = i_ldc_set_tx_tail(ldcp, tx_tail); 44701991Sheppo if (rv == 0) { 44711991Sheppo ldcp->tx_tail = tx_tail; 44721991Sheppo ldcp->last_msg_snt = curr_seqid; 44731991Sheppo *size = bytes_written; 44741991Sheppo } else { 44751991Sheppo int rv2; 44761991Sheppo 44771991Sheppo if (rv != EWOULDBLOCK) { 44781991Sheppo *size = 0; 44792336Snarayan if (mutex_tryenter(&ldcp->lock)) { 44802793Slm66018 i_ldc_reset(ldcp, B_FALSE); 44812336Snarayan mutex_exit(&ldcp->lock); 44822336Snarayan } else { 44832336Snarayan /* 44842336Snarayan * Release Tx lock, and then reacquire channel 44852336Snarayan * and Tx lock in correct order 44862336Snarayan */ 44872336Snarayan mutex_exit(&ldcp->tx_lock); 44882336Snarayan mutex_enter(&ldcp->lock); 44892336Snarayan mutex_enter(&ldcp->tx_lock); 44902793Slm66018 i_ldc_reset(ldcp, B_FALSE); 44912336Snarayan mutex_exit(&ldcp->lock); 44922336Snarayan } 44931991Sheppo return (ECONNRESET); 44941991Sheppo } 44951991Sheppo 44963010Slm66018 D1(ldcp->id, "hv_tx_set_tail returns 0x%x (head 0x%x, " 44974690Snarayan "old tail 0x%x, new tail 0x%x, qsize=0x%x)\n", 44984690Snarayan rv, ldcp->tx_head, ldcp->tx_tail, tx_tail, 44994690Snarayan (ldcp->tx_q_entries << LDC_PACKET_SHIFT)); 45001991Sheppo 45011991Sheppo rv2 = hv_ldc_tx_get_state(ldcp->id, 45021991Sheppo &tx_head, &tx_tail, &ldcp->link_state); 45031991Sheppo 45043010Slm66018 D1(ldcp->id, "hv_ldc_tx_get_state returns 0x%x " 45054690Snarayan "(head 0x%x, tail 0x%x state 0x%x)\n", 45064690Snarayan rv2, tx_head, tx_tail, ldcp->link_state); 45071991Sheppo 45081991Sheppo *size = 0; 45091991Sheppo } 45101991Sheppo 45111991Sheppo D2(ldcp->id, "ldc_write: (0x%llx) end xfer size=%d", ldcp->id, *size); 45121991Sheppo 45131991Sheppo return (rv); 45141991Sheppo } 45151991Sheppo 45161991Sheppo /* 45171991Sheppo * Write specified amount of bytes to the channel 45181991Sheppo * in multiple pkts of pkt_payload size. Each 45191991Sheppo * packet is tagged with an unique packet ID in 45202410Slm66018 * the case of a reliable link. 45211991Sheppo * 45221991Sheppo * On return, size contains the number of bytes written. 45231991Sheppo * This function needs to ensure that the write size is < MTU size 45241991Sheppo */ 45251991Sheppo static int 45261991Sheppo i_ldc_write_stream(ldc_chan_t *ldcp, caddr_t buf, size_t *sizep) 45271991Sheppo { 45282336Snarayan ASSERT(MUTEX_HELD(&ldcp->tx_lock)); 4529*6408Sha137994 ASSERT(ldcp->mode == LDC_MODE_RELIABLE); 45301991Sheppo 45311991Sheppo /* Truncate packet to max of MTU size */ 45321991Sheppo if (*sizep > ldcp->mtu) *sizep = ldcp->mtu; 45331991Sheppo return (i_ldc_write_packet(ldcp, buf, sizep)); 45341991Sheppo } 45351991Sheppo 45361991Sheppo 45371991Sheppo /* 45381991Sheppo * Interfaces for channel nexus to register/unregister with LDC module 45391991Sheppo * The nexus will register functions to be used to register individual 45401991Sheppo * channels with the nexus and enable interrupts for the channels 45411991Sheppo */ 45421991Sheppo int 45431991Sheppo ldc_register(ldc_cnex_t *cinfo) 45441991Sheppo { 45451991Sheppo ldc_chan_t *ldcp; 45461991Sheppo 45471991Sheppo if (cinfo == NULL || cinfo->dip == NULL || 45481991Sheppo cinfo->reg_chan == NULL || cinfo->unreg_chan == NULL || 45491991Sheppo cinfo->add_intr == NULL || cinfo->rem_intr == NULL || 45501991Sheppo cinfo->clr_intr == NULL) { 45511991Sheppo 45521991Sheppo DWARN(DBG_ALL_LDCS, "ldc_register: invalid nexus info\n"); 45531991Sheppo return (EINVAL); 45541991Sheppo } 45551991Sheppo 45561991Sheppo mutex_enter(&ldcssp->lock); 45571991Sheppo 45581991Sheppo /* nexus registration */ 45591991Sheppo ldcssp->cinfo.dip = cinfo->dip; 45601991Sheppo ldcssp->cinfo.reg_chan = cinfo->reg_chan; 45611991Sheppo ldcssp->cinfo.unreg_chan = cinfo->unreg_chan; 45621991Sheppo ldcssp->cinfo.add_intr = cinfo->add_intr; 45631991Sheppo ldcssp->cinfo.rem_intr = cinfo->rem_intr; 45641991Sheppo ldcssp->cinfo.clr_intr = cinfo->clr_intr; 45651991Sheppo 45661991Sheppo /* register any channels that might have been previously initialized */ 45671991Sheppo ldcp = ldcssp->chan_list; 45681991Sheppo while (ldcp) { 45691991Sheppo if ((ldcp->tstate & TS_QCONF_RDY) && 45701991Sheppo (ldcp->tstate & TS_CNEX_RDY) == 0) 45711991Sheppo (void) i_ldc_register_channel(ldcp); 45721991Sheppo 45731991Sheppo ldcp = ldcp->next; 45741991Sheppo } 45751991Sheppo 45761991Sheppo mutex_exit(&ldcssp->lock); 45771991Sheppo 45781991Sheppo return (0); 45791991Sheppo } 45801991Sheppo 45811991Sheppo int 45821991Sheppo ldc_unregister(ldc_cnex_t *cinfo) 45831991Sheppo { 45841991Sheppo if (cinfo == NULL || cinfo->dip == NULL) { 45851991Sheppo DWARN(DBG_ALL_LDCS, "ldc_unregister: invalid nexus info\n"); 45861991Sheppo return (EINVAL); 45871991Sheppo } 45881991Sheppo 45891991Sheppo mutex_enter(&ldcssp->lock); 45901991Sheppo 45911991Sheppo if (cinfo->dip != ldcssp->cinfo.dip) { 45921991Sheppo DWARN(DBG_ALL_LDCS, "ldc_unregister: invalid dip\n"); 45931991Sheppo mutex_exit(&ldcssp->lock); 45941991Sheppo return (EINVAL); 45951991Sheppo } 45961991Sheppo 45971991Sheppo /* nexus unregister */ 45981991Sheppo ldcssp->cinfo.dip = NULL; 45991991Sheppo ldcssp->cinfo.reg_chan = NULL; 46001991Sheppo ldcssp->cinfo.unreg_chan = NULL; 46011991Sheppo ldcssp->cinfo.add_intr = NULL; 46021991Sheppo ldcssp->cinfo.rem_intr = NULL; 46031991Sheppo ldcssp->cinfo.clr_intr = NULL; 46041991Sheppo 46051991Sheppo mutex_exit(&ldcssp->lock); 46061991Sheppo 46071991Sheppo return (0); 46081991Sheppo } 4609