112198SEiji.Ota@Sun.COM /*
212198SEiji.Ota@Sun.COM * CDDL HEADER START
312198SEiji.Ota@Sun.COM *
412198SEiji.Ota@Sun.COM * The contents of this file are subject to the terms of the
512198SEiji.Ota@Sun.COM * Common Development and Distribution License (the "License").
612198SEiji.Ota@Sun.COM * You may not use this file except in compliance with the License.
712198SEiji.Ota@Sun.COM *
812198SEiji.Ota@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
912198SEiji.Ota@Sun.COM * or http://www.opensolaris.org/os/licensing.
1012198SEiji.Ota@Sun.COM * See the License for the specific language governing permissions
1112198SEiji.Ota@Sun.COM * and limitations under the License.
1212198SEiji.Ota@Sun.COM *
1312198SEiji.Ota@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
1412198SEiji.Ota@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1512198SEiji.Ota@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
1612198SEiji.Ota@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
1712198SEiji.Ota@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
1812198SEiji.Ota@Sun.COM *
1912198SEiji.Ota@Sun.COM * CDDL HEADER END
2012198SEiji.Ota@Sun.COM */
2112198SEiji.Ota@Sun.COM /*
2212198SEiji.Ota@Sun.COM * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
2312198SEiji.Ota@Sun.COM */
2412198SEiji.Ota@Sun.COM #include <sys/types.h>
2512198SEiji.Ota@Sun.COM #include <sys/stream.h>
2612198SEiji.Ota@Sun.COM #include <sys/dlpi.h>
2712198SEiji.Ota@Sun.COM #include <sys/stropts.h>
2812198SEiji.Ota@Sun.COM #include <sys/strsun.h>
2912198SEiji.Ota@Sun.COM #include <sys/sysmacros.h>
3012198SEiji.Ota@Sun.COM #include <sys/strlog.h>
3112198SEiji.Ota@Sun.COM #include <sys/ddi.h>
3212198SEiji.Ota@Sun.COM #include <sys/cmn_err.h>
3312198SEiji.Ota@Sun.COM #include <sys/socket.h>
3412198SEiji.Ota@Sun.COM #include <net/if.h>
3512198SEiji.Ota@Sun.COM #include <net/if_types.h>
3612198SEiji.Ota@Sun.COM #include <netinet/in.h>
3712198SEiji.Ota@Sun.COM #include <sys/ethernet.h>
3812198SEiji.Ota@Sun.COM #include <inet/arp.h>
3912198SEiji.Ota@Sun.COM #include <inet/ip.h>
4012198SEiji.Ota@Sun.COM #include <inet/ip6.h>
4112198SEiji.Ota@Sun.COM #include <inet/ip_ire.h>
4212198SEiji.Ota@Sun.COM #include <inet/ip_if.h>
4312198SEiji.Ota@Sun.COM #include <inet/ip_ftable.h>
4412198SEiji.Ota@Sun.COM
4512198SEiji.Ota@Sun.COM #include <sys/sunddi.h>
4612198SEiji.Ota@Sun.COM #include <sys/ksynch.h>
4712198SEiji.Ota@Sun.COM
4812198SEiji.Ota@Sun.COM #include <sys/rds.h>
4912198SEiji.Ota@Sun.COM #include <sys/socket.h>
5012198SEiji.Ota@Sun.COM #include <sys/socketvar.h>
5112198SEiji.Ota@Sun.COM #include <sys/sockio.h>
5212198SEiji.Ota@Sun.COM #include <sys/sysmacros.h>
5312198SEiji.Ota@Sun.COM #include <inet/common.h>
5412198SEiji.Ota@Sun.COM #include <inet/ip.h>
5512198SEiji.Ota@Sun.COM #include <net/if_types.h>
5612198SEiji.Ota@Sun.COM
5712198SEiji.Ota@Sun.COM #include <sys/ib/clients/rdsv3/rdsv3.h>
5812198SEiji.Ota@Sun.COM #include <sys/ib/clients/rdsv3/rdma.h>
5912198SEiji.Ota@Sun.COM #include <sys/ib/clients/rdsv3/ib.h>
6012198SEiji.Ota@Sun.COM #include <sys/ib/clients/rdsv3/rdsv3_impl.h>
6112198SEiji.Ota@Sun.COM #include <sys/ib/clients/rdsv3/rdsv3_debug.h>
6212198SEiji.Ota@Sun.COM
6312198SEiji.Ota@Sun.COM #include <sys/dls.h>
6412198SEiji.Ota@Sun.COM #include <sys/mac.h>
6512198SEiji.Ota@Sun.COM #include <sys/mac_client.h>
6612198SEiji.Ota@Sun.COM #include <sys/mac_provider.h>
6712198SEiji.Ota@Sun.COM #include <sys/mac_client_priv.h>
6812198SEiji.Ota@Sun.COM
6912198SEiji.Ota@Sun.COM ddi_taskq_t *rdsv3_taskq = NULL;
7012198SEiji.Ota@Sun.COM extern kmem_cache_t *rdsv3_alloc_cache;
7112198SEiji.Ota@Sun.COM
7212198SEiji.Ota@Sun.COM extern unsigned int ip_ocsum(ushort_t *address, int halfword_count,
7312198SEiji.Ota@Sun.COM unsigned int sum);
7412198SEiji.Ota@Sun.COM
7512198SEiji.Ota@Sun.COM /*
7612198SEiji.Ota@Sun.COM * Check if the IP interface named by `lifrp' is RDS-capable.
7712198SEiji.Ota@Sun.COM */
7812198SEiji.Ota@Sun.COM boolean_t
rdsv3_capable_interface(struct lifreq * lifrp)7912198SEiji.Ota@Sun.COM rdsv3_capable_interface(struct lifreq *lifrp)
8012198SEiji.Ota@Sun.COM {
8112198SEiji.Ota@Sun.COM char ifname[LIFNAMSIZ];
8212198SEiji.Ota@Sun.COM char drv[MAXLINKNAMELEN];
8312198SEiji.Ota@Sun.COM uint_t ppa;
8412198SEiji.Ota@Sun.COM char *cp;
8512198SEiji.Ota@Sun.COM
8612198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_capable_interface", "Enter");
8712198SEiji.Ota@Sun.COM
8812198SEiji.Ota@Sun.COM if (lifrp->lifr_type == IFT_IB)
8912198SEiji.Ota@Sun.COM return (B_TRUE);
9012198SEiji.Ota@Sun.COM
9112198SEiji.Ota@Sun.COM /*
9212198SEiji.Ota@Sun.COM * Strip off the logical interface portion before getting
9312198SEiji.Ota@Sun.COM * intimate with the name.
9412198SEiji.Ota@Sun.COM */
9512198SEiji.Ota@Sun.COM (void) strlcpy(ifname, lifrp->lifr_name, LIFNAMSIZ);
9612198SEiji.Ota@Sun.COM if ((cp = strchr(ifname, ':')) != NULL)
9712198SEiji.Ota@Sun.COM *cp = '\0';
9812198SEiji.Ota@Sun.COM
9912198SEiji.Ota@Sun.COM if (strcmp("lo0", ifname) == 0) {
10012198SEiji.Ota@Sun.COM /*
10112198SEiji.Ota@Sun.COM * loopback is considered RDS-capable
10212198SEiji.Ota@Sun.COM */
10312198SEiji.Ota@Sun.COM return (B_TRUE);
10412198SEiji.Ota@Sun.COM }
10512198SEiji.Ota@Sun.COM
10612198SEiji.Ota@Sun.COM return (ddi_parse(ifname, drv, &ppa) == DDI_SUCCESS &&
10712198SEiji.Ota@Sun.COM rdsv3_if_lookup_by_name(drv));
10812198SEiji.Ota@Sun.COM }
10912198SEiji.Ota@Sun.COM
11012198SEiji.Ota@Sun.COM int
rdsv3_do_ip_ioctl(ksocket_t so4,void ** ipaddrs,int * size,int * nifs)11112198SEiji.Ota@Sun.COM rdsv3_do_ip_ioctl(ksocket_t so4, void **ipaddrs, int *size, int *nifs)
11212198SEiji.Ota@Sun.COM {
11312198SEiji.Ota@Sun.COM struct lifnum lifn;
11412198SEiji.Ota@Sun.COM struct lifconf lifc;
11512198SEiji.Ota@Sun.COM struct lifreq *lp, *rlp, lifr;
11612198SEiji.Ota@Sun.COM int rval = 0;
11712198SEiji.Ota@Sun.COM int numifs;
11812198SEiji.Ota@Sun.COM int bufsize, rbufsize;
11912198SEiji.Ota@Sun.COM void *buf, *rbuf;
12012198SEiji.Ota@Sun.COM int i, j, n, rc;
12112198SEiji.Ota@Sun.COM
12212198SEiji.Ota@Sun.COM *ipaddrs = NULL;
12312198SEiji.Ota@Sun.COM *size = 0;
12412198SEiji.Ota@Sun.COM *nifs = 0;
12512198SEiji.Ota@Sun.COM
12612198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_do_ip_ioctl", "Enter");
12712198SEiji.Ota@Sun.COM
12812198SEiji.Ota@Sun.COM retry_count:
12912198SEiji.Ota@Sun.COM /* snapshot the current number of interfaces */
13012198SEiji.Ota@Sun.COM lifn.lifn_family = PF_UNSPEC;
13112198SEiji.Ota@Sun.COM lifn.lifn_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES;
13212198SEiji.Ota@Sun.COM lifn.lifn_count = 0;
13312198SEiji.Ota@Sun.COM rval = ksocket_ioctl(so4, SIOCGLIFNUM, (intptr_t)&lifn, &rval,
13412198SEiji.Ota@Sun.COM CRED());
13512198SEiji.Ota@Sun.COM if (rval != 0) {
13612198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_do_ip_ioctl",
13712198SEiji.Ota@Sun.COM "ksocket_ioctl returned: %d", rval);
13812198SEiji.Ota@Sun.COM return (rval);
13912198SEiji.Ota@Sun.COM }
14012198SEiji.Ota@Sun.COM
14112198SEiji.Ota@Sun.COM numifs = lifn.lifn_count;
14212198SEiji.Ota@Sun.COM if (numifs <= 0) {
14312198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_do_ip_ioctl", "No interfaces found");
14412198SEiji.Ota@Sun.COM return (0);
14512198SEiji.Ota@Sun.COM }
14612198SEiji.Ota@Sun.COM
14712198SEiji.Ota@Sun.COM /* allocate extra room in case more interfaces appear */
14812198SEiji.Ota@Sun.COM numifs += 10;
14912198SEiji.Ota@Sun.COM
15012198SEiji.Ota@Sun.COM /* get the interface names and ip addresses */
15112198SEiji.Ota@Sun.COM bufsize = numifs * sizeof (struct lifreq);
15212198SEiji.Ota@Sun.COM buf = kmem_alloc(bufsize, KM_SLEEP);
15312198SEiji.Ota@Sun.COM
15412198SEiji.Ota@Sun.COM lifc.lifc_family = AF_UNSPEC;
15512198SEiji.Ota@Sun.COM lifc.lifc_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES;
15612198SEiji.Ota@Sun.COM lifc.lifc_len = bufsize;
15712198SEiji.Ota@Sun.COM lifc.lifc_buf = buf;
15812198SEiji.Ota@Sun.COM rc = ksocket_ioctl(so4, SIOCGLIFCONF, (intptr_t)&lifc, &rval, CRED());
15912198SEiji.Ota@Sun.COM if (rc != 0) {
16012198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_do_ip_ioctl", "SIOCGLIFCONF failed");
16112198SEiji.Ota@Sun.COM kmem_free(buf, bufsize);
16212198SEiji.Ota@Sun.COM return (rc);
16312198SEiji.Ota@Sun.COM }
16412198SEiji.Ota@Sun.COM /* if our extra room is used up, try again */
16512198SEiji.Ota@Sun.COM if (bufsize <= lifc.lifc_len) {
16612198SEiji.Ota@Sun.COM kmem_free(buf, bufsize);
16712198SEiji.Ota@Sun.COM buf = NULL;
16812198SEiji.Ota@Sun.COM goto retry_count;
16912198SEiji.Ota@Sun.COM }
17012198SEiji.Ota@Sun.COM /* calc actual number of ifconfs */
17112198SEiji.Ota@Sun.COM n = lifc.lifc_len / sizeof (struct lifreq);
17212198SEiji.Ota@Sun.COM
17312198SEiji.Ota@Sun.COM /*
17412198SEiji.Ota@Sun.COM * Count the RDS interfaces
17512198SEiji.Ota@Sun.COM */
17612198SEiji.Ota@Sun.COM for (i = 0, j = 0, lp = lifc.lifc_req; i < n; i++, lp++) {
17712198SEiji.Ota@Sun.COM
17812198SEiji.Ota@Sun.COM /*
17912198SEiji.Ota@Sun.COM * Copy as the SIOCGLIFFLAGS ioctl is destructive
18012198SEiji.Ota@Sun.COM */
18112198SEiji.Ota@Sun.COM bcopy(lp, &lifr, sizeof (struct lifreq));
18212198SEiji.Ota@Sun.COM /*
18312198SEiji.Ota@Sun.COM * fetch the flags using the socket of the correct family
18412198SEiji.Ota@Sun.COM */
18512198SEiji.Ota@Sun.COM switch (lifr.lifr_addr.ss_family) {
18612198SEiji.Ota@Sun.COM case AF_INET:
18712198SEiji.Ota@Sun.COM rc = ksocket_ioctl(so4, SIOCGLIFFLAGS, (intptr_t)&lifr,
18812198SEiji.Ota@Sun.COM &rval, CRED());
18912198SEiji.Ota@Sun.COM break;
19012198SEiji.Ota@Sun.COM default:
19112198SEiji.Ota@Sun.COM continue;
19212198SEiji.Ota@Sun.COM }
19312198SEiji.Ota@Sun.COM
19412198SEiji.Ota@Sun.COM if (rc != 0) continue;
19512198SEiji.Ota@Sun.COM
19612198SEiji.Ota@Sun.COM /*
19712198SEiji.Ota@Sun.COM * If we got the flags, skip uninteresting
19812198SEiji.Ota@Sun.COM * interfaces based on flags
19912198SEiji.Ota@Sun.COM */
20012198SEiji.Ota@Sun.COM if ((lifr.lifr_flags & IFF_UP) != IFF_UP)
20112198SEiji.Ota@Sun.COM continue;
20212198SEiji.Ota@Sun.COM if (lifr.lifr_flags &
20312198SEiji.Ota@Sun.COM (IFF_ANYCAST|IFF_NOLOCAL|IFF_DEPRECATED))
20412198SEiji.Ota@Sun.COM continue;
20512198SEiji.Ota@Sun.COM if (!rdsv3_capable_interface(&lifr))
20612198SEiji.Ota@Sun.COM continue;
20712198SEiji.Ota@Sun.COM j++;
20812198SEiji.Ota@Sun.COM }
20912198SEiji.Ota@Sun.COM
21012198SEiji.Ota@Sun.COM if (j <= 0) {
21112198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_do_ip_ioctl", "No RDS interfaces");
21212198SEiji.Ota@Sun.COM kmem_free(buf, bufsize);
21312198SEiji.Ota@Sun.COM return (rval);
21412198SEiji.Ota@Sun.COM }
21512198SEiji.Ota@Sun.COM
21612198SEiji.Ota@Sun.COM numifs = j;
21712198SEiji.Ota@Sun.COM
21812198SEiji.Ota@Sun.COM /* This is the buffer we pass back */
21912198SEiji.Ota@Sun.COM rbufsize = numifs * sizeof (struct lifreq);
22012198SEiji.Ota@Sun.COM rbuf = kmem_alloc(rbufsize, KM_SLEEP);
22112198SEiji.Ota@Sun.COM rlp = (struct lifreq *)rbuf;
22212198SEiji.Ota@Sun.COM
22312198SEiji.Ota@Sun.COM /*
22412198SEiji.Ota@Sun.COM * Examine the array of interfaces and filter uninteresting ones
22512198SEiji.Ota@Sun.COM */
22612198SEiji.Ota@Sun.COM for (i = 0, lp = lifc.lifc_req; i < n; i++, lp++) {
22712198SEiji.Ota@Sun.COM
22812198SEiji.Ota@Sun.COM /*
22912198SEiji.Ota@Sun.COM * Copy the address as the SIOCGLIFFLAGS ioctl is destructive
23012198SEiji.Ota@Sun.COM */
23112198SEiji.Ota@Sun.COM bcopy(lp, &lifr, sizeof (struct lifreq));
23212198SEiji.Ota@Sun.COM /*
23312198SEiji.Ota@Sun.COM * fetch the flags using the socket of the correct family
23412198SEiji.Ota@Sun.COM */
23512198SEiji.Ota@Sun.COM switch (lifr.lifr_addr.ss_family) {
23612198SEiji.Ota@Sun.COM case AF_INET:
23712198SEiji.Ota@Sun.COM rc = ksocket_ioctl(so4, SIOCGLIFFLAGS, (intptr_t)&lifr,
23812198SEiji.Ota@Sun.COM &rval, CRED());
23912198SEiji.Ota@Sun.COM break;
24012198SEiji.Ota@Sun.COM default:
24112198SEiji.Ota@Sun.COM continue;
24212198SEiji.Ota@Sun.COM }
24312198SEiji.Ota@Sun.COM
24412198SEiji.Ota@Sun.COM
24512198SEiji.Ota@Sun.COM if (rc != 0) {
24612198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_do_ip_ioctl",
24712198SEiji.Ota@Sun.COM "ksocket_ioctl failed" " for %s", lifr.lifr_name);
24812198SEiji.Ota@Sun.COM continue;
24912198SEiji.Ota@Sun.COM }
25012198SEiji.Ota@Sun.COM
25112198SEiji.Ota@Sun.COM /*
25212198SEiji.Ota@Sun.COM * If we got the flags, skip uninteresting
25312198SEiji.Ota@Sun.COM * interfaces based on flags
25412198SEiji.Ota@Sun.COM */
25512198SEiji.Ota@Sun.COM if ((lifr.lifr_flags & IFF_UP) != IFF_UP)
25612198SEiji.Ota@Sun.COM continue;
25712198SEiji.Ota@Sun.COM if (lifr.lifr_flags &
25812198SEiji.Ota@Sun.COM (IFF_ANYCAST|IFF_NOLOCAL|IFF_DEPRECATED))
25912198SEiji.Ota@Sun.COM continue;
26012198SEiji.Ota@Sun.COM if (!rdsv3_capable_interface(&lifr))
26112198SEiji.Ota@Sun.COM continue;
26212198SEiji.Ota@Sun.COM
26312198SEiji.Ota@Sun.COM /* save the record */
26412198SEiji.Ota@Sun.COM bcopy(lp, rlp, sizeof (struct lifreq));
26512580SGiri.Adari@Sun.COM rlp->lifr_addr.ss_family = AF_INET_OFFLOAD;
26612198SEiji.Ota@Sun.COM rlp++;
26712198SEiji.Ota@Sun.COM }
26812198SEiji.Ota@Sun.COM
26912198SEiji.Ota@Sun.COM kmem_free(buf, bufsize);
27012198SEiji.Ota@Sun.COM
27112198SEiji.Ota@Sun.COM *ipaddrs = rbuf;
27212198SEiji.Ota@Sun.COM *size = rbufsize;
27312198SEiji.Ota@Sun.COM *nifs = numifs;
27412198SEiji.Ota@Sun.COM
27512198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_do_ip_ioctl", "Return");
27612198SEiji.Ota@Sun.COM
27712198SEiji.Ota@Sun.COM return (rval);
27812198SEiji.Ota@Sun.COM }
27912198SEiji.Ota@Sun.COM
28012198SEiji.Ota@Sun.COM /*
28112198SEiji.Ota@Sun.COM * Check if the IP interface named by `ifrp' is RDS-capable.
28212198SEiji.Ota@Sun.COM */
28312198SEiji.Ota@Sun.COM boolean_t
rdsv3_capable_interface_old(struct ifreq * ifrp)28412198SEiji.Ota@Sun.COM rdsv3_capable_interface_old(struct ifreq *ifrp)
28512198SEiji.Ota@Sun.COM {
28612198SEiji.Ota@Sun.COM char ifname[IFNAMSIZ];
28712198SEiji.Ota@Sun.COM char drv[MAXLINKNAMELEN];
28812198SEiji.Ota@Sun.COM uint_t ppa;
28912198SEiji.Ota@Sun.COM char *cp;
29012198SEiji.Ota@Sun.COM
29112198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_capable_interface_old", "Enter");
29212198SEiji.Ota@Sun.COM
29312198SEiji.Ota@Sun.COM /*
29412198SEiji.Ota@Sun.COM * Strip off the logical interface portion before getting
29512198SEiji.Ota@Sun.COM * intimate with the name.
29612198SEiji.Ota@Sun.COM */
29712198SEiji.Ota@Sun.COM (void) strlcpy(ifname, ifrp->ifr_name, IFNAMSIZ);
29812198SEiji.Ota@Sun.COM if ((cp = strchr(ifname, ':')) != NULL)
29912198SEiji.Ota@Sun.COM *cp = '\0';
30012198SEiji.Ota@Sun.COM
30112198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_capable_interface_old", "ifname: %s", ifname);
30212198SEiji.Ota@Sun.COM
30312198SEiji.Ota@Sun.COM if ((strcmp("lo0", ifname) == 0) ||
30412198SEiji.Ota@Sun.COM (strncmp("ibd", ifname, 3) == 0)) {
30512198SEiji.Ota@Sun.COM /*
30612198SEiji.Ota@Sun.COM * loopback and IB are considered RDS-capable
30712198SEiji.Ota@Sun.COM */
30812198SEiji.Ota@Sun.COM return (B_TRUE);
30912198SEiji.Ota@Sun.COM }
31012198SEiji.Ota@Sun.COM
31112198SEiji.Ota@Sun.COM return (ddi_parse(ifname, drv, &ppa) == DDI_SUCCESS &&
31212198SEiji.Ota@Sun.COM rdsv3_if_lookup_by_name(drv));
31312198SEiji.Ota@Sun.COM }
31412198SEiji.Ota@Sun.COM
31512198SEiji.Ota@Sun.COM int
rdsv3_do_ip_ioctl_old(ksocket_t so4,void ** ipaddrs,int * size,int * nifs)31612198SEiji.Ota@Sun.COM rdsv3_do_ip_ioctl_old(ksocket_t so4, void **ipaddrs, int *size, int *nifs)
31712198SEiji.Ota@Sun.COM {
31812198SEiji.Ota@Sun.COM uint_t ifn;
31912198SEiji.Ota@Sun.COM struct ifconf ifc;
32012198SEiji.Ota@Sun.COM struct ifreq *lp, *rlp, ifr;
32112198SEiji.Ota@Sun.COM int rval = 0;
32212198SEiji.Ota@Sun.COM int numifs;
32312198SEiji.Ota@Sun.COM int bufsize, rbufsize;
32412198SEiji.Ota@Sun.COM void *buf, *rbuf;
32512198SEiji.Ota@Sun.COM int i, j, n, rc;
32612198SEiji.Ota@Sun.COM
32712198SEiji.Ota@Sun.COM *ipaddrs = NULL;
32812198SEiji.Ota@Sun.COM *size = 0;
32912198SEiji.Ota@Sun.COM *nifs = 0;
33012198SEiji.Ota@Sun.COM
33112198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_do_ip_ioctl_old", "Enter");
33212198SEiji.Ota@Sun.COM
33312198SEiji.Ota@Sun.COM retry_count:
33412198SEiji.Ota@Sun.COM rval = ksocket_ioctl(so4, SIOCGIFNUM, (intptr_t)&ifn, &rval,
33512198SEiji.Ota@Sun.COM CRED());
33612198SEiji.Ota@Sun.COM if (rval != 0) {
33712198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_do_ip_ioctl_old",
33812198SEiji.Ota@Sun.COM "ksocket_ioctl(SIOCGIFNUM) returned: %d", rval);
33912198SEiji.Ota@Sun.COM return (rval);
34012198SEiji.Ota@Sun.COM }
34112198SEiji.Ota@Sun.COM
34212198SEiji.Ota@Sun.COM numifs = ifn;
34312198SEiji.Ota@Sun.COM if (numifs <= 0) {
34412198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_do_ip_ioctl_old", "No interfaces found");
34512198SEiji.Ota@Sun.COM return (0);
34612198SEiji.Ota@Sun.COM }
34712198SEiji.Ota@Sun.COM
34812198SEiji.Ota@Sun.COM /* allocate extra room in case more interfaces appear */
34912198SEiji.Ota@Sun.COM numifs += 10;
35012198SEiji.Ota@Sun.COM
35112198SEiji.Ota@Sun.COM /* get the interface names and ip addresses */
35212198SEiji.Ota@Sun.COM bufsize = numifs * sizeof (struct ifreq);
35312198SEiji.Ota@Sun.COM buf = kmem_alloc(bufsize, KM_SLEEP);
35412198SEiji.Ota@Sun.COM
35512198SEiji.Ota@Sun.COM ifc.ifc_len = bufsize;
35612198SEiji.Ota@Sun.COM ifc.ifc_buf = buf;
35712198SEiji.Ota@Sun.COM rc = ksocket_ioctl(so4, SIOCGIFCONF, (intptr_t)&ifc, &rval, CRED());
35812198SEiji.Ota@Sun.COM if (rc != 0) {
35912198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_do_ip_ioctl_old",
36012198SEiji.Ota@Sun.COM "SIOCGLIFCONF failed: %d", rc);
36112198SEiji.Ota@Sun.COM kmem_free(buf, bufsize);
36212198SEiji.Ota@Sun.COM return (rc);
36312198SEiji.Ota@Sun.COM }
36412198SEiji.Ota@Sun.COM /* if our extra room is used up, try again */
36512198SEiji.Ota@Sun.COM if (bufsize <= ifc.ifc_len) {
36612198SEiji.Ota@Sun.COM kmem_free(buf, bufsize);
36712198SEiji.Ota@Sun.COM buf = NULL;
36812198SEiji.Ota@Sun.COM goto retry_count;
36912198SEiji.Ota@Sun.COM }
37012198SEiji.Ota@Sun.COM /* calc actual number of ifconfs */
37112198SEiji.Ota@Sun.COM n = ifc.ifc_len / sizeof (struct ifreq);
37212198SEiji.Ota@Sun.COM
37312198SEiji.Ota@Sun.COM /*
37412198SEiji.Ota@Sun.COM * Count the RDS interfaces
37512198SEiji.Ota@Sun.COM */
37612198SEiji.Ota@Sun.COM for (i = 0, j = 0, lp = ifc.ifc_req; i < n; i++, lp++) {
37712198SEiji.Ota@Sun.COM
37812198SEiji.Ota@Sun.COM /*
37912198SEiji.Ota@Sun.COM * Copy as the SIOCGIFFLAGS ioctl is destructive
38012198SEiji.Ota@Sun.COM */
38112198SEiji.Ota@Sun.COM bcopy(lp, &ifr, sizeof (struct ifreq));
38212198SEiji.Ota@Sun.COM /*
38312198SEiji.Ota@Sun.COM * fetch the flags using the socket of the correct family
38412198SEiji.Ota@Sun.COM */
38512198SEiji.Ota@Sun.COM switch (ifr.ifr_addr.sa_family) {
38612198SEiji.Ota@Sun.COM case AF_INET:
38712198SEiji.Ota@Sun.COM rc = ksocket_ioctl(so4, SIOCGIFFLAGS, (intptr_t)&ifr,
38812198SEiji.Ota@Sun.COM &rval, CRED());
38912198SEiji.Ota@Sun.COM break;
39012198SEiji.Ota@Sun.COM default:
39112198SEiji.Ota@Sun.COM continue;
39212198SEiji.Ota@Sun.COM }
39312198SEiji.Ota@Sun.COM
39412198SEiji.Ota@Sun.COM if (rc != 0) continue;
39512198SEiji.Ota@Sun.COM
39612198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_do_ip_ioctl_old",
39712198SEiji.Ota@Sun.COM "1. ifr_name: %s, flags: %d", ifr.ifr_name,
39812198SEiji.Ota@Sun.COM (ushort_t)ifr.ifr_flags);
39912198SEiji.Ota@Sun.COM
40012198SEiji.Ota@Sun.COM /*
40112198SEiji.Ota@Sun.COM * If we got the flags, skip uninteresting
40212198SEiji.Ota@Sun.COM * interfaces based on flags
40312198SEiji.Ota@Sun.COM */
40412198SEiji.Ota@Sun.COM if ((((ushort_t)ifr.ifr_flags) & IFF_UP) != IFF_UP)
40512198SEiji.Ota@Sun.COM continue;
40612198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_do_ip_ioctl_old",
40712198SEiji.Ota@Sun.COM "2. ifr_name: %s, flags: %d", ifr.ifr_name,
40812198SEiji.Ota@Sun.COM (ushort_t)ifr.ifr_flags);
40912198SEiji.Ota@Sun.COM if (((ushort_t)ifr.ifr_flags) &
41012198SEiji.Ota@Sun.COM (IFF_ANYCAST|IFF_NOLOCAL|IFF_DEPRECATED))
41112198SEiji.Ota@Sun.COM continue;
41212198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_do_ip_ioctl_old",
41312198SEiji.Ota@Sun.COM "3. ifr_name: %s, flags: %d", ifr.ifr_name,
41412198SEiji.Ota@Sun.COM (ushort_t)ifr.ifr_flags);
41512198SEiji.Ota@Sun.COM if (!rdsv3_capable_interface_old(&ifr))
41612198SEiji.Ota@Sun.COM continue;
41712198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_do_ip_ioctl_old",
41812198SEiji.Ota@Sun.COM "4. ifr_name: %s, flags: %d", ifr.ifr_name,
41912198SEiji.Ota@Sun.COM (ushort_t)ifr.ifr_flags);
42012198SEiji.Ota@Sun.COM j++;
42112198SEiji.Ota@Sun.COM }
42212198SEiji.Ota@Sun.COM
42312198SEiji.Ota@Sun.COM if (j <= 0) {
42412198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_do_ip_ioctl_old", "No RDS interfaces");
42512198SEiji.Ota@Sun.COM kmem_free(buf, bufsize);
42612198SEiji.Ota@Sun.COM return (rval);
42712198SEiji.Ota@Sun.COM }
42812198SEiji.Ota@Sun.COM
42912198SEiji.Ota@Sun.COM numifs = j;
43012198SEiji.Ota@Sun.COM
43112198SEiji.Ota@Sun.COM /* This is the buffer we pass back */
43212198SEiji.Ota@Sun.COM rbufsize = numifs * sizeof (struct ifreq);
43312198SEiji.Ota@Sun.COM rbuf = kmem_alloc(rbufsize, KM_SLEEP);
43412198SEiji.Ota@Sun.COM rlp = (struct ifreq *)rbuf;
43512198SEiji.Ota@Sun.COM
43612198SEiji.Ota@Sun.COM /*
43712198SEiji.Ota@Sun.COM * Examine the array of interfaces and filter uninteresting ones
43812198SEiji.Ota@Sun.COM */
43912198SEiji.Ota@Sun.COM for (i = 0, lp = ifc.ifc_req; i < n; i++, lp++) {
44012198SEiji.Ota@Sun.COM
44112198SEiji.Ota@Sun.COM /*
44212198SEiji.Ota@Sun.COM * Copy the address as the SIOCGIFFLAGS ioctl is destructive
44312198SEiji.Ota@Sun.COM */
44412198SEiji.Ota@Sun.COM bcopy(lp, &ifr, sizeof (struct ifreq));
44512198SEiji.Ota@Sun.COM /*
44612198SEiji.Ota@Sun.COM * fetch the flags using the socket of the correct family
44712198SEiji.Ota@Sun.COM */
44812198SEiji.Ota@Sun.COM switch (ifr.ifr_addr.sa_family) {
44912198SEiji.Ota@Sun.COM case AF_INET:
45012198SEiji.Ota@Sun.COM rc = ksocket_ioctl(so4, SIOCGIFFLAGS, (intptr_t)&ifr,
45112198SEiji.Ota@Sun.COM &rval, CRED());
45212198SEiji.Ota@Sun.COM break;
45312198SEiji.Ota@Sun.COM default:
45412198SEiji.Ota@Sun.COM continue;
45512198SEiji.Ota@Sun.COM }
45612198SEiji.Ota@Sun.COM
45712198SEiji.Ota@Sun.COM
45812198SEiji.Ota@Sun.COM if (rc != 0) {
45912198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_do_ip_ioctl_old",
46012198SEiji.Ota@Sun.COM "ksocket_ioctl failed: %d for %s",
46112198SEiji.Ota@Sun.COM rc, ifr.ifr_name);
46212198SEiji.Ota@Sun.COM continue;
46312198SEiji.Ota@Sun.COM }
46412198SEiji.Ota@Sun.COM
46512198SEiji.Ota@Sun.COM /*
46612198SEiji.Ota@Sun.COM * If we got the flags, skip uninteresting
46712198SEiji.Ota@Sun.COM * interfaces based on flags
46812198SEiji.Ota@Sun.COM */
46912198SEiji.Ota@Sun.COM if ((((ushort_t)ifr.ifr_flags) & IFF_UP) != IFF_UP)
47012198SEiji.Ota@Sun.COM continue;
47112198SEiji.Ota@Sun.COM if (((ushort_t)ifr.ifr_flags) &
47212198SEiji.Ota@Sun.COM (IFF_ANYCAST|IFF_NOLOCAL|IFF_DEPRECATED))
47312198SEiji.Ota@Sun.COM continue;
47412198SEiji.Ota@Sun.COM if (!rdsv3_capable_interface_old(&ifr))
47512198SEiji.Ota@Sun.COM continue;
47612198SEiji.Ota@Sun.COM
47712198SEiji.Ota@Sun.COM /* save the record */
47812198SEiji.Ota@Sun.COM bcopy(lp, rlp, sizeof (struct ifreq));
47912580SGiri.Adari@Sun.COM rlp->ifr_addr.sa_family = AF_INET_OFFLOAD;
48012198SEiji.Ota@Sun.COM rlp++;
48112198SEiji.Ota@Sun.COM }
48212198SEiji.Ota@Sun.COM
48312198SEiji.Ota@Sun.COM kmem_free(buf, bufsize);
48412198SEiji.Ota@Sun.COM
48512198SEiji.Ota@Sun.COM *ipaddrs = rbuf;
48612198SEiji.Ota@Sun.COM *size = rbufsize;
48712198SEiji.Ota@Sun.COM *nifs = numifs;
48812198SEiji.Ota@Sun.COM
48912198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_do_ip_ioctl_old", "Return");
49012198SEiji.Ota@Sun.COM
49112198SEiji.Ota@Sun.COM return (rval);
49212198SEiji.Ota@Sun.COM }
49312198SEiji.Ota@Sun.COM
49412198SEiji.Ota@Sun.COM boolean_t
rdsv3_isloopback(ipaddr_t addr)49512198SEiji.Ota@Sun.COM rdsv3_isloopback(ipaddr_t addr)
49612198SEiji.Ota@Sun.COM {
49712198SEiji.Ota@Sun.COM ip_stack_t *ipst;
49812198SEiji.Ota@Sun.COM
49912198SEiji.Ota@Sun.COM ipst = netstack_find_by_zoneid(GLOBAL_ZONEID)->netstack_ip;
50012198SEiji.Ota@Sun.COM ASSERT(ipst != NULL);
50112198SEiji.Ota@Sun.COM if (ip_type_v4(addr, ipst) != IRE_LOOPBACK) {
50212198SEiji.Ota@Sun.COM netstack_rele(ipst->ips_netstack);
50312198SEiji.Ota@Sun.COM return (B_FALSE);
50412198SEiji.Ota@Sun.COM }
50512198SEiji.Ota@Sun.COM netstack_rele(ipst->ips_netstack);
50612198SEiji.Ota@Sun.COM return (B_TRUE);
50712198SEiji.Ota@Sun.COM }
50812198SEiji.Ota@Sun.COM
50912198SEiji.Ota@Sun.COM /*
51012198SEiji.Ota@Sun.COM * Work Queue Implementation
51112198SEiji.Ota@Sun.COM */
51212198SEiji.Ota@Sun.COM
51312198SEiji.Ota@Sun.COM #define RDSV3_WQ_THREAD_IDLE 0
51412198SEiji.Ota@Sun.COM #define RDSV3_WQ_THREAD_RUNNING 1
51512198SEiji.Ota@Sun.COM #define RDSV3_WQ_THREAD_FLUSHING 2
51612198SEiji.Ota@Sun.COM #define RDSV3_WQ_THREAD_EXITING 3
51712198SEiji.Ota@Sun.COM
51812198SEiji.Ota@Sun.COM /* worker thread */
51912198SEiji.Ota@Sun.COM void
rdsv3_worker_thread(void * arg)52012198SEiji.Ota@Sun.COM rdsv3_worker_thread(void *arg)
52112198SEiji.Ota@Sun.COM {
52212198SEiji.Ota@Sun.COM rdsv3_workqueue_struct_t *wq = arg;
52312198SEiji.Ota@Sun.COM rdsv3_work_t *work;
52412198SEiji.Ota@Sun.COM
52512198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_worker_thread", "Enter(wq: 0x%p)", wq);
52612198SEiji.Ota@Sun.COM
52712198SEiji.Ota@Sun.COM mutex_enter(&wq->wq_lock);
52812198SEiji.Ota@Sun.COM work = list_remove_head(&wq->wq_queue);
52912198SEiji.Ota@Sun.COM while (work) {
53012198SEiji.Ota@Sun.COM mutex_exit(&wq->wq_lock);
53112198SEiji.Ota@Sun.COM
53212198SEiji.Ota@Sun.COM /* process work */
53312198SEiji.Ota@Sun.COM work->func(work);
53412198SEiji.Ota@Sun.COM
53512198SEiji.Ota@Sun.COM mutex_enter(&wq->wq_lock);
53612198SEiji.Ota@Sun.COM work = list_remove_head(&wq->wq_queue);
53712198SEiji.Ota@Sun.COM }
53812198SEiji.Ota@Sun.COM
53912198SEiji.Ota@Sun.COM /* No more work, go home, until called again */
54012198SEiji.Ota@Sun.COM if (wq->wq_state != RDSV3_WQ_THREAD_EXITING) {
54112198SEiji.Ota@Sun.COM wq->wq_state = RDSV3_WQ_THREAD_IDLE;
54212198SEiji.Ota@Sun.COM }
54312198SEiji.Ota@Sun.COM mutex_exit(&wq->wq_lock);
54412198SEiji.Ota@Sun.COM
54512198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_worker_thread", "Return(wq: 0x%p)", wq);
54612198SEiji.Ota@Sun.COM }
54712198SEiji.Ota@Sun.COM
54812198SEiji.Ota@Sun.COM /* XXX */
54912198SEiji.Ota@Sun.COM void
rdsv3_flush_workqueue(rdsv3_workqueue_struct_t * wq)55012198SEiji.Ota@Sun.COM rdsv3_flush_workqueue(rdsv3_workqueue_struct_t *wq)
55112198SEiji.Ota@Sun.COM {
55212198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_flush_workqueue", "Enter(wq: %p)", wq);
55312198SEiji.Ota@Sun.COM
55412198SEiji.Ota@Sun.COM mutex_enter(&wq->wq_lock);
55512198SEiji.Ota@Sun.COM switch (wq->wq_state) {
55612198SEiji.Ota@Sun.COM case RDSV3_WQ_THREAD_IDLE:
55712198SEiji.Ota@Sun.COM /* nothing to do */
55812198SEiji.Ota@Sun.COM ASSERT(list_is_empty(&wq->wq_queue));
55912198SEiji.Ota@Sun.COM break;
56012198SEiji.Ota@Sun.COM
56112198SEiji.Ota@Sun.COM case RDSV3_WQ_THREAD_RUNNING:
56212198SEiji.Ota@Sun.COM wq->wq_state = RDSV3_WQ_THREAD_FLUSHING;
56312198SEiji.Ota@Sun.COM /* FALLTHRU */
56412198SEiji.Ota@Sun.COM case RDSV3_WQ_THREAD_FLUSHING:
56512198SEiji.Ota@Sun.COM /* already flushing, wait until the flushing is complete */
56612198SEiji.Ota@Sun.COM do {
56712198SEiji.Ota@Sun.COM mutex_exit(&wq->wq_lock);
56812198SEiji.Ota@Sun.COM delay(drv_usectohz(1000000));
56912198SEiji.Ota@Sun.COM mutex_enter(&wq->wq_lock);
57012198SEiji.Ota@Sun.COM } while (wq->wq_state == RDSV3_WQ_THREAD_FLUSHING);
57112198SEiji.Ota@Sun.COM break;
57212198SEiji.Ota@Sun.COM case RDSV3_WQ_THREAD_EXITING:
57312198SEiji.Ota@Sun.COM mutex_exit(&wq->wq_lock);
57412198SEiji.Ota@Sun.COM rdsv3_worker_thread(wq);
57512198SEiji.Ota@Sun.COM return;
57612198SEiji.Ota@Sun.COM }
57712198SEiji.Ota@Sun.COM mutex_exit(&wq->wq_lock);
57812198SEiji.Ota@Sun.COM
57912198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_flush_workqueue", "Return(wq: %p)", wq);
58012198SEiji.Ota@Sun.COM }
58112198SEiji.Ota@Sun.COM
58212198SEiji.Ota@Sun.COM void
rdsv3_queue_work(rdsv3_workqueue_struct_t * wq,rdsv3_work_t * wp)58312198SEiji.Ota@Sun.COM rdsv3_queue_work(rdsv3_workqueue_struct_t *wq, rdsv3_work_t *wp)
58412198SEiji.Ota@Sun.COM {
58512198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_queue_work", "Enter(wq: %p, wp: %p)", wq, wp);
58612198SEiji.Ota@Sun.COM
58712198SEiji.Ota@Sun.COM mutex_enter(&wq->wq_lock);
58812198SEiji.Ota@Sun.COM
58912198SEiji.Ota@Sun.COM if (list_link_active(&wp->work_item)) {
59012198SEiji.Ota@Sun.COM /* This is already in the queue, ignore this call */
59112198SEiji.Ota@Sun.COM mutex_exit(&wq->wq_lock);
59212198SEiji.Ota@Sun.COM RDSV3_DPRINTF3("rdsv3_queue_work", "already queued: %p", wp);
59312198SEiji.Ota@Sun.COM return;
59412198SEiji.Ota@Sun.COM }
59512198SEiji.Ota@Sun.COM
59612198SEiji.Ota@Sun.COM switch (wq->wq_state) {
59712198SEiji.Ota@Sun.COM case RDSV3_WQ_THREAD_RUNNING:
59812198SEiji.Ota@Sun.COM list_insert_tail(&wq->wq_queue, wp);
59912198SEiji.Ota@Sun.COM mutex_exit(&wq->wq_lock);
60012198SEiji.Ota@Sun.COM break;
60112198SEiji.Ota@Sun.COM
60212198SEiji.Ota@Sun.COM case RDSV3_WQ_THREAD_FLUSHING:
60312198SEiji.Ota@Sun.COM do {
60412198SEiji.Ota@Sun.COM mutex_exit(&wq->wq_lock);
60512198SEiji.Ota@Sun.COM delay(drv_usectohz(1000000));
60612198SEiji.Ota@Sun.COM mutex_enter(&wq->wq_lock);
60712198SEiji.Ota@Sun.COM } while (wq->wq_state == RDSV3_WQ_THREAD_FLUSHING);
60812198SEiji.Ota@Sun.COM
60912198SEiji.Ota@Sun.COM if (wq->wq_state == RDSV3_WQ_THREAD_RUNNING) {
61012198SEiji.Ota@Sun.COM list_insert_tail(&wq->wq_queue, wp);
61112198SEiji.Ota@Sun.COM mutex_exit(&wq->wq_lock);
61212198SEiji.Ota@Sun.COM break;
61312198SEiji.Ota@Sun.COM }
61412198SEiji.Ota@Sun.COM /* FALLTHRU */
61512198SEiji.Ota@Sun.COM
61612198SEiji.Ota@Sun.COM case RDSV3_WQ_THREAD_IDLE:
61712198SEiji.Ota@Sun.COM list_insert_tail(&wq->wq_queue, wp);
61812198SEiji.Ota@Sun.COM wq->wq_state = RDSV3_WQ_THREAD_RUNNING;
61912198SEiji.Ota@Sun.COM mutex_exit(&wq->wq_lock);
62012198SEiji.Ota@Sun.COM
62112198SEiji.Ota@Sun.COM (void) ddi_taskq_dispatch(rdsv3_taskq, rdsv3_worker_thread, wq,
62212198SEiji.Ota@Sun.COM DDI_SLEEP);
62312198SEiji.Ota@Sun.COM break;
62412198SEiji.Ota@Sun.COM
62512198SEiji.Ota@Sun.COM case RDSV3_WQ_THREAD_EXITING:
62612198SEiji.Ota@Sun.COM mutex_exit(&wq->wq_lock);
62712198SEiji.Ota@Sun.COM break;
62812198SEiji.Ota@Sun.COM }
62912198SEiji.Ota@Sun.COM
63012198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_queue_work", "Return(wq: %p, wp: %p)", wq, wp);
63112198SEiji.Ota@Sun.COM }
63212198SEiji.Ota@Sun.COM
63312198SEiji.Ota@Sun.COM /* timeout handler for delayed work queuing */
63412198SEiji.Ota@Sun.COM void
rdsv3_work_timeout_handler(void * arg)63512198SEiji.Ota@Sun.COM rdsv3_work_timeout_handler(void *arg)
63612198SEiji.Ota@Sun.COM {
63712198SEiji.Ota@Sun.COM rdsv3_delayed_work_t *dwp = (rdsv3_delayed_work_t *)arg;
63812198SEiji.Ota@Sun.COM
63912198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_work_timeout_handler",
64012198SEiji.Ota@Sun.COM "Enter(wq: %p, wp: %p)", dwp->wq, &dwp->work);
64112198SEiji.Ota@Sun.COM
64212198SEiji.Ota@Sun.COM mutex_enter(&dwp->lock);
64312198SEiji.Ota@Sun.COM dwp->timeid = 0;
64412198SEiji.Ota@Sun.COM mutex_exit(&dwp->lock);
64512198SEiji.Ota@Sun.COM
64612198SEiji.Ota@Sun.COM mutex_enter(&dwp->wq->wq_lock);
64712198SEiji.Ota@Sun.COM dwp->wq->wq_pending--;
64812198SEiji.Ota@Sun.COM if (dwp->wq->wq_state == RDSV3_WQ_THREAD_EXITING) {
64912198SEiji.Ota@Sun.COM mutex_exit(&dwp->wq->wq_lock);
65012198SEiji.Ota@Sun.COM return;
65112198SEiji.Ota@Sun.COM }
65212198SEiji.Ota@Sun.COM mutex_exit(&dwp->wq->wq_lock);
65312198SEiji.Ota@Sun.COM
65412198SEiji.Ota@Sun.COM rdsv3_queue_work(dwp->wq, &dwp->work);
65512198SEiji.Ota@Sun.COM
65612198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_work_timeout_handler",
65712198SEiji.Ota@Sun.COM "Return(wq: %p, wp: %p)", dwp->wq, &dwp->work);
65812198SEiji.Ota@Sun.COM }
65912198SEiji.Ota@Sun.COM
66012198SEiji.Ota@Sun.COM void
rdsv3_queue_delayed_work(rdsv3_workqueue_struct_t * wq,rdsv3_delayed_work_t * dwp,uint_t delay)66112198SEiji.Ota@Sun.COM rdsv3_queue_delayed_work(rdsv3_workqueue_struct_t *wq,
66212198SEiji.Ota@Sun.COM rdsv3_delayed_work_t *dwp, uint_t delay)
66312198SEiji.Ota@Sun.COM {
66412198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_queue_delayed_work",
66512198SEiji.Ota@Sun.COM "Enter(wq: %p, wp: %p)", wq, dwp);
66612198SEiji.Ota@Sun.COM
66712198SEiji.Ota@Sun.COM if (delay == 0) {
66812198SEiji.Ota@Sun.COM rdsv3_queue_work(wq, &dwp->work);
66912198SEiji.Ota@Sun.COM return;
67012198SEiji.Ota@Sun.COM }
67112198SEiji.Ota@Sun.COM
67212198SEiji.Ota@Sun.COM mutex_enter(&wq->wq_lock);
67312198SEiji.Ota@Sun.COM if (wq->wq_state == RDSV3_WQ_THREAD_EXITING) {
67412198SEiji.Ota@Sun.COM mutex_exit(&wq->wq_lock);
67512198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_queue_delayed_work",
67612198SEiji.Ota@Sun.COM "WQ exiting - don't queue (wq: %p, wp: %p)", wq, dwp);
67712198SEiji.Ota@Sun.COM return;
67812198SEiji.Ota@Sun.COM }
67912198SEiji.Ota@Sun.COM wq->wq_pending++;
68012198SEiji.Ota@Sun.COM mutex_exit(&wq->wq_lock);
68112198SEiji.Ota@Sun.COM
68212198SEiji.Ota@Sun.COM mutex_enter(&dwp->lock);
68312198SEiji.Ota@Sun.COM if (dwp->timeid == 0) {
68412198SEiji.Ota@Sun.COM dwp->wq = wq;
68512198SEiji.Ota@Sun.COM dwp->timeid = timeout(rdsv3_work_timeout_handler, dwp,
68612198SEiji.Ota@Sun.COM jiffies + (delay * rdsv3_one_sec_in_hz));
68712198SEiji.Ota@Sun.COM mutex_exit(&dwp->lock);
68812198SEiji.Ota@Sun.COM } else {
68912198SEiji.Ota@Sun.COM mutex_exit(&dwp->lock);
69012198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_queue_delayed_work", "Already queued: %p",
69112198SEiji.Ota@Sun.COM dwp);
69212198SEiji.Ota@Sun.COM mutex_enter(&wq->wq_lock);
69312198SEiji.Ota@Sun.COM wq->wq_pending--;
69412198SEiji.Ota@Sun.COM mutex_exit(&wq->wq_lock);
69512198SEiji.Ota@Sun.COM }
69612198SEiji.Ota@Sun.COM
69712198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_queue_delayed_work",
69812198SEiji.Ota@Sun.COM "Return(wq: %p, wp: %p)", wq, dwp);
69912198SEiji.Ota@Sun.COM }
70012198SEiji.Ota@Sun.COM
70112198SEiji.Ota@Sun.COM void
rdsv3_cancel_delayed_work(rdsv3_delayed_work_t * dwp)70212198SEiji.Ota@Sun.COM rdsv3_cancel_delayed_work(rdsv3_delayed_work_t *dwp)
70312198SEiji.Ota@Sun.COM {
70412198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_cancel_delayed_work",
70512198SEiji.Ota@Sun.COM "Enter(wq: %p, dwp: %p)", dwp->wq, dwp);
70612198SEiji.Ota@Sun.COM
70712198SEiji.Ota@Sun.COM mutex_enter(&dwp->lock);
70812198SEiji.Ota@Sun.COM if (dwp->timeid != 0) {
70912198SEiji.Ota@Sun.COM (void) untimeout(dwp->timeid);
71012198SEiji.Ota@Sun.COM dwp->timeid = 0;
71112198SEiji.Ota@Sun.COM } else {
71212198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_cancel_delayed_work",
71312198SEiji.Ota@Sun.COM "Nothing to cancel (wq: %p, dwp: %p)", dwp->wq, dwp);
71412198SEiji.Ota@Sun.COM mutex_exit(&dwp->lock);
71512198SEiji.Ota@Sun.COM return;
71612198SEiji.Ota@Sun.COM }
71712198SEiji.Ota@Sun.COM mutex_exit(&dwp->lock);
71812198SEiji.Ota@Sun.COM
71912198SEiji.Ota@Sun.COM mutex_enter(&dwp->wq->wq_lock);
72012198SEiji.Ota@Sun.COM dwp->wq->wq_pending--;
72112198SEiji.Ota@Sun.COM mutex_exit(&dwp->wq->wq_lock);
72212198SEiji.Ota@Sun.COM
72312198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_cancel_delayed_work",
72412198SEiji.Ota@Sun.COM "Return(wq: %p, dwp: %p)", dwp->wq, dwp);
72512198SEiji.Ota@Sun.COM }
72612198SEiji.Ota@Sun.COM
72712198SEiji.Ota@Sun.COM void
rdsv3_destroy_task_workqueue(rdsv3_workqueue_struct_t * wq)72812198SEiji.Ota@Sun.COM rdsv3_destroy_task_workqueue(rdsv3_workqueue_struct_t *wq)
72912198SEiji.Ota@Sun.COM {
73012198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_destroy_workqueue", "Enter");
73112198SEiji.Ota@Sun.COM
73212198SEiji.Ota@Sun.COM ASSERT(wq);
73312198SEiji.Ota@Sun.COM
73412198SEiji.Ota@Sun.COM mutex_enter(&wq->wq_lock);
73512198SEiji.Ota@Sun.COM wq->wq_state = RDSV3_WQ_THREAD_EXITING;
73612198SEiji.Ota@Sun.COM
73712198SEiji.Ota@Sun.COM while (wq->wq_pending > 0) {
73812198SEiji.Ota@Sun.COM mutex_exit(&wq->wq_lock);
73912198SEiji.Ota@Sun.COM delay(drv_usectohz(1000000));
74012198SEiji.Ota@Sun.COM mutex_enter(&wq->wq_lock);
74112198SEiji.Ota@Sun.COM };
74212198SEiji.Ota@Sun.COM mutex_exit(&wq->wq_lock);
74312198SEiji.Ota@Sun.COM
74412198SEiji.Ota@Sun.COM rdsv3_flush_workqueue(wq);
74512198SEiji.Ota@Sun.COM
74612198SEiji.Ota@Sun.COM list_destroy(&wq->wq_queue);
74712198SEiji.Ota@Sun.COM mutex_destroy(&wq->wq_lock);
74812198SEiji.Ota@Sun.COM kmem_free(wq, sizeof (rdsv3_workqueue_struct_t));
74912198SEiji.Ota@Sun.COM
75012198SEiji.Ota@Sun.COM ASSERT(rdsv3_taskq);
75112198SEiji.Ota@Sun.COM ddi_taskq_destroy(rdsv3_taskq);
75212198SEiji.Ota@Sun.COM
75312198SEiji.Ota@Sun.COM wq = NULL;
75412198SEiji.Ota@Sun.COM rdsv3_taskq = NULL;
75512198SEiji.Ota@Sun.COM
75612198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_destroy_workqueue", "Return");
75712198SEiji.Ota@Sun.COM }
75812198SEiji.Ota@Sun.COM
75912198SEiji.Ota@Sun.COM /* ARGSUSED */
76012198SEiji.Ota@Sun.COM void
rdsv3_rdma_init_worker(struct rdsv3_work_s * work)76112198SEiji.Ota@Sun.COM rdsv3_rdma_init_worker(struct rdsv3_work_s *work)
76212198SEiji.Ota@Sun.COM {
76312198SEiji.Ota@Sun.COM rdsv3_rdma_init();
76412198SEiji.Ota@Sun.COM }
76512198SEiji.Ota@Sun.COM
76612676SEiji.Ota@Sun.COM #define RDSV3_NUM_TASKQ_THREADS 1
76712198SEiji.Ota@Sun.COM rdsv3_workqueue_struct_t *
rdsv3_create_task_workqueue(char * name)76812198SEiji.Ota@Sun.COM rdsv3_create_task_workqueue(char *name)
76912198SEiji.Ota@Sun.COM {
77012198SEiji.Ota@Sun.COM rdsv3_workqueue_struct_t *wq;
77112198SEiji.Ota@Sun.COM
77212198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("create_singlethread_workqueue", "Enter (dip: %p)",
77312198SEiji.Ota@Sun.COM rdsv3_dev_info);
77412198SEiji.Ota@Sun.COM
77512198SEiji.Ota@Sun.COM rdsv3_taskq = ddi_taskq_create(rdsv3_dev_info, name,
77612198SEiji.Ota@Sun.COM RDSV3_NUM_TASKQ_THREADS, TASKQ_DEFAULTPRI, 0);
77712198SEiji.Ota@Sun.COM if (rdsv3_taskq == NULL) {
77812320SGiri.Adari@Sun.COM RDSV3_DPRINTF2(__FILE__,
77912198SEiji.Ota@Sun.COM "ddi_taskq_create failed for rdsv3_taskq");
78012198SEiji.Ota@Sun.COM return (NULL);
78112198SEiji.Ota@Sun.COM }
78212198SEiji.Ota@Sun.COM
78312198SEiji.Ota@Sun.COM wq = kmem_zalloc(sizeof (rdsv3_workqueue_struct_t), KM_NOSLEEP);
78412198SEiji.Ota@Sun.COM if (wq == NULL) {
78512320SGiri.Adari@Sun.COM RDSV3_DPRINTF2(__FILE__, "kmem_zalloc failed for wq");
78612198SEiji.Ota@Sun.COM ddi_taskq_destroy(rdsv3_taskq);
78712198SEiji.Ota@Sun.COM return (NULL);
78812198SEiji.Ota@Sun.COM }
78912198SEiji.Ota@Sun.COM
79012198SEiji.Ota@Sun.COM list_create(&wq->wq_queue, sizeof (struct rdsv3_work_s),
79112198SEiji.Ota@Sun.COM offsetof(struct rdsv3_work_s, work_item));
79212198SEiji.Ota@Sun.COM mutex_init(&wq->wq_lock, NULL, MUTEX_DRIVER, NULL);
79312198SEiji.Ota@Sun.COM wq->wq_state = RDSV3_WQ_THREAD_IDLE;
79412198SEiji.Ota@Sun.COM wq->wq_pending = 0;
79512198SEiji.Ota@Sun.COM rdsv3_one_sec_in_hz = drv_usectohz(1000000);
79612198SEiji.Ota@Sun.COM
79712198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("create_singlethread_workqueue", "Return");
79812198SEiji.Ota@Sun.COM
79912198SEiji.Ota@Sun.COM return (wq);
80012198SEiji.Ota@Sun.COM }
80112198SEiji.Ota@Sun.COM
80212198SEiji.Ota@Sun.COM /*
80312198SEiji.Ota@Sun.COM * Implementation for struct sock
80412198SEiji.Ota@Sun.COM */
80512198SEiji.Ota@Sun.COM
80612198SEiji.Ota@Sun.COM void
rdsv3_sock_exit_data(struct rsock * sk)80712198SEiji.Ota@Sun.COM rdsv3_sock_exit_data(struct rsock *sk)
80812198SEiji.Ota@Sun.COM {
80912198SEiji.Ota@Sun.COM struct rdsv3_sock *rs = sk->sk_protinfo;
81012198SEiji.Ota@Sun.COM
81112198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_sock_exit_data", "rs: %p sk: %p", rs, sk);
81212198SEiji.Ota@Sun.COM
81312198SEiji.Ota@Sun.COM ASSERT(rs != NULL);
81412198SEiji.Ota@Sun.COM ASSERT(rdsv3_sk_sock_flag(sk, SOCK_DEAD));
81512198SEiji.Ota@Sun.COM
81612198SEiji.Ota@Sun.COM rs->rs_sk = NULL;
81712198SEiji.Ota@Sun.COM
81812198SEiji.Ota@Sun.COM list_destroy(&rs->rs_send_queue);
81912198SEiji.Ota@Sun.COM list_destroy(&rs->rs_notify_queue);
82012198SEiji.Ota@Sun.COM list_destroy(&rs->rs_recv_queue);
82112198SEiji.Ota@Sun.COM
82212198SEiji.Ota@Sun.COM rw_destroy(&rs->rs_recv_lock);
82312198SEiji.Ota@Sun.COM mutex_destroy(&rs->rs_lock);
82412198SEiji.Ota@Sun.COM
82512198SEiji.Ota@Sun.COM mutex_destroy(&rs->rs_rdma_lock);
82612198SEiji.Ota@Sun.COM avl_destroy(&rs->rs_rdma_keys);
82712198SEiji.Ota@Sun.COM
82812676SEiji.Ota@Sun.COM mutex_destroy(&rs->rs_conn_lock);
82912676SEiji.Ota@Sun.COM mutex_destroy(&rs->rs_congested_lock);
83012676SEiji.Ota@Sun.COM cv_destroy(&rs->rs_congested_cv);
83112676SEiji.Ota@Sun.COM
83212198SEiji.Ota@Sun.COM rdsv3_exit_waitqueue(sk->sk_sleep);
83312198SEiji.Ota@Sun.COM kmem_free(sk->sk_sleep, sizeof (rdsv3_wait_queue_t));
83412198SEiji.Ota@Sun.COM mutex_destroy(&sk->sk_lock);
83512198SEiji.Ota@Sun.COM
83612198SEiji.Ota@Sun.COM kmem_cache_free(rdsv3_alloc_cache, sk);
83712198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_sock_exit_data", "rs: %p sk: %p", rs, sk);
83812198SEiji.Ota@Sun.COM }
83912198SEiji.Ota@Sun.COM
84012198SEiji.Ota@Sun.COM /* XXX - figure out right values */
84112198SEiji.Ota@Sun.COM #define RDSV3_RECV_HIWATER (256 * 1024)
84212198SEiji.Ota@Sun.COM #define RDSV3_RECV_LOWATER 128
84312198SEiji.Ota@Sun.COM #define RDSV3_XMIT_HIWATER (256 * 1024)
84412198SEiji.Ota@Sun.COM #define RDSV3_XMIT_LOWATER 1024
84512198SEiji.Ota@Sun.COM
84612198SEiji.Ota@Sun.COM struct rsock *
rdsv3_sk_alloc()84712198SEiji.Ota@Sun.COM rdsv3_sk_alloc()
84812198SEiji.Ota@Sun.COM {
84912198SEiji.Ota@Sun.COM struct rsock *sk;
85012198SEiji.Ota@Sun.COM
85112198SEiji.Ota@Sun.COM sk = kmem_cache_alloc(rdsv3_alloc_cache, KM_SLEEP);
85212198SEiji.Ota@Sun.COM if (sk == NULL) {
85312198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_create", "kmem_cache_alloc failed");
85412198SEiji.Ota@Sun.COM return (NULL);
85512198SEiji.Ota@Sun.COM }
85612198SEiji.Ota@Sun.COM
85712198SEiji.Ota@Sun.COM bzero(sk, sizeof (struct rsock) + sizeof (struct rdsv3_sock));
85812198SEiji.Ota@Sun.COM return (sk);
85912198SEiji.Ota@Sun.COM }
86012198SEiji.Ota@Sun.COM
86112198SEiji.Ota@Sun.COM void
rdsv3_sock_init_data(struct rsock * sk)86212198SEiji.Ota@Sun.COM rdsv3_sock_init_data(struct rsock *sk)
86312198SEiji.Ota@Sun.COM {
86412198SEiji.Ota@Sun.COM sk->sk_sleep = kmem_zalloc(sizeof (rdsv3_wait_queue_t), KM_SLEEP);
86512198SEiji.Ota@Sun.COM rdsv3_init_waitqueue(sk->sk_sleep);
86612198SEiji.Ota@Sun.COM
86712198SEiji.Ota@Sun.COM mutex_init(&sk->sk_lock, NULL, MUTEX_DRIVER, NULL);
86812198SEiji.Ota@Sun.COM sk->sk_refcount = 1;
86912198SEiji.Ota@Sun.COM sk->sk_protinfo = (struct rdsv3_sock *)(sk + 1);
87012198SEiji.Ota@Sun.COM sk->sk_sndbuf = RDSV3_XMIT_HIWATER;
87112198SEiji.Ota@Sun.COM sk->sk_rcvbuf = RDSV3_RECV_HIWATER;
87212198SEiji.Ota@Sun.COM }
87312198SEiji.Ota@Sun.COM
87412198SEiji.Ota@Sun.COM /*
87512198SEiji.Ota@Sun.COM * Connection cache
87612198SEiji.Ota@Sun.COM */
87712198SEiji.Ota@Sun.COM /* ARGSUSED */
87812198SEiji.Ota@Sun.COM int
rdsv3_conn_constructor(void * buf,void * arg,int kmflags)87912198SEiji.Ota@Sun.COM rdsv3_conn_constructor(void *buf, void *arg, int kmflags)
88012198SEiji.Ota@Sun.COM {
88112198SEiji.Ota@Sun.COM struct rdsv3_connection *conn = buf;
88212198SEiji.Ota@Sun.COM
88312198SEiji.Ota@Sun.COM bzero(conn, sizeof (struct rdsv3_connection));
88412198SEiji.Ota@Sun.COM
88512198SEiji.Ota@Sun.COM conn->c_next_tx_seq = 1;
88612198SEiji.Ota@Sun.COM mutex_init(&conn->c_lock, NULL, MUTEX_DRIVER, NULL);
88712198SEiji.Ota@Sun.COM mutex_init(&conn->c_send_lock, NULL, MUTEX_DRIVER, NULL);
88812676SEiji.Ota@Sun.COM conn->c_send_generation = 1;
88912676SEiji.Ota@Sun.COM conn->c_senders = 0;
89012676SEiji.Ota@Sun.COM
89112198SEiji.Ota@Sun.COM list_create(&conn->c_send_queue, sizeof (struct rdsv3_message),
89212198SEiji.Ota@Sun.COM offsetof(struct rdsv3_message, m_conn_item));
89312198SEiji.Ota@Sun.COM list_create(&conn->c_retrans, sizeof (struct rdsv3_message),
89412198SEiji.Ota@Sun.COM offsetof(struct rdsv3_message, m_conn_item));
89512198SEiji.Ota@Sun.COM return (0);
89612198SEiji.Ota@Sun.COM }
89712198SEiji.Ota@Sun.COM
89812198SEiji.Ota@Sun.COM /* ARGSUSED */
89912198SEiji.Ota@Sun.COM void
rdsv3_conn_destructor(void * buf,void * arg)90012198SEiji.Ota@Sun.COM rdsv3_conn_destructor(void *buf, void *arg)
90112198SEiji.Ota@Sun.COM {
90212198SEiji.Ota@Sun.COM struct rdsv3_connection *conn = buf;
90312198SEiji.Ota@Sun.COM
90412198SEiji.Ota@Sun.COM ASSERT(list_is_empty(&conn->c_send_queue));
90512198SEiji.Ota@Sun.COM ASSERT(list_is_empty(&conn->c_retrans));
90612198SEiji.Ota@Sun.COM list_destroy(&conn->c_send_queue);
90712198SEiji.Ota@Sun.COM list_destroy(&conn->c_retrans);
90812198SEiji.Ota@Sun.COM mutex_destroy(&conn->c_send_lock);
90912198SEiji.Ota@Sun.COM mutex_destroy(&conn->c_lock);
91012198SEiji.Ota@Sun.COM }
91112198SEiji.Ota@Sun.COM
91212198SEiji.Ota@Sun.COM int
rdsv3_conn_compare(const void * conn1,const void * conn2)91312198SEiji.Ota@Sun.COM rdsv3_conn_compare(const void *conn1, const void *conn2)
91412198SEiji.Ota@Sun.COM {
91512198SEiji.Ota@Sun.COM uint32_be_t laddr1, faddr1, laddr2, faddr2;
91612198SEiji.Ota@Sun.COM
91712198SEiji.Ota@Sun.COM laddr1 = ((rdsv3_conn_info_t *)conn1)->c_laddr;
91812198SEiji.Ota@Sun.COM laddr2 = ((struct rdsv3_connection *)conn2)->c_laddr;
91912198SEiji.Ota@Sun.COM
92012198SEiji.Ota@Sun.COM if (laddr1 == laddr2) {
92112198SEiji.Ota@Sun.COM faddr1 = ((rdsv3_conn_info_t *)conn1)->c_faddr;
92212198SEiji.Ota@Sun.COM faddr2 = ((struct rdsv3_connection *)conn2)->c_faddr;
92312198SEiji.Ota@Sun.COM if (faddr1 == faddr2)
92412198SEiji.Ota@Sun.COM return (0);
92512198SEiji.Ota@Sun.COM if (faddr1 < faddr2)
92612198SEiji.Ota@Sun.COM return (-1);
92712198SEiji.Ota@Sun.COM return (1);
92812198SEiji.Ota@Sun.COM }
92912198SEiji.Ota@Sun.COM
93012198SEiji.Ota@Sun.COM if (laddr1 < laddr2)
93112198SEiji.Ota@Sun.COM return (-1);
93212198SEiji.Ota@Sun.COM
93312198SEiji.Ota@Sun.COM return (1);
93412198SEiji.Ota@Sun.COM }
93512198SEiji.Ota@Sun.COM
93612444SGiri.Adari@Sun.COM /* rdsv3_ib_incoming cache */
93712444SGiri.Adari@Sun.COM /* ARGSUSED */
93812444SGiri.Adari@Sun.COM int
rdsv3_ib_inc_constructor(void * buf,void * arg,int kmflags)93912444SGiri.Adari@Sun.COM rdsv3_ib_inc_constructor(void *buf, void *arg, int kmflags)
94012444SGiri.Adari@Sun.COM {
94112444SGiri.Adari@Sun.COM list_create(&((struct rdsv3_ib_incoming *)buf)->ii_frags,
94212444SGiri.Adari@Sun.COM sizeof (struct rdsv3_page_frag),
94312444SGiri.Adari@Sun.COM offsetof(struct rdsv3_page_frag, f_item));
94412444SGiri.Adari@Sun.COM
94512444SGiri.Adari@Sun.COM return (0);
94612444SGiri.Adari@Sun.COM }
94712444SGiri.Adari@Sun.COM
94812444SGiri.Adari@Sun.COM /* ARGSUSED */
94912444SGiri.Adari@Sun.COM void
rdsv3_ib_inc_destructor(void * buf,void * arg)95012444SGiri.Adari@Sun.COM rdsv3_ib_inc_destructor(void *buf, void *arg)
95112444SGiri.Adari@Sun.COM {
95212444SGiri.Adari@Sun.COM list_destroy(&((struct rdsv3_ib_incoming *)buf)->ii_frags);
95312444SGiri.Adari@Sun.COM }
95412444SGiri.Adari@Sun.COM
95512444SGiri.Adari@Sun.COM /* ib_frag_slab cache */
95612444SGiri.Adari@Sun.COM /* ARGSUSED */
95712444SGiri.Adari@Sun.COM int
rdsv3_ib_frag_constructor(void * buf,void * arg,int kmflags)95812444SGiri.Adari@Sun.COM rdsv3_ib_frag_constructor(void *buf, void *arg, int kmflags)
95912444SGiri.Adari@Sun.COM {
96012444SGiri.Adari@Sun.COM struct rdsv3_page_frag *frag = (struct rdsv3_page_frag *)buf;
96112444SGiri.Adari@Sun.COM struct rdsv3_ib_device *rds_ibdev = (struct rdsv3_ib_device *)arg;
96212444SGiri.Adari@Sun.COM ibt_iov_attr_t iov_attr;
96312444SGiri.Adari@Sun.COM ibt_iov_t iov_arr[1];
96412444SGiri.Adari@Sun.COM ibt_all_wr_t wr;
96512444SGiri.Adari@Sun.COM
96612444SGiri.Adari@Sun.COM bzero(frag, sizeof (struct rdsv3_page_frag));
96712444SGiri.Adari@Sun.COM list_link_init(&frag->f_item);
96812444SGiri.Adari@Sun.COM
96912444SGiri.Adari@Sun.COM frag->f_page = kmem_alloc(PAGE_SIZE, kmflags);
97012444SGiri.Adari@Sun.COM if (frag->f_page == NULL) {
97112444SGiri.Adari@Sun.COM RDSV3_DPRINTF2("rdsv3_ib_frag_constructor",
97212444SGiri.Adari@Sun.COM "kmem_alloc for %d failed", PAGE_SIZE);
97312444SGiri.Adari@Sun.COM return (-1);
97412444SGiri.Adari@Sun.COM }
97512444SGiri.Adari@Sun.COM frag->f_offset = 0;
97612444SGiri.Adari@Sun.COM
97712444SGiri.Adari@Sun.COM iov_attr.iov_as = NULL;
97812444SGiri.Adari@Sun.COM iov_attr.iov = &iov_arr[0];
97912444SGiri.Adari@Sun.COM iov_attr.iov_buf = NULL;
98012444SGiri.Adari@Sun.COM iov_attr.iov_list_len = 1;
98112444SGiri.Adari@Sun.COM iov_attr.iov_wr_nds = 1;
98212444SGiri.Adari@Sun.COM iov_attr.iov_lso_hdr_sz = 0;
98312444SGiri.Adari@Sun.COM iov_attr.iov_flags = IBT_IOV_SLEEP | IBT_IOV_RECV;
98412444SGiri.Adari@Sun.COM
98512444SGiri.Adari@Sun.COM iov_arr[0].iov_addr = frag->f_page;
98612444SGiri.Adari@Sun.COM iov_arr[0].iov_len = PAGE_SIZE;
98712444SGiri.Adari@Sun.COM
98812444SGiri.Adari@Sun.COM wr.recv.wr_nds = 1;
98912444SGiri.Adari@Sun.COM wr.recv.wr_sgl = &frag->f_sge;
99012444SGiri.Adari@Sun.COM
99112444SGiri.Adari@Sun.COM if (ibt_map_mem_iov(ib_get_ibt_hca_hdl(rds_ibdev->dev),
99212444SGiri.Adari@Sun.COM &iov_attr, &wr, &frag->f_mapped) != IBT_SUCCESS) {
99312444SGiri.Adari@Sun.COM RDSV3_DPRINTF2("rdsv3_ib_frag_constructor",
99412444SGiri.Adari@Sun.COM "ibt_map_mem_iov failed");
99512444SGiri.Adari@Sun.COM kmem_free(frag->f_page, PAGE_SIZE);
99612444SGiri.Adari@Sun.COM return (-1);
99712444SGiri.Adari@Sun.COM }
99812444SGiri.Adari@Sun.COM
99912444SGiri.Adari@Sun.COM return (0);
100012444SGiri.Adari@Sun.COM }
100112444SGiri.Adari@Sun.COM
100212444SGiri.Adari@Sun.COM /* ARGSUSED */
100312444SGiri.Adari@Sun.COM void
rdsv3_ib_frag_destructor(void * buf,void * arg)100412444SGiri.Adari@Sun.COM rdsv3_ib_frag_destructor(void *buf, void *arg)
100512444SGiri.Adari@Sun.COM {
100612444SGiri.Adari@Sun.COM struct rdsv3_page_frag *frag = (struct rdsv3_page_frag *)buf;
100712444SGiri.Adari@Sun.COM struct rdsv3_ib_device *rds_ibdev = (struct rdsv3_ib_device *)arg;
100812444SGiri.Adari@Sun.COM
100912444SGiri.Adari@Sun.COM /* unmap the page */
101012444SGiri.Adari@Sun.COM if (ibt_unmap_mem_iov(ib_get_ibt_hca_hdl(rds_ibdev->dev),
101112444SGiri.Adari@Sun.COM frag->f_mapped) != IBT_SUCCESS)
101212444SGiri.Adari@Sun.COM RDSV3_DPRINTF2("rdsv3_ib_frag_destructor",
101312444SGiri.Adari@Sun.COM "ibt_unmap_mem_iov failed");
101412444SGiri.Adari@Sun.COM
101512444SGiri.Adari@Sun.COM /* free the page */
101612444SGiri.Adari@Sun.COM kmem_free(frag->f_page, PAGE_SIZE);
101712444SGiri.Adari@Sun.COM }
101812444SGiri.Adari@Sun.COM
101912198SEiji.Ota@Sun.COM /* loop.c */
102012198SEiji.Ota@Sun.COM extern kmutex_t loop_conns_lock;
102112198SEiji.Ota@Sun.COM extern list_t loop_conns;
102212198SEiji.Ota@Sun.COM
102312198SEiji.Ota@Sun.COM struct rdsv3_loop_connection
102412198SEiji.Ota@Sun.COM {
102512198SEiji.Ota@Sun.COM struct list_node loop_node;
102612198SEiji.Ota@Sun.COM struct rdsv3_connection *conn;
102712198SEiji.Ota@Sun.COM };
102812198SEiji.Ota@Sun.COM
102912198SEiji.Ota@Sun.COM void
rdsv3_loop_init(void)103012198SEiji.Ota@Sun.COM rdsv3_loop_init(void)
103112198SEiji.Ota@Sun.COM {
103212198SEiji.Ota@Sun.COM list_create(&loop_conns, sizeof (struct rdsv3_loop_connection),
103312198SEiji.Ota@Sun.COM offsetof(struct rdsv3_loop_connection, loop_node));
103412198SEiji.Ota@Sun.COM mutex_init(&loop_conns_lock, NULL, MUTEX_DRIVER, NULL);
103512198SEiji.Ota@Sun.COM }
103612198SEiji.Ota@Sun.COM
103712198SEiji.Ota@Sun.COM /* rdma.c */
103812198SEiji.Ota@Sun.COM /* IB Rkey is used here for comparison */
103912198SEiji.Ota@Sun.COM int
rdsv3_mr_compare(const void * mr1,const void * mr2)104012198SEiji.Ota@Sun.COM rdsv3_mr_compare(const void *mr1, const void *mr2)
104112198SEiji.Ota@Sun.COM {
104212198SEiji.Ota@Sun.COM uint32_t key1 = *(uint32_t *)mr1;
104312198SEiji.Ota@Sun.COM uint32_t key2 = ((struct rdsv3_mr *)mr2)->r_key;
104412198SEiji.Ota@Sun.COM
104512198SEiji.Ota@Sun.COM if (key1 < key2)
104612198SEiji.Ota@Sun.COM return (-1);
104712198SEiji.Ota@Sun.COM if (key1 > key2)
104812198SEiji.Ota@Sun.COM return (1);
104912198SEiji.Ota@Sun.COM return (0);
105012198SEiji.Ota@Sun.COM }
105112198SEiji.Ota@Sun.COM
105212198SEiji.Ota@Sun.COM /* transport.c */
105312414SEiji.Ota@Sun.COM extern struct rdsv3_transport *transports[];
105412198SEiji.Ota@Sun.COM extern krwlock_t trans_sem;
105512198SEiji.Ota@Sun.COM
105612198SEiji.Ota@Sun.COM void
rdsv3_trans_exit(void)105712198SEiji.Ota@Sun.COM rdsv3_trans_exit(void)
105812198SEiji.Ota@Sun.COM {
105912198SEiji.Ota@Sun.COM struct rdsv3_transport *trans;
106012414SEiji.Ota@Sun.COM int i;
106112198SEiji.Ota@Sun.COM
106212198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_trans_exit", "Enter");
106312198SEiji.Ota@Sun.COM
106412198SEiji.Ota@Sun.COM /* currently, only IB transport */
106512198SEiji.Ota@Sun.COM rw_enter(&trans_sem, RW_READER);
106612414SEiji.Ota@Sun.COM trans = NULL;
106712414SEiji.Ota@Sun.COM for (i = 0; i < RDS_TRANS_COUNT; i++) {
106812414SEiji.Ota@Sun.COM if (transports[i]) {
106912414SEiji.Ota@Sun.COM trans = transports[i];
107012414SEiji.Ota@Sun.COM break;
107112414SEiji.Ota@Sun.COM }
107212414SEiji.Ota@Sun.COM }
107312198SEiji.Ota@Sun.COM rw_exit(&trans_sem);
107412198SEiji.Ota@Sun.COM
107512198SEiji.Ota@Sun.COM /* trans->exit() will remove the trans from the list */
107612198SEiji.Ota@Sun.COM if (trans)
107712198SEiji.Ota@Sun.COM trans->exit();
107812198SEiji.Ota@Sun.COM
107912198SEiji.Ota@Sun.COM rw_destroy(&trans_sem);
108012198SEiji.Ota@Sun.COM
108112198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_trans_exit", "Return");
108212198SEiji.Ota@Sun.COM }
108312198SEiji.Ota@Sun.COM
108412198SEiji.Ota@Sun.COM void
rdsv3_trans_init()108512198SEiji.Ota@Sun.COM rdsv3_trans_init()
108612198SEiji.Ota@Sun.COM {
108712198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_trans_init", "Enter");
108812198SEiji.Ota@Sun.COM
108912198SEiji.Ota@Sun.COM rw_init(&trans_sem, NULL, RW_DRIVER, NULL);
109012198SEiji.Ota@Sun.COM
109112198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_trans_init", "Return");
109212198SEiji.Ota@Sun.COM }
109312198SEiji.Ota@Sun.COM
109412198SEiji.Ota@Sun.COM int
rdsv3_put_cmsg(struct nmsghdr * msg,int level,int type,size_t size,void * payload)109512198SEiji.Ota@Sun.COM rdsv3_put_cmsg(struct nmsghdr *msg, int level, int type, size_t size,
109612198SEiji.Ota@Sun.COM void *payload)
109712198SEiji.Ota@Sun.COM {
109812198SEiji.Ota@Sun.COM struct cmsghdr *cp;
109912198SEiji.Ota@Sun.COM char *bp;
110012198SEiji.Ota@Sun.COM size_t cmlen;
110112198SEiji.Ota@Sun.COM size_t cmspace;
110212198SEiji.Ota@Sun.COM size_t bufsz;
110312198SEiji.Ota@Sun.COM
110412198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_put_cmsg",
110512198SEiji.Ota@Sun.COM "Enter(msg: %p level: %d type: %d sz: %d)",
110612198SEiji.Ota@Sun.COM msg, level, type, size);
110712198SEiji.Ota@Sun.COM
1108*12896SEiji.Ota@Sun.COM if (msg == NULL || msg->msg_controllen == 0) {
110912198SEiji.Ota@Sun.COM return (0);
111012198SEiji.Ota@Sun.COM }
111112198SEiji.Ota@Sun.COM /* check for first cmsg or this is another cmsg to be appended */
111212198SEiji.Ota@Sun.COM if (msg->msg_control == NULL)
111312198SEiji.Ota@Sun.COM msg->msg_controllen = 0;
111412198SEiji.Ota@Sun.COM
111512198SEiji.Ota@Sun.COM cmlen = CMSG_LEN(size);
111612198SEiji.Ota@Sun.COM cmspace = CMSG_SPACE(size);
111712198SEiji.Ota@Sun.COM bufsz = msg->msg_controllen + cmspace;
111812198SEiji.Ota@Sun.COM
111912198SEiji.Ota@Sun.COM /* extend the existing cmsg to append the next cmsg */
112012198SEiji.Ota@Sun.COM bp = kmem_alloc(bufsz, KM_SLEEP);
112112198SEiji.Ota@Sun.COM if (msg->msg_control) {
112212198SEiji.Ota@Sun.COM bcopy(msg->msg_control, bp, msg->msg_controllen);
112312198SEiji.Ota@Sun.COM kmem_free(msg->msg_control, (size_t)msg->msg_controllen);
112412198SEiji.Ota@Sun.COM }
112512198SEiji.Ota@Sun.COM
112612198SEiji.Ota@Sun.COM /* assign payload the proper cmsg location */
112712198SEiji.Ota@Sun.COM cp = (struct cmsghdr *)(bp + msg->msg_controllen);
112812198SEiji.Ota@Sun.COM cp->cmsg_len = cmlen;
112912198SEiji.Ota@Sun.COM cp->cmsg_level = level;
113012198SEiji.Ota@Sun.COM cp->cmsg_type = type;
113112198SEiji.Ota@Sun.COM
113212198SEiji.Ota@Sun.COM bcopy(payload, CMSG_DATA(cp), cmlen -
113312198SEiji.Ota@Sun.COM (unsigned int)_CMSG_DATA_ALIGN(sizeof (struct cmsghdr)));
113412198SEiji.Ota@Sun.COM
113512198SEiji.Ota@Sun.COM msg->msg_control = bp;
113612198SEiji.Ota@Sun.COM msg->msg_controllen = bufsz;
113712198SEiji.Ota@Sun.COM
113812198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_put_cmsg", "Return(cmsg_len: %d)", cp->cmsg_len);
113912198SEiji.Ota@Sun.COM
114012198SEiji.Ota@Sun.COM return (0);
114112198SEiji.Ota@Sun.COM }
114212198SEiji.Ota@Sun.COM
114312198SEiji.Ota@Sun.COM /* ARGSUSED */
114412198SEiji.Ota@Sun.COM int
rdsv3_verify_bind_address(ipaddr_t addr)114512198SEiji.Ota@Sun.COM rdsv3_verify_bind_address(ipaddr_t addr)
114612198SEiji.Ota@Sun.COM {
114712198SEiji.Ota@Sun.COM return (1);
114812198SEiji.Ota@Sun.COM }
114912198SEiji.Ota@Sun.COM
115012198SEiji.Ota@Sun.COM /* checksum */
115112198SEiji.Ota@Sun.COM uint16_t
rdsv3_ip_fast_csum(void * hdr,size_t length)115212198SEiji.Ota@Sun.COM rdsv3_ip_fast_csum(void *hdr, size_t length)
115312198SEiji.Ota@Sun.COM {
115412198SEiji.Ota@Sun.COM return (0xffff &
115512198SEiji.Ota@Sun.COM (uint16_t)(~ip_ocsum((ushort_t *)hdr, (int)length <<1, 0)));
115612198SEiji.Ota@Sun.COM }
115712198SEiji.Ota@Sun.COM
115812198SEiji.Ota@Sun.COM /* scatterlist implementation */
115912198SEiji.Ota@Sun.COM /* ARGSUSED */
116012198SEiji.Ota@Sun.COM caddr_t
rdsv3_ib_sg_dma_address(ib_device_t * dev,struct rdsv3_scatterlist * scat,uint_t offset)116112198SEiji.Ota@Sun.COM rdsv3_ib_sg_dma_address(ib_device_t *dev, struct rdsv3_scatterlist *scat,
116212198SEiji.Ota@Sun.COM uint_t offset)
116312198SEiji.Ota@Sun.COM {
116412198SEiji.Ota@Sun.COM return (0);
116512198SEiji.Ota@Sun.COM }
116612198SEiji.Ota@Sun.COM
116712198SEiji.Ota@Sun.COM uint_t
rdsv3_ib_dma_map_sg(struct ib_device * dev,struct rdsv3_scatterlist * scat,uint_t num)116812198SEiji.Ota@Sun.COM rdsv3_ib_dma_map_sg(struct ib_device *dev, struct rdsv3_scatterlist *scat,
116912198SEiji.Ota@Sun.COM uint_t num)
117012198SEiji.Ota@Sun.COM {
117112198SEiji.Ota@Sun.COM struct rdsv3_scatterlist *s, *first;
117212198SEiji.Ota@Sun.COM ibt_iov_t *iov;
117312198SEiji.Ota@Sun.COM ibt_wr_ds_t *sgl;
117412198SEiji.Ota@Sun.COM ibt_iov_attr_t iov_attr;
117512198SEiji.Ota@Sun.COM ibt_send_wr_t swr;
117612198SEiji.Ota@Sun.COM uint_t i;
117712198SEiji.Ota@Sun.COM
117812198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_ib_dma_map_sg", "scat %p, num: %d", scat, num);
117912198SEiji.Ota@Sun.COM
118012198SEiji.Ota@Sun.COM s = first = &scat[0];
118112198SEiji.Ota@Sun.COM ASSERT(first->mihdl == NULL);
118212198SEiji.Ota@Sun.COM
118312198SEiji.Ota@Sun.COM iov = kmem_alloc(num * sizeof (ibt_iov_t), KM_SLEEP);
118412198SEiji.Ota@Sun.COM sgl = kmem_zalloc((num * 2) * sizeof (ibt_wr_ds_t), KM_SLEEP);
118512198SEiji.Ota@Sun.COM
118612198SEiji.Ota@Sun.COM for (i = 0; i < num; i++, s++) {
118712198SEiji.Ota@Sun.COM iov[i].iov_addr = s->vaddr;
118812198SEiji.Ota@Sun.COM iov[i].iov_len = s->length;
118912198SEiji.Ota@Sun.COM }
119012198SEiji.Ota@Sun.COM
119112198SEiji.Ota@Sun.COM iov_attr.iov_as = NULL;
119212198SEiji.Ota@Sun.COM iov_attr.iov = iov;
119312198SEiji.Ota@Sun.COM iov_attr.iov_buf = NULL;
119412198SEiji.Ota@Sun.COM iov_attr.iov_list_len = num;
119512198SEiji.Ota@Sun.COM iov_attr.iov_wr_nds = num * 2;
119612198SEiji.Ota@Sun.COM iov_attr.iov_lso_hdr_sz = 0;
119712198SEiji.Ota@Sun.COM iov_attr.iov_flags = IBT_IOV_SLEEP;
119812198SEiji.Ota@Sun.COM
119912198SEiji.Ota@Sun.COM swr.wr_sgl = sgl;
120012198SEiji.Ota@Sun.COM
120112198SEiji.Ota@Sun.COM i = ibt_map_mem_iov(ib_get_ibt_hca_hdl(dev),
120212198SEiji.Ota@Sun.COM &iov_attr, (ibt_all_wr_t *)&swr, &first->mihdl);
120312198SEiji.Ota@Sun.COM kmem_free(iov, num * sizeof (ibt_iov_t));
120412198SEiji.Ota@Sun.COM if (i != IBT_SUCCESS) {
120512198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_ib_dma_map_sg",
120612198SEiji.Ota@Sun.COM "ibt_map_mem_iov returned: %d", i);
120712198SEiji.Ota@Sun.COM return (0);
120812198SEiji.Ota@Sun.COM }
120912198SEiji.Ota@Sun.COM
121012198SEiji.Ota@Sun.COM s = first;
121112198SEiji.Ota@Sun.COM for (i = 0; i < num; i++, s++, sgl++) {
121212198SEiji.Ota@Sun.COM s->sgl = sgl;
121312198SEiji.Ota@Sun.COM }
121412198SEiji.Ota@Sun.COM
121512198SEiji.Ota@Sun.COM return (num);
121612198SEiji.Ota@Sun.COM }
121712198SEiji.Ota@Sun.COM
121812198SEiji.Ota@Sun.COM void
rdsv3_ib_dma_unmap_sg(ib_device_t * dev,struct rdsv3_scatterlist * scat,uint_t num)121912198SEiji.Ota@Sun.COM rdsv3_ib_dma_unmap_sg(ib_device_t *dev, struct rdsv3_scatterlist *scat,
122012198SEiji.Ota@Sun.COM uint_t num)
122112198SEiji.Ota@Sun.COM {
122212198SEiji.Ota@Sun.COM /* Zero length messages have no scatter gather entries */
122312198SEiji.Ota@Sun.COM if (num != 0) {
122412198SEiji.Ota@Sun.COM ASSERT(scat->mihdl != NULL);
122512198SEiji.Ota@Sun.COM ASSERT(scat->sgl != NULL);
122612198SEiji.Ota@Sun.COM
122712198SEiji.Ota@Sun.COM (void) ibt_unmap_mem_iov(ib_get_ibt_hca_hdl(dev), scat->mihdl);
122812198SEiji.Ota@Sun.COM
122912198SEiji.Ota@Sun.COM kmem_free(scat->sgl, (num * 2) * sizeof (ibt_wr_ds_t));
123012198SEiji.Ota@Sun.COM scat->sgl = NULL;
123112198SEiji.Ota@Sun.COM scat->mihdl = NULL;
123212198SEiji.Ota@Sun.COM }
123312198SEiji.Ota@Sun.COM }
123412198SEiji.Ota@Sun.COM
123512198SEiji.Ota@Sun.COM int
rdsv3_ib_alloc_hdrs(ib_device_t * dev,struct rdsv3_ib_connection * ic)123612198SEiji.Ota@Sun.COM rdsv3_ib_alloc_hdrs(ib_device_t *dev, struct rdsv3_ib_connection *ic)
123712198SEiji.Ota@Sun.COM {
123812198SEiji.Ota@Sun.COM caddr_t addr;
123912198SEiji.Ota@Sun.COM size_t size;
124012198SEiji.Ota@Sun.COM ibt_mr_attr_t mr_attr;
124112198SEiji.Ota@Sun.COM ibt_mr_desc_t mr_desc;
124212198SEiji.Ota@Sun.COM ibt_mr_hdl_t mr_hdl;
124312198SEiji.Ota@Sun.COM int ret;
124412198SEiji.Ota@Sun.COM
124512198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_ib_alloc_hdrs", "Enter(dev: %p)", dev);
124612198SEiji.Ota@Sun.COM
124712198SEiji.Ota@Sun.COM ASSERT(ic->i_mr == NULL);
124812198SEiji.Ota@Sun.COM
124912198SEiji.Ota@Sun.COM size = (ic->i_send_ring.w_nr + ic->i_recv_ring.w_nr + 1) *
125012198SEiji.Ota@Sun.COM sizeof (struct rdsv3_header);
125112198SEiji.Ota@Sun.COM
125212198SEiji.Ota@Sun.COM addr = kmem_zalloc(size, KM_NOSLEEP);
125312198SEiji.Ota@Sun.COM if (addr == NULL)
125412198SEiji.Ota@Sun.COM return (-1);
125512198SEiji.Ota@Sun.COM
125612198SEiji.Ota@Sun.COM mr_attr.mr_vaddr = (ib_vaddr_t)(uintptr_t)addr;
125712198SEiji.Ota@Sun.COM mr_attr.mr_len = size;
125812198SEiji.Ota@Sun.COM mr_attr.mr_as = NULL;
125912198SEiji.Ota@Sun.COM mr_attr.mr_flags = IBT_MR_ENABLE_LOCAL_WRITE;
126012198SEiji.Ota@Sun.COM ret = ibt_register_mr(ib_get_ibt_hca_hdl(dev), RDSV3_PD2PDHDL(ic->i_pd),
126112198SEiji.Ota@Sun.COM &mr_attr, &mr_hdl, &mr_desc);
126212198SEiji.Ota@Sun.COM if (ret != IBT_SUCCESS) {
126312198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_ib_alloc_hdrs",
126412198SEiji.Ota@Sun.COM "ibt_register_mr returned: " "%d", ret);
126512198SEiji.Ota@Sun.COM return (-1);
126612198SEiji.Ota@Sun.COM }
126712198SEiji.Ota@Sun.COM
126812198SEiji.Ota@Sun.COM ic->i_mr =
126912198SEiji.Ota@Sun.COM (struct rdsv3_hdrs_mr *)kmem_alloc(sizeof (struct rdsv3_hdrs_mr),
127012198SEiji.Ota@Sun.COM KM_SLEEP);
127112198SEiji.Ota@Sun.COM ic->i_mr->addr = addr;
127212198SEiji.Ota@Sun.COM ic->i_mr->size = size;
127312198SEiji.Ota@Sun.COM ic->i_mr->hdl = mr_hdl;
127412198SEiji.Ota@Sun.COM ic->i_mr->lkey = mr_desc.md_lkey;
127512198SEiji.Ota@Sun.COM
127612198SEiji.Ota@Sun.COM ic->i_send_hdrs = (struct rdsv3_header *)addr;
127712198SEiji.Ota@Sun.COM ic->i_send_hdrs_dma = (uint64_t)(uintptr_t)addr;
127812198SEiji.Ota@Sun.COM
127912198SEiji.Ota@Sun.COM ic->i_recv_hdrs = (struct rdsv3_header *)(addr +
128012198SEiji.Ota@Sun.COM (ic->i_send_ring.w_nr * sizeof (struct rdsv3_header)));
128112198SEiji.Ota@Sun.COM ic->i_recv_hdrs_dma = (uint64_t)(uintptr_t)(addr +
128212198SEiji.Ota@Sun.COM (ic->i_send_ring.w_nr * sizeof (struct rdsv3_header)));
128312198SEiji.Ota@Sun.COM
128412198SEiji.Ota@Sun.COM ic->i_ack = (struct rdsv3_header *)(addr +
128512198SEiji.Ota@Sun.COM ((ic->i_send_ring.w_nr + ic->i_recv_ring.w_nr) *
128612198SEiji.Ota@Sun.COM sizeof (struct rdsv3_header)));
128712198SEiji.Ota@Sun.COM ic->i_ack_dma = (uint64_t)(uintptr_t)(addr +
128812198SEiji.Ota@Sun.COM ((ic->i_send_ring.w_nr + ic->i_recv_ring.w_nr) *
128912198SEiji.Ota@Sun.COM sizeof (struct rdsv3_header)));
129012198SEiji.Ota@Sun.COM
129112198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_ib_alloc_hdrs", "Return(dev: %p)", dev);
129212198SEiji.Ota@Sun.COM
129312198SEiji.Ota@Sun.COM return (0);
129412198SEiji.Ota@Sun.COM }
129512198SEiji.Ota@Sun.COM
129612198SEiji.Ota@Sun.COM void
rdsv3_ib_free_hdrs(ib_device_t * dev,struct rdsv3_ib_connection * ic)129712198SEiji.Ota@Sun.COM rdsv3_ib_free_hdrs(ib_device_t *dev, struct rdsv3_ib_connection *ic)
129812198SEiji.Ota@Sun.COM {
129912198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_ib_free_hdrs", "Enter(dev: %p)", dev);
130012198SEiji.Ota@Sun.COM ASSERT(ic->i_mr != NULL);
130112198SEiji.Ota@Sun.COM
130212198SEiji.Ota@Sun.COM ic->i_send_hdrs = NULL;
130312198SEiji.Ota@Sun.COM ic->i_send_hdrs_dma = NULL;
130412198SEiji.Ota@Sun.COM
130512198SEiji.Ota@Sun.COM ic->i_recv_hdrs = NULL;
130612198SEiji.Ota@Sun.COM ic->i_recv_hdrs_dma = NULL;
130712198SEiji.Ota@Sun.COM
130812198SEiji.Ota@Sun.COM ic->i_ack = NULL;
130912198SEiji.Ota@Sun.COM ic->i_ack_dma = NULL;
131012198SEiji.Ota@Sun.COM
131112198SEiji.Ota@Sun.COM (void) ibt_deregister_mr(ib_get_ibt_hca_hdl(dev), ic->i_mr->hdl);
131212198SEiji.Ota@Sun.COM
131312198SEiji.Ota@Sun.COM kmem_free(ic->i_mr->addr, ic->i_mr->size);
131412198SEiji.Ota@Sun.COM kmem_free(ic->i_mr, sizeof (struct rdsv3_hdrs_mr));
131512198SEiji.Ota@Sun.COM
131612198SEiji.Ota@Sun.COM ic->i_mr = NULL;
131712198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_ib_free_hdrs", "Return(dev: %p)", dev);
131812198SEiji.Ota@Sun.COM }
131912414SEiji.Ota@Sun.COM
132012414SEiji.Ota@Sun.COM /*
132112414SEiji.Ota@Sun.COM * atomic_add_unless - add unless the number is a given value
132212414SEiji.Ota@Sun.COM * @v: pointer of type atomic_t
132312414SEiji.Ota@Sun.COM * @a: the amount to add to v...
132412414SEiji.Ota@Sun.COM * @u: ...unless v is equal to u.
132512414SEiji.Ota@Sun.COM *
132612414SEiji.Ota@Sun.COM * Atomically adds @a to @v, so long as it was not @u.
132712414SEiji.Ota@Sun.COM * Returns non-zero if @v was not @u, and zero otherwise.
132812414SEiji.Ota@Sun.COM */
132912414SEiji.Ota@Sun.COM int
atomic_add_unless(atomic_t * v,uint_t a,ulong_t u)133012414SEiji.Ota@Sun.COM atomic_add_unless(atomic_t *v, uint_t a, ulong_t u)
133112414SEiji.Ota@Sun.COM {
133212414SEiji.Ota@Sun.COM uint_t c, old;
133312414SEiji.Ota@Sun.COM
133412414SEiji.Ota@Sun.COM c = *v;
133512414SEiji.Ota@Sun.COM while (c != u && (old = atomic_cas_uint(v, c, c + a)) != c) {
133612414SEiji.Ota@Sun.COM c = old;
133712414SEiji.Ota@Sun.COM }
133812414SEiji.Ota@Sun.COM return ((ulong_t)c != u);
133912414SEiji.Ota@Sun.COM }
1340