c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * CDDL HEADER START
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * The contents of this file are subject to the terms of the
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Common Development and Distribution License (the "License").
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * You may not use this file except in compliance with the License.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * or http://www.opensolaris.org/os/licensing.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * See the License for the specific language governing permissions
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * and limitations under the License.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * When distributing Covered Code, include this CDDL HEADER in each
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * If applicable, add the following below this CDDL HEADER, with the
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * fields enclosed by brackets "[]" replaced with your own identifying
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * information: Portions Copyright [yyyy] [name of copyright owner]
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * CDDL HEADER END
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/types.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/stream.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/dlpi.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/stropts.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/strsun.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/sysmacros.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/strlog.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/ddi.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/cmn_err.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/socket.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <net/if.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <net/if_types.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <netinet/in.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/ethernet.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <inet/arp.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <inet/ip.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <inet/ip6.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <inet/ip_ire.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <inet/ip_if.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <inet/ip_ftable.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/sunddi.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/ksynch.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/rds.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/socket.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/socketvar.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/sockio.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/sysmacros.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <inet/common.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <inet/ip.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <net/if_types.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/ib/clients/rdsv3/rdsv3.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/ib/clients/rdsv3/rdma.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/ib/clients/rdsv3/ib.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/ib/clients/rdsv3/rdsv3_impl.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/ib/clients/rdsv3/rdsv3_debug.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/dls.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/mac.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/mac_client.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/mac_provider.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/mac_client_priv.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaddi_taskq_t *rdsv3_taskq = NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaextern kmem_cache_t *rdsv3_alloc_cache;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaextern unsigned int ip_ocsum(ushort_t *address, int halfword_count,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota unsigned int sum);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Check if the IP interface named by `lifrp' is RDS-capable.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaboolean_t
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_capable_interface(struct lifreq *lifrp)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota char ifname[LIFNAMSIZ];
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota char drv[MAXLINKNAMELEN];
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota uint_t ppa;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota char *cp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_capable_interface", "Enter");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (lifrp->lifr_type == IFT_IB)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (B_TRUE);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Strip off the logical interface portion before getting
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * intimate with the name.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (void) strlcpy(ifname, lifrp->lifr_name, LIFNAMSIZ);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((cp = strchr(ifname, ':')) != NULL)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *cp = '\0';
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (strcmp("lo0", ifname) == 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * loopback is considered RDS-capable
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (B_TRUE);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (ddi_parse(ifname, drv, &ppa) == DDI_SUCCESS &&
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_if_lookup_by_name(drv));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaint
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_do_ip_ioctl(ksocket_t so4, void **ipaddrs, int *size, int *nifs)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct lifnum lifn;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct lifconf lifc;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct lifreq *lp, *rlp, lifr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int rval = 0;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int numifs;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int bufsize, rbufsize;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota void *buf, *rbuf;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int i, j, n, rc;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *ipaddrs = NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *size = 0;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *nifs = 0;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_do_ip_ioctl", "Enter");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaretry_count:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* snapshot the current number of interfaces */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota lifn.lifn_family = PF_UNSPEC;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota lifn.lifn_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota lifn.lifn_count = 0;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rval = ksocket_ioctl(so4, SIOCGLIFNUM, (intptr_t)&lifn, &rval,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota CRED());
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rval != 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_do_ip_ioctl",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ksocket_ioctl returned: %d", rval);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (rval);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota numifs = lifn.lifn_count;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (numifs <= 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_do_ip_ioctl", "No interfaces found");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* allocate extra room in case more interfaces appear */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota numifs += 10;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* get the interface names and ip addresses */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota bufsize = numifs * sizeof (struct lifreq);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota buf = kmem_alloc(bufsize, KM_SLEEP);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota lifc.lifc_family = AF_UNSPEC;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota lifc.lifc_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota lifc.lifc_len = bufsize;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota lifc.lifc_buf = buf;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rc = ksocket_ioctl(so4, SIOCGLIFCONF, (intptr_t)&lifc, &rval, CRED());
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rc != 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_do_ip_ioctl", "SIOCGLIFCONF failed");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(buf, bufsize);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (rc);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* if our extra room is used up, try again */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (bufsize <= lifc.lifc_len) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(buf, bufsize);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota buf = NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota goto retry_count;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* calc actual number of ifconfs */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota n = lifc.lifc_len / sizeof (struct lifreq);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Count the RDS interfaces
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota for (i = 0, j = 0, lp = lifc.lifc_req; i < n; i++, lp++) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Copy as the SIOCGLIFFLAGS ioctl is destructive
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota bcopy(lp, &lifr, sizeof (struct lifreq));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * fetch the flags using the socket of the correct family
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (lifr.lifr_addr.ss_family) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case AF_INET:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rc = ksocket_ioctl(so4, SIOCGLIFFLAGS, (intptr_t)&lifr,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota &rval, CRED());
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota continue;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rc != 0) continue;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * If we got the flags, skip uninteresting
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * interfaces based on flags
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((lifr.lifr_flags & IFF_UP) != IFF_UP)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota continue;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (lifr.lifr_flags &
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (IFF_ANYCAST|IFF_NOLOCAL|IFF_DEPRECATED))
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota continue;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (!rdsv3_capable_interface(&lifr))
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota continue;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota j++;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (j <= 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_do_ip_ioctl", "No RDS interfaces");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(buf, bufsize);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (rval);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota numifs = j;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* This is the buffer we pass back */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rbufsize = numifs * sizeof (struct lifreq);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rbuf = kmem_alloc(rbufsize, KM_SLEEP);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rlp = (struct lifreq *)rbuf;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Examine the array of interfaces and filter uninteresting ones
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota for (i = 0, lp = lifc.lifc_req; i < n; i++, lp++) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Copy the address as the SIOCGLIFFLAGS ioctl is destructive
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota bcopy(lp, &lifr, sizeof (struct lifreq));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * fetch the flags using the socket of the correct family
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (lifr.lifr_addr.ss_family) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case AF_INET:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rc = ksocket_ioctl(so4, SIOCGLIFFLAGS, (intptr_t)&lifr,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota &rval, CRED());
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota continue;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rc != 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_do_ip_ioctl",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ksocket_ioctl failed" " for %s", lifr.lifr_name);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota continue;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * If we got the flags, skip uninteresting
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * interfaces based on flags
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((lifr.lifr_flags & IFF_UP) != IFF_UP)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota continue;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (lifr.lifr_flags &
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (IFF_ANYCAST|IFF_NOLOCAL|IFF_DEPRECATED))
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota continue;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (!rdsv3_capable_interface(&lifr))
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota continue;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* save the record */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota bcopy(lp, rlp, sizeof (struct lifreq));
b27516f55237249607f754e6e42e865f12456675agiri rlp->lifr_addr.ss_family = AF_INET_OFFLOAD;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rlp++;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(buf, bufsize);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *ipaddrs = rbuf;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *size = rbufsize;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *nifs = numifs;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_do_ip_ioctl", "Return");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (rval);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Check if the IP interface named by `ifrp' is RDS-capable.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaboolean_t
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_capable_interface_old(struct ifreq *ifrp)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota char ifname[IFNAMSIZ];
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota char drv[MAXLINKNAMELEN];
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota uint_t ppa;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota char *cp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_capable_interface_old", "Enter");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Strip off the logical interface portion before getting
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * intimate with the name.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (void) strlcpy(ifname, ifrp->ifr_name, IFNAMSIZ);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((cp = strchr(ifname, ':')) != NULL)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *cp = '\0';
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_capable_interface_old", "ifname: %s", ifname);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((strcmp("lo0", ifname) == 0) ||
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (strncmp("ibd", ifname, 3) == 0)) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * loopback and IB are considered RDS-capable
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (B_TRUE);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (ddi_parse(ifname, drv, &ppa) == DDI_SUCCESS &&
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_if_lookup_by_name(drv));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaint
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_do_ip_ioctl_old(ksocket_t so4, void **ipaddrs, int *size, int *nifs)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota uint_t ifn;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct ifconf ifc;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct ifreq *lp, *rlp, ifr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int rval = 0;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int numifs;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int bufsize, rbufsize;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota void *buf, *rbuf;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int i, j, n, rc;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *ipaddrs = NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *size = 0;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *nifs = 0;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_do_ip_ioctl_old", "Enter");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaretry_count:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rval = ksocket_ioctl(so4, SIOCGIFNUM, (intptr_t)&ifn, &rval,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota CRED());
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rval != 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_do_ip_ioctl_old",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ksocket_ioctl(SIOCGIFNUM) returned: %d", rval);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (rval);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota numifs = ifn;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (numifs <= 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_do_ip_ioctl_old", "No interfaces found");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* allocate extra room in case more interfaces appear */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota numifs += 10;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* get the interface names and ip addresses */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota bufsize = numifs * sizeof (struct ifreq);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota buf = kmem_alloc(bufsize, KM_SLEEP);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ifc.ifc_len = bufsize;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ifc.ifc_buf = buf;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rc = ksocket_ioctl(so4, SIOCGIFCONF, (intptr_t)&ifc, &rval, CRED());
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rc != 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_do_ip_ioctl_old",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "SIOCGLIFCONF failed: %d", rc);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(buf, bufsize);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (rc);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* if our extra room is used up, try again */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (bufsize <= ifc.ifc_len) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(buf, bufsize);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota buf = NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota goto retry_count;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* calc actual number of ifconfs */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota n = ifc.ifc_len / sizeof (struct ifreq);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Count the RDS interfaces
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota for (i = 0, j = 0, lp = ifc.ifc_req; i < n; i++, lp++) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Copy as the SIOCGIFFLAGS ioctl is destructive
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota bcopy(lp, &ifr, sizeof (struct ifreq));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * fetch the flags using the socket of the correct family
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (ifr.ifr_addr.sa_family) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case AF_INET:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rc = ksocket_ioctl(so4, SIOCGIFFLAGS, (intptr_t)&ifr,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota &rval, CRED());
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota continue;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rc != 0) continue;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_do_ip_ioctl_old",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "1. ifr_name: %s, flags: %d", ifr.ifr_name,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (ushort_t)ifr.ifr_flags);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * If we got the flags, skip uninteresting
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * interfaces based on flags
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((((ushort_t)ifr.ifr_flags) & IFF_UP) != IFF_UP)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota continue;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_do_ip_ioctl_old",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "2. ifr_name: %s, flags: %d", ifr.ifr_name,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (ushort_t)ifr.ifr_flags);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (((ushort_t)ifr.ifr_flags) &
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (IFF_ANYCAST|IFF_NOLOCAL|IFF_DEPRECATED))
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota continue;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_do_ip_ioctl_old",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "3. ifr_name: %s, flags: %d", ifr.ifr_name,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (ushort_t)ifr.ifr_flags);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (!rdsv3_capable_interface_old(&ifr))
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota continue;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_do_ip_ioctl_old",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "4. ifr_name: %s, flags: %d", ifr.ifr_name,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (ushort_t)ifr.ifr_flags);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota j++;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (j <= 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_do_ip_ioctl_old", "No RDS interfaces");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(buf, bufsize);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (rval);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota numifs = j;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* This is the buffer we pass back */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rbufsize = numifs * sizeof (struct ifreq);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rbuf = kmem_alloc(rbufsize, KM_SLEEP);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rlp = (struct ifreq *)rbuf;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Examine the array of interfaces and filter uninteresting ones
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota for (i = 0, lp = ifc.ifc_req; i < n; i++, lp++) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Copy the address as the SIOCGIFFLAGS ioctl is destructive
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota bcopy(lp, &ifr, sizeof (struct ifreq));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * fetch the flags using the socket of the correct family
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (ifr.ifr_addr.sa_family) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case AF_INET:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rc = ksocket_ioctl(so4, SIOCGIFFLAGS, (intptr_t)&ifr,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota &rval, CRED());
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota continue;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rc != 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_do_ip_ioctl_old",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ksocket_ioctl failed: %d for %s",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rc, ifr.ifr_name);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota continue;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * If we got the flags, skip uninteresting
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * interfaces based on flags
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((((ushort_t)ifr.ifr_flags) & IFF_UP) != IFF_UP)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota continue;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (((ushort_t)ifr.ifr_flags) &
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (IFF_ANYCAST|IFF_NOLOCAL|IFF_DEPRECATED))
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota continue;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (!rdsv3_capable_interface_old(&ifr))
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota continue;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* save the record */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota bcopy(lp, rlp, sizeof (struct ifreq));
b27516f55237249607f754e6e42e865f12456675agiri rlp->ifr_addr.sa_family = AF_INET_OFFLOAD;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rlp++;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(buf, bufsize);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *ipaddrs = rbuf;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *size = rbufsize;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *nifs = numifs;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_do_ip_ioctl_old", "Return");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (rval);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaboolean_t
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_isloopback(ipaddr_t addr)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ip_stack_t *ipst;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ipst = netstack_find_by_zoneid(GLOBAL_ZONEID)->netstack_ip;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(ipst != NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ip_type_v4(addr, ipst) != IRE_LOOPBACK) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota netstack_rele(ipst->ips_netstack);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (B_FALSE);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota netstack_rele(ipst->ips_netstack);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (B_TRUE);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Work Queue Implementation
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#define RDSV3_WQ_THREAD_IDLE 0
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#define RDSV3_WQ_THREAD_RUNNING 1
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#define RDSV3_WQ_THREAD_FLUSHING 2
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#define RDSV3_WQ_THREAD_EXITING 3
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/* worker thread */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_worker_thread(void *arg)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_workqueue_struct_t *wq = arg;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_work_t *work;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_worker_thread", "Enter(wq: 0x%p)", wq);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota work = list_remove_head(&wq->wq_queue);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota while (work) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* process work */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota work->func(work);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota work = list_remove_head(&wq->wq_queue);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* No more work, go home, until called again */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (wq->wq_state != RDSV3_WQ_THREAD_EXITING) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota wq->wq_state = RDSV3_WQ_THREAD_IDLE;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_worker_thread", "Return(wq: 0x%p)", wq);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/* XXX */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_flush_workqueue(rdsv3_workqueue_struct_t *wq)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_flush_workqueue", "Enter(wq: %p)", wq);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (wq->wq_state) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case RDSV3_WQ_THREAD_IDLE:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* nothing to do */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(list_is_empty(&wq->wq_queue));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case RDSV3_WQ_THREAD_RUNNING:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota wq->wq_state = RDSV3_WQ_THREAD_FLUSHING;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* FALLTHRU */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case RDSV3_WQ_THREAD_FLUSHING:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* already flushing, wait until the flushing is complete */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota do {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota delay(drv_usectohz(1000000));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota } while (wq->wq_state == RDSV3_WQ_THREAD_FLUSHING);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case RDSV3_WQ_THREAD_EXITING:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_worker_thread(wq);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_flush_workqueue", "Return(wq: %p)", wq);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_queue_work(rdsv3_workqueue_struct_t *wq, rdsv3_work_t *wp)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_queue_work", "Enter(wq: %p, wp: %p)", wq, wp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (list_link_active(&wp->work_item)) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* This is already in the queue, ignore this call */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF3("rdsv3_queue_work", "already queued: %p", wp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (wq->wq_state) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case RDSV3_WQ_THREAD_RUNNING:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota list_insert_tail(&wq->wq_queue, wp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case RDSV3_WQ_THREAD_FLUSHING:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota do {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota delay(drv_usectohz(1000000));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota } while (wq->wq_state == RDSV3_WQ_THREAD_FLUSHING);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (wq->wq_state == RDSV3_WQ_THREAD_RUNNING) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota list_insert_tail(&wq->wq_queue, wp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* FALLTHRU */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case RDSV3_WQ_THREAD_IDLE:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota list_insert_tail(&wq->wq_queue, wp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota wq->wq_state = RDSV3_WQ_THREAD_RUNNING;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (void) ddi_taskq_dispatch(rdsv3_taskq, rdsv3_worker_thread, wq,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota DDI_SLEEP);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case RDSV3_WQ_THREAD_EXITING:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_queue_work", "Return(wq: %p, wp: %p)", wq, wp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/* timeout handler for delayed work queuing */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_work_timeout_handler(void *arg)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_delayed_work_t *dwp = (rdsv3_delayed_work_t *)arg;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_work_timeout_handler",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "Enter(wq: %p, wp: %p)", dwp->wq, &dwp->work);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&dwp->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota dwp->timeid = 0;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&dwp->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&dwp->wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota dwp->wq->wq_pending--;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (dwp->wq->wq_state == RDSV3_WQ_THREAD_EXITING) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&dwp->wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&dwp->wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_queue_work(dwp->wq, &dwp->work);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_work_timeout_handler",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "Return(wq: %p, wp: %p)", dwp->wq, &dwp->work);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_queue_delayed_work(rdsv3_workqueue_struct_t *wq,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_delayed_work_t *dwp, uint_t delay)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_queue_delayed_work",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "Enter(wq: %p, wp: %p)", wq, dwp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (delay == 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_queue_work(wq, &dwp->work);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (wq->wq_state == RDSV3_WQ_THREAD_EXITING) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_queue_delayed_work",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "WQ exiting - don't queue (wq: %p, wp: %p)", wq, dwp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota wq->wq_pending++;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&dwp->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (dwp->timeid == 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota dwp->wq = wq;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota dwp->timeid = timeout(rdsv3_work_timeout_handler, dwp,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota jiffies + (delay * rdsv3_one_sec_in_hz));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&dwp->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota } else {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&dwp->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_queue_delayed_work", "Already queued: %p",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota dwp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota wq->wq_pending--;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_queue_delayed_work",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "Return(wq: %p, wp: %p)", wq, dwp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_cancel_delayed_work(rdsv3_delayed_work_t *dwp)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_cancel_delayed_work",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "Enter(wq: %p, dwp: %p)", dwp->wq, dwp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&dwp->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (dwp->timeid != 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (void) untimeout(dwp->timeid);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota dwp->timeid = 0;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota } else {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_cancel_delayed_work",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "Nothing to cancel (wq: %p, dwp: %p)", dwp->wq, dwp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&dwp->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&dwp->lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&dwp->wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota dwp->wq->wq_pending--;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&dwp->wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_cancel_delayed_work",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "Return(wq: %p, dwp: %p)", dwp->wq, dwp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_destroy_task_workqueue(rdsv3_workqueue_struct_t *wq)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_destroy_workqueue", "Enter");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(wq);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota wq->wq_state = RDSV3_WQ_THREAD_EXITING;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota while (wq->wq_pending > 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota delay(drv_usectohz(1000000));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota };
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_flush_workqueue(wq);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota list_destroy(&wq->wq_queue);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_destroy(&wq->wq_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(wq, sizeof (rdsv3_workqueue_struct_t));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(rdsv3_taskq);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ddi_taskq_destroy(rdsv3_taskq);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota wq = NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_taskq = NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_destroy_workqueue", "Return");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/* ARGSUSED */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_rdma_init_worker(struct rdsv3_work_s *work)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_rdma_init();
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota#define RDSV3_NUM_TASKQ_THREADS 1
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_workqueue_struct_t *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_create_task_workqueue(char *name)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_workqueue_struct_t *wq;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("create_singlethread_workqueue", "Enter (dip: %p)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_dev_info);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_taskq = ddi_taskq_create(rdsv3_dev_info, name,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_NUM_TASKQ_THREADS, TASKQ_DEFAULTPRI, 0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rdsv3_taskq == NULL) {
6e18d381c642549b8bb1774a803d3510aec6baafagiri RDSV3_DPRINTF2(__FILE__,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ddi_taskq_create failed for rdsv3_taskq");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota wq = kmem_zalloc(sizeof (rdsv3_workqueue_struct_t), KM_NOSLEEP);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (wq == NULL) {
6e18d381c642549b8bb1774a803d3510aec6baafagiri RDSV3_DPRINTF2(__FILE__, "kmem_zalloc failed for wq");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ddi_taskq_destroy(rdsv3_taskq);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota list_create(&wq->wq_queue, sizeof (struct rdsv3_work_s),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota offsetof(struct rdsv3_work_s, work_item));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_init(&wq->wq_lock, NULL, MUTEX_DRIVER, NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota wq->wq_state = RDSV3_WQ_THREAD_IDLE;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota wq->wq_pending = 0;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_one_sec_in_hz = drv_usectohz(1000000);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("create_singlethread_workqueue", "Return");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (wq);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Implementation for struct sock
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_sock_exit_data(struct rsock *sk)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_sock *rs = sk->sk_protinfo;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_sock_exit_data", "rs: %p sk: %p", rs, sk);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(rs != NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(rdsv3_sk_sock_flag(sk, SOCK_DEAD));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rs->rs_sk = NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota list_destroy(&rs->rs_send_queue);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota list_destroy(&rs->rs_notify_queue);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota list_destroy(&rs->rs_recv_queue);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rw_destroy(&rs->rs_recv_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_destroy(&rs->rs_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_destroy(&rs->rs_rdma_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota avl_destroy(&rs->rs_rdma_keys);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota mutex_destroy(&rs->rs_conn_lock);
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota mutex_destroy(&rs->rs_congested_lock);
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota cv_destroy(&rs->rs_congested_cv);
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_exit_waitqueue(sk->sk_sleep);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(sk->sk_sleep, sizeof (rdsv3_wait_queue_t));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_destroy(&sk->sk_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_cache_free(rdsv3_alloc_cache, sk);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_sock_exit_data", "rs: %p sk: %p", rs, sk);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/* XXX - figure out right values */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#define RDSV3_RECV_HIWATER (256 * 1024)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#define RDSV3_RECV_LOWATER 128
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#define RDSV3_XMIT_HIWATER (256 * 1024)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#define RDSV3_XMIT_LOWATER 1024
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastruct rsock *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_sk_alloc()
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rsock *sk;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sk = kmem_cache_alloc(rdsv3_alloc_cache, KM_SLEEP);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (sk == NULL) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_create", "kmem_cache_alloc failed");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota bzero(sk, sizeof (struct rsock) + sizeof (struct rdsv3_sock));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (sk);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_sock_init_data(struct rsock *sk)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sk->sk_sleep = kmem_zalloc(sizeof (rdsv3_wait_queue_t), KM_SLEEP);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_init_waitqueue(sk->sk_sleep);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_init(&sk->sk_lock, NULL, MUTEX_DRIVER, NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sk->sk_refcount = 1;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sk->sk_protinfo = (struct rdsv3_sock *)(sk + 1);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sk->sk_sndbuf = RDSV3_XMIT_HIWATER;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sk->sk_rcvbuf = RDSV3_RECV_HIWATER;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Connection cache
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/* ARGSUSED */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaint
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_conn_constructor(void *buf, void *arg, int kmflags)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_connection *conn = buf;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota bzero(conn, sizeof (struct rdsv3_connection));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota conn->c_next_tx_seq = 1;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_init(&conn->c_lock, NULL, MUTEX_DRIVER, NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_init(&conn->c_send_lock, NULL, MUTEX_DRIVER, NULL);
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota conn->c_send_generation = 1;
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota conn->c_senders = 0;
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota list_create(&conn->c_send_queue, sizeof (struct rdsv3_message),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota offsetof(struct rdsv3_message, m_conn_item));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota list_create(&conn->c_retrans, sizeof (struct rdsv3_message),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota offsetof(struct rdsv3_message, m_conn_item));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/* ARGSUSED */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_conn_destructor(void *buf, void *arg)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_connection *conn = buf;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(list_is_empty(&conn->c_send_queue));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(list_is_empty(&conn->c_retrans));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota list_destroy(&conn->c_send_queue);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota list_destroy(&conn->c_retrans);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_destroy(&conn->c_send_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_destroy(&conn->c_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaint
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_conn_compare(const void *conn1, const void *conn2)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota uint32_be_t laddr1, faddr1, laddr2, faddr2;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota laddr1 = ((rdsv3_conn_info_t *)conn1)->c_laddr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota laddr2 = ((struct rdsv3_connection *)conn2)->c_laddr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (laddr1 == laddr2) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota faddr1 = ((rdsv3_conn_info_t *)conn1)->c_faddr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota faddr2 = ((struct rdsv3_connection *)conn2)->c_faddr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (faddr1 == faddr2)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (faddr1 < faddr2)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-1);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (1);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (laddr1 < laddr2)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-1);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (1);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
d2b539e744e90927cf7a57df3475145c279d68f9agiri/* rdsv3_ib_incoming cache */
d2b539e744e90927cf7a57df3475145c279d68f9agiri/* ARGSUSED */
d2b539e744e90927cf7a57df3475145c279d68f9agiriint
d2b539e744e90927cf7a57df3475145c279d68f9agirirdsv3_ib_inc_constructor(void *buf, void *arg, int kmflags)
d2b539e744e90927cf7a57df3475145c279d68f9agiri{
d2b539e744e90927cf7a57df3475145c279d68f9agiri list_create(&((struct rdsv3_ib_incoming *)buf)->ii_frags,
d2b539e744e90927cf7a57df3475145c279d68f9agiri sizeof (struct rdsv3_page_frag),
d2b539e744e90927cf7a57df3475145c279d68f9agiri offsetof(struct rdsv3_page_frag, f_item));
d2b539e744e90927cf7a57df3475145c279d68f9agiri
d2b539e744e90927cf7a57df3475145c279d68f9agiri return (0);
d2b539e744e90927cf7a57df3475145c279d68f9agiri}
d2b539e744e90927cf7a57df3475145c279d68f9agiri
d2b539e744e90927cf7a57df3475145c279d68f9agiri/* ARGSUSED */
d2b539e744e90927cf7a57df3475145c279d68f9agirivoid
d2b539e744e90927cf7a57df3475145c279d68f9agirirdsv3_ib_inc_destructor(void *buf, void *arg)
d2b539e744e90927cf7a57df3475145c279d68f9agiri{
d2b539e744e90927cf7a57df3475145c279d68f9agiri list_destroy(&((struct rdsv3_ib_incoming *)buf)->ii_frags);
d2b539e744e90927cf7a57df3475145c279d68f9agiri}
d2b539e744e90927cf7a57df3475145c279d68f9agiri
d2b539e744e90927cf7a57df3475145c279d68f9agiri/* ib_frag_slab cache */
d2b539e744e90927cf7a57df3475145c279d68f9agiri/* ARGSUSED */
d2b539e744e90927cf7a57df3475145c279d68f9agiriint
d2b539e744e90927cf7a57df3475145c279d68f9agirirdsv3_ib_frag_constructor(void *buf, void *arg, int kmflags)
d2b539e744e90927cf7a57df3475145c279d68f9agiri{
d2b539e744e90927cf7a57df3475145c279d68f9agiri struct rdsv3_page_frag *frag = (struct rdsv3_page_frag *)buf;
d2b539e744e90927cf7a57df3475145c279d68f9agiri struct rdsv3_ib_device *rds_ibdev = (struct rdsv3_ib_device *)arg;
d2b539e744e90927cf7a57df3475145c279d68f9agiri ibt_iov_attr_t iov_attr;
d2b539e744e90927cf7a57df3475145c279d68f9agiri ibt_iov_t iov_arr[1];
d2b539e744e90927cf7a57df3475145c279d68f9agiri ibt_all_wr_t wr;
d2b539e744e90927cf7a57df3475145c279d68f9agiri
d2b539e744e90927cf7a57df3475145c279d68f9agiri bzero(frag, sizeof (struct rdsv3_page_frag));
d2b539e744e90927cf7a57df3475145c279d68f9agiri list_link_init(&frag->f_item);
d2b539e744e90927cf7a57df3475145c279d68f9agiri
d2b539e744e90927cf7a57df3475145c279d68f9agiri frag->f_page = kmem_alloc(PAGE_SIZE, kmflags);
d2b539e744e90927cf7a57df3475145c279d68f9agiri if (frag->f_page == NULL) {
d2b539e744e90927cf7a57df3475145c279d68f9agiri RDSV3_DPRINTF2("rdsv3_ib_frag_constructor",
d2b539e744e90927cf7a57df3475145c279d68f9agiri "kmem_alloc for %d failed", PAGE_SIZE);
d2b539e744e90927cf7a57df3475145c279d68f9agiri return (-1);
d2b539e744e90927cf7a57df3475145c279d68f9agiri }
d2b539e744e90927cf7a57df3475145c279d68f9agiri frag->f_offset = 0;
d2b539e744e90927cf7a57df3475145c279d68f9agiri
d2b539e744e90927cf7a57df3475145c279d68f9agiri iov_attr.iov_as = NULL;
d2b539e744e90927cf7a57df3475145c279d68f9agiri iov_attr.iov = &iov_arr[0];
d2b539e744e90927cf7a57df3475145c279d68f9agiri iov_attr.iov_buf = NULL;
d2b539e744e90927cf7a57df3475145c279d68f9agiri iov_attr.iov_list_len = 1;
d2b539e744e90927cf7a57df3475145c279d68f9agiri iov_attr.iov_wr_nds = 1;
d2b539e744e90927cf7a57df3475145c279d68f9agiri iov_attr.iov_lso_hdr_sz = 0;
d2b539e744e90927cf7a57df3475145c279d68f9agiri iov_attr.iov_flags = IBT_IOV_SLEEP | IBT_IOV_RECV;
d2b539e744e90927cf7a57df3475145c279d68f9agiri
d2b539e744e90927cf7a57df3475145c279d68f9agiri iov_arr[0].iov_addr = frag->f_page;
d2b539e744e90927cf7a57df3475145c279d68f9agiri iov_arr[0].iov_len = PAGE_SIZE;
d2b539e744e90927cf7a57df3475145c279d68f9agiri
d2b539e744e90927cf7a57df3475145c279d68f9agiri wr.recv.wr_nds = 1;
d2b539e744e90927cf7a57df3475145c279d68f9agiri wr.recv.wr_sgl = &frag->f_sge;
d2b539e744e90927cf7a57df3475145c279d68f9agiri
d2b539e744e90927cf7a57df3475145c279d68f9agiri if (ibt_map_mem_iov(ib_get_ibt_hca_hdl(rds_ibdev->dev),
d2b539e744e90927cf7a57df3475145c279d68f9agiri &iov_attr, &wr, &frag->f_mapped) != IBT_SUCCESS) {
d2b539e744e90927cf7a57df3475145c279d68f9agiri RDSV3_DPRINTF2("rdsv3_ib_frag_constructor",
d2b539e744e90927cf7a57df3475145c279d68f9agiri "ibt_map_mem_iov failed");
d2b539e744e90927cf7a57df3475145c279d68f9agiri kmem_free(frag->f_page, PAGE_SIZE);
d2b539e744e90927cf7a57df3475145c279d68f9agiri return (-1);
d2b539e744e90927cf7a57df3475145c279d68f9agiri }
d2b539e744e90927cf7a57df3475145c279d68f9agiri
d2b539e744e90927cf7a57df3475145c279d68f9agiri return (0);
d2b539e744e90927cf7a57df3475145c279d68f9agiri}
d2b539e744e90927cf7a57df3475145c279d68f9agiri
d2b539e744e90927cf7a57df3475145c279d68f9agiri/* ARGSUSED */
d2b539e744e90927cf7a57df3475145c279d68f9agirivoid
d2b539e744e90927cf7a57df3475145c279d68f9agirirdsv3_ib_frag_destructor(void *buf, void *arg)
d2b539e744e90927cf7a57df3475145c279d68f9agiri{
d2b539e744e90927cf7a57df3475145c279d68f9agiri struct rdsv3_page_frag *frag = (struct rdsv3_page_frag *)buf;
d2b539e744e90927cf7a57df3475145c279d68f9agiri struct rdsv3_ib_device *rds_ibdev = (struct rdsv3_ib_device *)arg;
d2b539e744e90927cf7a57df3475145c279d68f9agiri
d2b539e744e90927cf7a57df3475145c279d68f9agiri /* unmap the page */
d2b539e744e90927cf7a57df3475145c279d68f9agiri if (ibt_unmap_mem_iov(ib_get_ibt_hca_hdl(rds_ibdev->dev),
d2b539e744e90927cf7a57df3475145c279d68f9agiri frag->f_mapped) != IBT_SUCCESS)
d2b539e744e90927cf7a57df3475145c279d68f9agiri RDSV3_DPRINTF2("rdsv3_ib_frag_destructor",
d2b539e744e90927cf7a57df3475145c279d68f9agiri "ibt_unmap_mem_iov failed");
d2b539e744e90927cf7a57df3475145c279d68f9agiri
d2b539e744e90927cf7a57df3475145c279d68f9agiri /* free the page */
d2b539e744e90927cf7a57df3475145c279d68f9agiri kmem_free(frag->f_page, PAGE_SIZE);
d2b539e744e90927cf7a57df3475145c279d68f9agiri}
d2b539e744e90927cf7a57df3475145c279d68f9agiri
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/* loop.c */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaextern kmutex_t loop_conns_lock;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaextern list_t loop_conns;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastruct rdsv3_loop_connection
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct list_node loop_node;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_connection *conn;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota};
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_loop_init(void)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota list_create(&loop_conns, sizeof (struct rdsv3_loop_connection),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota offsetof(struct rdsv3_loop_connection, loop_node));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_init(&loop_conns_lock, NULL, MUTEX_DRIVER, NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/* rdma.c */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/* IB Rkey is used here for comparison */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaint
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_mr_compare(const void *mr1, const void *mr2)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota uint32_t key1 = *(uint32_t *)mr1;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota uint32_t key2 = ((struct rdsv3_mr *)mr2)->r_key;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (key1 < key2)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-1);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (key1 > key2)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (1);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/* transport.c */
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Otaextern struct rdsv3_transport *transports[];
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaextern krwlock_t trans_sem;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_trans_exit(void)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_transport *trans;
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota int i;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_trans_exit", "Enter");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* currently, only IB transport */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rw_enter(&trans_sem, RW_READER);
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota trans = NULL;
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota for (i = 0; i < RDS_TRANS_COUNT; i++) {
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota if (transports[i]) {
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota trans = transports[i];
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota break;
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota }
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rw_exit(&trans_sem);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* trans->exit() will remove the trans from the list */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (trans)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota trans->exit();
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rw_destroy(&trans_sem);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_trans_exit", "Return");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_trans_init()
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_trans_init", "Enter");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rw_init(&trans_sem, NULL, RW_DRIVER, NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_trans_init", "Return");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaint
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_put_cmsg(struct nmsghdr *msg, int level, int type, size_t size,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota void *payload)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct cmsghdr *cp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota char *bp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota size_t cmlen;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota size_t cmspace;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota size_t bufsz;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_put_cmsg",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "Enter(msg: %p level: %d type: %d sz: %d)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota msg, level, type, size);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
9b3d509c544ac523c29e6a3cfd08e87a552b622bEiji Ota if (msg == NULL || msg->msg_controllen == 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* check for first cmsg or this is another cmsg to be appended */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (msg->msg_control == NULL)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota msg->msg_controllen = 0;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cmlen = CMSG_LEN(size);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cmspace = CMSG_SPACE(size);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota bufsz = msg->msg_controllen + cmspace;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* extend the existing cmsg to append the next cmsg */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota bp = kmem_alloc(bufsz, KM_SLEEP);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (msg->msg_control) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota bcopy(msg->msg_control, bp, msg->msg_controllen);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(msg->msg_control, (size_t)msg->msg_controllen);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* assign payload the proper cmsg location */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cp = (struct cmsghdr *)(bp + msg->msg_controllen);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cp->cmsg_len = cmlen;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cp->cmsg_level = level;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cp->cmsg_type = type;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota bcopy(payload, CMSG_DATA(cp), cmlen -
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (unsigned int)_CMSG_DATA_ALIGN(sizeof (struct cmsghdr)));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota msg->msg_control = bp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota msg->msg_controllen = bufsz;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_put_cmsg", "Return(cmsg_len: %d)", cp->cmsg_len);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/* ARGSUSED */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaint
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_verify_bind_address(ipaddr_t addr)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (1);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/* checksum */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otauint16_t
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_ip_fast_csum(void *hdr, size_t length)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0xffff &
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (uint16_t)(~ip_ocsum((ushort_t *)hdr, (int)length <<1, 0)));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/* scatterlist implementation */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/* ARGSUSED */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otacaddr_t
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_ib_sg_dma_address(ib_device_t *dev, struct rdsv3_scatterlist *scat,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota uint_t offset)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otauint_t
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_ib_dma_map_sg(struct ib_device *dev, struct rdsv3_scatterlist *scat,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota uint_t num)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_scatterlist *s, *first;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_iov_t *iov;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_wr_ds_t *sgl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_iov_attr_t iov_attr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_send_wr_t swr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota uint_t i;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_ib_dma_map_sg", "scat %p, num: %d", scat, num);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota s = first = &scat[0];
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(first->mihdl == NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota iov = kmem_alloc(num * sizeof (ibt_iov_t), KM_SLEEP);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sgl = kmem_zalloc((num * 2) * sizeof (ibt_wr_ds_t), KM_SLEEP);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota for (i = 0; i < num; i++, s++) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota iov[i].iov_addr = s->vaddr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota iov[i].iov_len = s->length;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota iov_attr.iov_as = NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota iov_attr.iov = iov;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota iov_attr.iov_buf = NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota iov_attr.iov_list_len = num;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota iov_attr.iov_wr_nds = num * 2;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota iov_attr.iov_lso_hdr_sz = 0;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota iov_attr.iov_flags = IBT_IOV_SLEEP;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota swr.wr_sgl = sgl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota i = ibt_map_mem_iov(ib_get_ibt_hca_hdl(dev),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota &iov_attr, (ibt_all_wr_t *)&swr, &first->mihdl);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(iov, num * sizeof (ibt_iov_t));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (i != IBT_SUCCESS) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_ib_dma_map_sg",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ibt_map_mem_iov returned: %d", i);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota s = first;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota for (i = 0; i < num; i++, s++, sgl++) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota s->sgl = sgl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (num);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_ib_dma_unmap_sg(ib_device_t *dev, struct rdsv3_scatterlist *scat,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota uint_t num)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* Zero length messages have no scatter gather entries */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (num != 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(scat->mihdl != NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(scat->sgl != NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (void) ibt_unmap_mem_iov(ib_get_ibt_hca_hdl(dev), scat->mihdl);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(scat->sgl, (num * 2) * sizeof (ibt_wr_ds_t));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota scat->sgl = NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota scat->mihdl = NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaint
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_ib_alloc_hdrs(ib_device_t *dev, struct rdsv3_ib_connection *ic)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota caddr_t addr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota size_t size;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_mr_attr_t mr_attr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_mr_desc_t mr_desc;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ibt_mr_hdl_t mr_hdl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int ret;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_ib_alloc_hdrs", "Enter(dev: %p)", dev);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(ic->i_mr == NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota size = (ic->i_send_ring.w_nr + ic->i_recv_ring.w_nr + 1) *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sizeof (struct rdsv3_header);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota addr = kmem_zalloc(size, KM_NOSLEEP);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (addr == NULL)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-1);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mr_attr.mr_vaddr = (ib_vaddr_t)(uintptr_t)addr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mr_attr.mr_len = size;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mr_attr.mr_as = NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mr_attr.mr_flags = IBT_MR_ENABLE_LOCAL_WRITE;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = ibt_register_mr(ib_get_ibt_hca_hdl(dev), RDSV3_PD2PDHDL(ic->i_pd),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota &mr_attr, &mr_hdl, &mr_desc);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ret != IBT_SUCCESS) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_ib_alloc_hdrs",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ibt_register_mr returned: " "%d", ret);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-1);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ic->i_mr =
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (struct rdsv3_hdrs_mr *)kmem_alloc(sizeof (struct rdsv3_hdrs_mr),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota KM_SLEEP);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ic->i_mr->addr = addr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ic->i_mr->size = size;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ic->i_mr->hdl = mr_hdl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ic->i_mr->lkey = mr_desc.md_lkey;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ic->i_send_hdrs = (struct rdsv3_header *)addr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ic->i_send_hdrs_dma = (uint64_t)(uintptr_t)addr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ic->i_recv_hdrs = (struct rdsv3_header *)(addr +
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (ic->i_send_ring.w_nr * sizeof (struct rdsv3_header)));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ic->i_recv_hdrs_dma = (uint64_t)(uintptr_t)(addr +
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (ic->i_send_ring.w_nr * sizeof (struct rdsv3_header)));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ic->i_ack = (struct rdsv3_header *)(addr +
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ((ic->i_send_ring.w_nr + ic->i_recv_ring.w_nr) *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sizeof (struct rdsv3_header)));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ic->i_ack_dma = (uint64_t)(uintptr_t)(addr +
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ((ic->i_send_ring.w_nr + ic->i_recv_ring.w_nr) *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sizeof (struct rdsv3_header)));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_ib_alloc_hdrs", "Return(dev: %p)", dev);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_ib_free_hdrs(ib_device_t *dev, struct rdsv3_ib_connection *ic)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_ib_free_hdrs", "Enter(dev: %p)", dev);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(ic->i_mr != NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ic->i_send_hdrs = NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ic->i_send_hdrs_dma = NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ic->i_recv_hdrs = NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ic->i_recv_hdrs_dma = NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ic->i_ack = NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ic->i_ack_dma = NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (void) ibt_deregister_mr(ib_get_ibt_hca_hdl(dev), ic->i_mr->hdl);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(ic->i_mr->addr, ic->i_mr->size);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(ic->i_mr, sizeof (struct rdsv3_hdrs_mr));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ic->i_mr = NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_ib_free_hdrs", "Return(dev: %p)", dev);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota/*
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota * atomic_add_unless - add unless the number is a given value
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota * @v: pointer of type atomic_t
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota * @a: the amount to add to v...
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota * @u: ...unless v is equal to u.
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota *
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota * Atomically adds @a to @v, so long as it was not @u.
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota * Returns non-zero if @v was not @u, and zero otherwise.
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota */
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Otaint
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Otaatomic_add_unless(atomic_t *v, uint_t a, ulong_t u)
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota{
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota uint_t c, old;
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota c = *v;
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota while (c != u && (old = atomic_cas_uint(v, c, c + a)) != c) {
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota c = old;
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota }
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota return ((ulong_t)c != u);
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota}