c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
16e76cdd6e3cfaac7d91c3b0644ee1bc6cf52347agiri * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
16e76cdd6e3cfaac7d91c3b0644ee1bc6cf52347agiri
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
16e76cdd6e3cfaac7d91c3b0644ee1bc6cf52347agiri * This file contains code imported from the OFED rds source file threads.c
16e76cdd6e3cfaac7d91c3b0644ee1bc6cf52347agiri * Oracle elects to have and use the contents of threads.c under and governed
16e76cdd6e3cfaac7d91c3b0644ee1bc6cf52347agiri * by the OpenIB.org BSD license (see below for full license text). However,
16e76cdd6e3cfaac7d91c3b0644ee1bc6cf52347agiri * the following notice accompanied the original version of this file:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Copyright (c) 2006 Oracle. All rights reserved.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * This software is available to you under a choice of one of two
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * licenses. You may choose to be licensed under the terms of the GNU
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * General Public License (GPL) Version 2, available from the file
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * COPYING in the main directory of this source tree, or the
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * OpenIB.org BSD license below:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Redistribution and use in source and binary forms, with or
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * without modification, are permitted provided that the following
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * conditions are met:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * - Redistributions of source code must retain the above
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * copyright notice, this list of conditions and the following
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * disclaimer.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * - Redistributions in binary form must reproduce the above
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * copyright notice, this list of conditions and the following
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * disclaimer in the documentation and/or other materials
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * provided with the distribution.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * SOFTWARE.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/rds.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/sunddi.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/ib/clients/rdsv3/rdsv3.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/ib/clients/rdsv3/rdsv3_debug.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * All of connection management is simplified by serializing it through
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * work queues that execute in a connection managing thread.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * TCP wants to send acks through sendpage() in response to data_ready(),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * but it needs a process context to do so.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * The receive paths need to allocate but can't drop packets (!) so we have
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * a thread around to block allocating if the receive fast path sees an
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * allocation failure.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Grand Unified Theory of connection life cycle:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * At any point in time, the connection can be in one of these states:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * DOWN, CONNECTING, UP, DISCONNECTING, ERROR
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * The following transitions are possible:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * ANY -> ERROR
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * UP -> DISCONNECTING
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * ERROR -> DISCONNECTING
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * DISCONNECTING -> DOWN
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * DOWN -> CONNECTING
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * CONNECTING -> UP
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Transition to state DISCONNECTING/DOWN:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * - Inside the shutdown worker; synchronizes with xmit path
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * through c_send_lock, and with connection management callbacks
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * via c_cm_lock.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * For receive callbacks, we rely on the underlying transport
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * (TCP, IB/RDMA) to provide the necessary synchronisation.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastruct rdsv3_workqueue_struct_s *rdsv3_wq;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_connect_complete(struct rdsv3_connection *conn)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_connect_complete", "Enter(conn: %p)", conn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (!rdsv3_conn_transition(conn, RDSV3_CONN_CONNECTING,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_CONN_UP)) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#ifndef __lock_lint
6e18d381c642549b8bb1774a803d3510aec6baafagiri RDSV3_DPRINTF2("rdsv3_connect_complete",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "%s: Cannot transition to state UP, "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "current state is %d",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota __func__,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota atomic_get(&conn->c_state));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#endif
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota conn->c_state = RDSV3_CONN_ERROR;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_queue_work(rdsv3_wq, &conn->c_down_w);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_connect_complete",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "conn %p for %u.%u.%u.%u to %u.%u.%u.%u complete",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota conn, NIPQUAD(conn->c_laddr), NIPQUAD(conn->c_faddr));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota conn->c_reconnect_jiffies = 0;
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota conn->c_last_connect_jiffies = ddi_get_lbolt();
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota set_bit(0, &conn->c_map_queued);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_queue_delayed_work(rdsv3_wq, &conn->c_send_w, 0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_queue_delayed_work(rdsv3_wq, &conn->c_recv_w, 0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_connect_complete", "Return(conn: %p)", conn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * This random exponential backoff is relied on to eventually resolve racing
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * connects.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * If connect attempts race then both parties drop both connections and come
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * here to wait for a random amount of time before trying again. Eventually
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * the backoff range will be so much greater than the time it takes to
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * establish a connection that one of the pair will establish the connection
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * before the other's random delay fires.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Connection attempts that arrive while a connection is already established
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * are also considered to be racing connects. This lets a connection from
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * a rebooted machine replace an existing stale connection before the transport
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * notices that the connection has failed.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * We should *always* start with a random backoff; otherwise a broken connection
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * will always take several iterations to be re-established.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_queue_reconnect(struct rdsv3_connection *conn)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota unsigned long rand;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_queue_reconnect",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "conn %p for %u.%u.%u.%u to %u.%u.%u.%u reconnect jiffies %lu",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota conn, NIPQUAD(conn->c_laddr), NIPQUAD(conn->c_faddr),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota conn->c_reconnect_jiffies);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota set_bit(RDSV3_RECONNECT_PENDING, &conn->c_flags);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (conn->c_reconnect_jiffies == 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota conn->c_reconnect_jiffies = rdsv3_sysctl_reconnect_min_jiffies;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_queue_delayed_work(rdsv3_wq, &conn->c_conn_w, 0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (void) random_get_pseudo_bytes((uint8_t *)&rand, sizeof (rand));
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF5("rdsv3",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "%lu delay %lu ceil conn %p for %u.%u.%u.%u -> %u.%u.%u.%u",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rand % conn->c_reconnect_jiffies, conn->c_reconnect_jiffies,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota conn, NIPQUAD(conn->c_laddr), NIPQUAD(conn->c_faddr));
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_queue_delayed_work(rdsv3_wq, &conn->c_conn_w,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rand % conn->c_reconnect_jiffies);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota conn->c_reconnect_jiffies = min(conn->c_reconnect_jiffies * 2,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_sysctl_reconnect_max_jiffies);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_connect_worker(struct rdsv3_work_s *work)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_connection *conn = container_of(work,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_connection, c_conn_w.work);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int ret;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_connect_worker", "Enter(work: %p)", work);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota clear_bit(RDSV3_RECONNECT_PENDING, &conn->c_flags);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rdsv3_conn_transition(conn, RDSV3_CONN_DOWN,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_CONN_CONNECTING)) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = conn->c_trans->conn_connect(conn);
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF5("rdsv3",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "connect conn %p for %u.%u.%u.%u -> %u.%u.%u.%u "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ret %d", conn, NIPQUAD(conn->c_laddr),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota NIPQUAD(conn->c_faddr), ret);
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_connect_worker",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "conn %p for %u.%u.%u.%u to %u.%u.%u.%u dispatched, ret %d",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota conn, NIPQUAD(conn->c_laddr), NIPQUAD(conn->c_faddr), ret);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ret) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rdsv3_conn_transition(conn, RDSV3_CONN_CONNECTING,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_CONN_DOWN))
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_queue_reconnect(conn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota else {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_connect_worker",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "RDS: connect failed: %p", conn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_conn_drop(conn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_connect_worker", "Return(work: %p)", work);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_send_worker(struct rdsv3_work_s *work)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_connection *conn = container_of(work,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_connection, c_send_w.work);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int ret;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_send_worker", "Enter(work: %p)", work);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rdsv3_conn_state(conn) == RDSV3_CONN_UP) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = rdsv3_send_xmit(conn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF5("rdsv3", "conn %p ret %d", conn, ret);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (ret) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case -EAGAIN:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_stats_inc(s_send_immediate_retry);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_queue_delayed_work(rdsv3_wq, &conn->c_send_w, 0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case -ENOMEM:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_stats_inc(s_send_delayed_retry);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_queue_delayed_work(rdsv3_wq, &conn->c_send_w, 2);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_send_worker", "Return(work: %p)", work);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_recv_worker(struct rdsv3_work_s *work)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_connection *conn = container_of(work,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_connection, c_recv_w.work);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int ret;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_recv_worker", "Enter(work: %p)", work);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rdsv3_conn_state(conn) == RDSV3_CONN_UP) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = conn->c_trans->recv(conn);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF5("rdsv3", "conn %p ret %d", conn, ret);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (ret) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case -EAGAIN:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_stats_inc(s_recv_immediate_retry);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_queue_delayed_work(rdsv3_wq, &conn->c_recv_w, 0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case -ENOMEM:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_stats_inc(s_recv_delayed_retry);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_queue_delayed_work(rdsv3_wq, &conn->c_recv_w, 2);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_recv_worker", "Return(work: %p)", work);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Otavoid
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Otardsv3_shutdown_worker(struct rdsv3_work_s *work)
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota{
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota struct rdsv3_connection *conn = container_of(work,
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota struct rdsv3_connection, c_down_w);
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota rdsv3_conn_shutdown(conn);
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota}
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota#define time_after(a, b) ((long)(b) - (long)(a) < 0)
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Otavoid
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Otardsv3_reaper_worker(struct rdsv3_work_s *work)
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota{
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota struct rdsv3_connection *conn = container_of(work,
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota struct rdsv3_connection, c_reap_w.work);
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota if (rdsv3_conn_state(conn) != RDSV3_CONN_UP &&
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota !time_after(conn->c_last_connect_jiffies,
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota ddi_get_lbolt() - RDSV3_REAPER_WAIT_JIFFIES)) {
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota rdsv3_conn_destroy(conn);
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota } else {
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota rdsv3_queue_delayed_work(rdsv3_wq, &conn->c_reap_w,
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota RDSV3_REAPER_WAIT_JIFFIES);
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota }
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota}
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_threads_exit(void)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_destroy_task_workqueue(rdsv3_wq);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaint
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_threads_init(void)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_wq = rdsv3_create_task_workqueue("krdsd");
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota if (!rdsv3_wq)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-ENOMEM);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}