18c3e34a4SDavid Howells /* RxRPC individual remote procedure call handling 28c3e34a4SDavid Howells * 38c3e34a4SDavid Howells * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. 48c3e34a4SDavid Howells * Written by David Howells (dhowells@redhat.com) 58c3e34a4SDavid Howells * 68c3e34a4SDavid Howells * This program is free software; you can redistribute it and/or 78c3e34a4SDavid Howells * modify it under the terms of the GNU General Public License 88c3e34a4SDavid Howells * as published by the Free Software Foundation; either version 98c3e34a4SDavid Howells * 2 of the License, or (at your option) any later version. 108c3e34a4SDavid Howells */ 118c3e34a4SDavid Howells 128c3e34a4SDavid Howells #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 138c3e34a4SDavid Howells 148c3e34a4SDavid Howells #include <linux/slab.h> 158c3e34a4SDavid Howells #include <linux/module.h> 168c3e34a4SDavid Howells #include <linux/circ_buf.h> 178c3e34a4SDavid Howells #include <linux/spinlock_types.h> 188c3e34a4SDavid Howells #include <net/sock.h> 198c3e34a4SDavid Howells #include <net/af_rxrpc.h> 208c3e34a4SDavid Howells #include "ar-internal.h" 218c3e34a4SDavid Howells 228c3e34a4SDavid Howells /* 238c3e34a4SDavid Howells * Maximum lifetime of a call (in jiffies). 248c3e34a4SDavid Howells */ 258c3e34a4SDavid Howells unsigned int rxrpc_max_call_lifetime = 60 * HZ; 268c3e34a4SDavid Howells 278c3e34a4SDavid Howells const char *const rxrpc_call_states[NR__RXRPC_CALL_STATES] = { 28999b69f8SDavid Howells [RXRPC_CALL_UNINITIALISED] = "Uninit ", 29999b69f8SDavid Howells [RXRPC_CALL_CLIENT_AWAIT_CONN] = "ClWtConn", 308c3e34a4SDavid Howells [RXRPC_CALL_CLIENT_SEND_REQUEST] = "ClSndReq", 318c3e34a4SDavid Howells [RXRPC_CALL_CLIENT_AWAIT_REPLY] = "ClAwtRpl", 328c3e34a4SDavid Howells [RXRPC_CALL_CLIENT_RECV_REPLY] = "ClRcvRpl", 338c3e34a4SDavid Howells [RXRPC_CALL_CLIENT_FINAL_ACK] = "ClFnlACK", 3400e90712SDavid Howells [RXRPC_CALL_SERVER_PREALLOC] = "SvPrealc", 358c3e34a4SDavid Howells [RXRPC_CALL_SERVER_SECURING] = "SvSecure", 368c3e34a4SDavid Howells [RXRPC_CALL_SERVER_ACCEPTING] = "SvAccept", 378c3e34a4SDavid Howells [RXRPC_CALL_SERVER_RECV_REQUEST] = "SvRcvReq", 388c3e34a4SDavid Howells [RXRPC_CALL_SERVER_ACK_REQUEST] = "SvAckReq", 398c3e34a4SDavid Howells [RXRPC_CALL_SERVER_SEND_REPLY] = "SvSndRpl", 408c3e34a4SDavid Howells [RXRPC_CALL_SERVER_AWAIT_ACK] = "SvAwtACK", 418c3e34a4SDavid Howells [RXRPC_CALL_COMPLETE] = "Complete", 42f5c17aaeSDavid Howells }; 43f5c17aaeSDavid Howells 44f5c17aaeSDavid Howells const char *const rxrpc_call_completions[NR__RXRPC_CALL_COMPLETIONS] = { 45f5c17aaeSDavid Howells [RXRPC_CALL_SUCCEEDED] = "Complete", 468c3e34a4SDavid Howells [RXRPC_CALL_SERVER_BUSY] = "SvBusy ", 478c3e34a4SDavid Howells [RXRPC_CALL_REMOTELY_ABORTED] = "RmtAbort", 488c3e34a4SDavid Howells [RXRPC_CALL_LOCALLY_ABORTED] = "LocAbort", 49f5c17aaeSDavid Howells [RXRPC_CALL_LOCAL_ERROR] = "LocError", 508c3e34a4SDavid Howells [RXRPC_CALL_NETWORK_ERROR] = "NetError", 518c3e34a4SDavid Howells }; 528c3e34a4SDavid Howells 53fff72429SDavid Howells const char rxrpc_call_traces[rxrpc_call__nr_trace][4] = { 54fff72429SDavid Howells [rxrpc_call_new_client] = "NWc", 55fff72429SDavid Howells [rxrpc_call_new_service] = "NWs", 56fff72429SDavid Howells [rxrpc_call_queued] = "QUE", 57fff72429SDavid Howells [rxrpc_call_queued_ref] = "QUR", 58fff72429SDavid Howells [rxrpc_call_seen] = "SEE", 59fff72429SDavid Howells [rxrpc_call_got] = "GOT", 60fff72429SDavid Howells [rxrpc_call_got_skb] = "Gsk", 61fff72429SDavid Howells [rxrpc_call_got_userid] = "Gus", 62fff72429SDavid Howells [rxrpc_call_put] = "PUT", 63fff72429SDavid Howells [rxrpc_call_put_skb] = "Psk", 64fff72429SDavid Howells [rxrpc_call_put_userid] = "Pus", 65fff72429SDavid Howells [rxrpc_call_put_noqueue] = "PNQ", 66fff72429SDavid Howells }; 67fff72429SDavid Howells 688c3e34a4SDavid Howells struct kmem_cache *rxrpc_call_jar; 698c3e34a4SDavid Howells LIST_HEAD(rxrpc_calls); 708c3e34a4SDavid Howells DEFINE_RWLOCK(rxrpc_call_lock); 718c3e34a4SDavid Howells 728c3e34a4SDavid Howells static void rxrpc_call_life_expired(unsigned long _call); 738c3e34a4SDavid Howells static void rxrpc_ack_time_expired(unsigned long _call); 748c3e34a4SDavid Howells static void rxrpc_resend_time_expired(unsigned long _call); 758c3e34a4SDavid Howells 768c3e34a4SDavid Howells /* 778c3e34a4SDavid Howells * find an extant server call 788c3e34a4SDavid Howells * - called in process context with IRQs enabled 798c3e34a4SDavid Howells */ 808c3e34a4SDavid Howells struct rxrpc_call *rxrpc_find_call_by_user_ID(struct rxrpc_sock *rx, 818c3e34a4SDavid Howells unsigned long user_call_ID) 828c3e34a4SDavid Howells { 838c3e34a4SDavid Howells struct rxrpc_call *call; 848c3e34a4SDavid Howells struct rb_node *p; 858c3e34a4SDavid Howells 868c3e34a4SDavid Howells _enter("%p,%lx", rx, user_call_ID); 878c3e34a4SDavid Howells 888c3e34a4SDavid Howells read_lock(&rx->call_lock); 898c3e34a4SDavid Howells 908c3e34a4SDavid Howells p = rx->calls.rb_node; 918c3e34a4SDavid Howells while (p) { 928c3e34a4SDavid Howells call = rb_entry(p, struct rxrpc_call, sock_node); 938c3e34a4SDavid Howells 948c3e34a4SDavid Howells if (user_call_ID < call->user_call_ID) 958c3e34a4SDavid Howells p = p->rb_left; 968c3e34a4SDavid Howells else if (user_call_ID > call->user_call_ID) 978c3e34a4SDavid Howells p = p->rb_right; 988c3e34a4SDavid Howells else 998c3e34a4SDavid Howells goto found_extant_call; 1008c3e34a4SDavid Howells } 1018c3e34a4SDavid Howells 1028c3e34a4SDavid Howells read_unlock(&rx->call_lock); 1038c3e34a4SDavid Howells _leave(" = NULL"); 1048c3e34a4SDavid Howells return NULL; 1058c3e34a4SDavid Howells 1068c3e34a4SDavid Howells found_extant_call: 107fff72429SDavid Howells rxrpc_get_call(call, rxrpc_call_got); 1088c3e34a4SDavid Howells read_unlock(&rx->call_lock); 1098c3e34a4SDavid Howells _leave(" = %p [%d]", call, atomic_read(&call->usage)); 1108c3e34a4SDavid Howells return call; 1118c3e34a4SDavid Howells } 1128c3e34a4SDavid Howells 1138c3e34a4SDavid Howells /* 1148c3e34a4SDavid Howells * allocate a new call 1158c3e34a4SDavid Howells */ 11600e90712SDavid Howells struct rxrpc_call *rxrpc_alloc_call(gfp_t gfp) 1178c3e34a4SDavid Howells { 1188c3e34a4SDavid Howells struct rxrpc_call *call; 1198c3e34a4SDavid Howells 1208c3e34a4SDavid Howells call = kmem_cache_zalloc(rxrpc_call_jar, gfp); 1218c3e34a4SDavid Howells if (!call) 1228c3e34a4SDavid Howells return NULL; 1238c3e34a4SDavid Howells 1248c3e34a4SDavid Howells call->acks_winsz = 16; 1258c3e34a4SDavid Howells call->acks_window = kmalloc(call->acks_winsz * sizeof(unsigned long), 1268c3e34a4SDavid Howells gfp); 1278c3e34a4SDavid Howells if (!call->acks_window) { 1288c3e34a4SDavid Howells kmem_cache_free(rxrpc_call_jar, call); 1298c3e34a4SDavid Howells return NULL; 1308c3e34a4SDavid Howells } 1318c3e34a4SDavid Howells 1328c3e34a4SDavid Howells setup_timer(&call->lifetimer, &rxrpc_call_life_expired, 1338c3e34a4SDavid Howells (unsigned long) call); 1348c3e34a4SDavid Howells setup_timer(&call->ack_timer, &rxrpc_ack_time_expired, 1358c3e34a4SDavid Howells (unsigned long) call); 1368c3e34a4SDavid Howells setup_timer(&call->resend_timer, &rxrpc_resend_time_expired, 1378c3e34a4SDavid Howells (unsigned long) call); 1388c3e34a4SDavid Howells INIT_WORK(&call->processor, &rxrpc_process_call); 139999b69f8SDavid Howells INIT_LIST_HEAD(&call->link); 14045025bceSDavid Howells INIT_LIST_HEAD(&call->chan_wait_link); 1418c3e34a4SDavid Howells INIT_LIST_HEAD(&call->accept_link); 1428c3e34a4SDavid Howells skb_queue_head_init(&call->rx_queue); 1438c3e34a4SDavid Howells skb_queue_head_init(&call->rx_oos_queue); 144d001648eSDavid Howells skb_queue_head_init(&call->knlrecv_queue); 14545025bceSDavid Howells init_waitqueue_head(&call->waitq); 1468c3e34a4SDavid Howells spin_lock_init(&call->lock); 1478c3e34a4SDavid Howells rwlock_init(&call->state_lock); 1488c3e34a4SDavid Howells atomic_set(&call->usage, 1); 1498c3e34a4SDavid Howells call->debug_id = atomic_inc_return(&rxrpc_debug_id); 1508c3e34a4SDavid Howells 1518c3e34a4SDavid Howells memset(&call->sock_node, 0xed, sizeof(call->sock_node)); 1528c3e34a4SDavid Howells 1538c3e34a4SDavid Howells call->rx_data_expect = 1; 1548c3e34a4SDavid Howells call->rx_data_eaten = 0; 1558c3e34a4SDavid Howells call->rx_first_oos = 0; 1568c3e34a4SDavid Howells call->ackr_win_top = call->rx_data_eaten + 1 + rxrpc_rx_window_size; 1578c3e34a4SDavid Howells call->creation_jif = jiffies; 1588c3e34a4SDavid Howells return call; 1598c3e34a4SDavid Howells } 1608c3e34a4SDavid Howells 1618c3e34a4SDavid Howells /* 162999b69f8SDavid Howells * Allocate a new client call. 1638c3e34a4SDavid Howells */ 164aa390bbeSDavid Howells static struct rxrpc_call *rxrpc_alloc_client_call(struct rxrpc_sock *rx, 165999b69f8SDavid Howells struct sockaddr_rxrpc *srx, 1668c3e34a4SDavid Howells gfp_t gfp) 1678c3e34a4SDavid Howells { 1688c3e34a4SDavid Howells struct rxrpc_call *call; 1698c3e34a4SDavid Howells 1708c3e34a4SDavid Howells _enter(""); 1718c3e34a4SDavid Howells 172999b69f8SDavid Howells ASSERT(rx->local != NULL); 1738c3e34a4SDavid Howells 1748c3e34a4SDavid Howells call = rxrpc_alloc_call(gfp); 1758c3e34a4SDavid Howells if (!call) 1768c3e34a4SDavid Howells return ERR_PTR(-ENOMEM); 177999b69f8SDavid Howells call->state = RXRPC_CALL_CLIENT_AWAIT_CONN; 1788c3e34a4SDavid Howells call->rx_data_post = 1; 179999b69f8SDavid Howells call->service_id = srx->srx_service; 1808d94aa38SDavid Howells rcu_assign_pointer(call->socket, rx); 181999b69f8SDavid Howells 182999b69f8SDavid Howells _leave(" = %p", call); 183999b69f8SDavid Howells return call; 184999b69f8SDavid Howells } 185999b69f8SDavid Howells 186999b69f8SDavid Howells /* 187999b69f8SDavid Howells * Begin client call. 188999b69f8SDavid Howells */ 189999b69f8SDavid Howells static int rxrpc_begin_client_call(struct rxrpc_call *call, 190999b69f8SDavid Howells struct rxrpc_conn_parameters *cp, 191999b69f8SDavid Howells struct sockaddr_rxrpc *srx, 192999b69f8SDavid Howells gfp_t gfp) 193999b69f8SDavid Howells { 194999b69f8SDavid Howells int ret; 195999b69f8SDavid Howells 196999b69f8SDavid Howells /* Set up or get a connection record and set the protocol parameters, 197999b69f8SDavid Howells * including channel number and call ID. 198999b69f8SDavid Howells */ 199aa390bbeSDavid Howells ret = rxrpc_connect_call(call, cp, srx, gfp); 200999b69f8SDavid Howells if (ret < 0) 201999b69f8SDavid Howells return ret; 202999b69f8SDavid Howells 20385f32278SDavid Howells spin_lock(&call->conn->params.peer->lock); 20485f32278SDavid Howells hlist_add_head(&call->error_link, &call->conn->params.peer->error_targets); 20585f32278SDavid Howells spin_unlock(&call->conn->params.peer->lock); 2068c3e34a4SDavid Howells 2078c3e34a4SDavid Howells call->lifetimer.expires = jiffies + rxrpc_max_call_lifetime; 2088c3e34a4SDavid Howells add_timer(&call->lifetimer); 209999b69f8SDavid Howells return 0; 2108c3e34a4SDavid Howells } 2118c3e34a4SDavid Howells 2128c3e34a4SDavid Howells /* 2138c3e34a4SDavid Howells * set up a call for the given data 2148c3e34a4SDavid Howells * - called in process context with IRQs enabled 2158c3e34a4SDavid Howells */ 2168c3e34a4SDavid Howells struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx, 21719ffa01cSDavid Howells struct rxrpc_conn_parameters *cp, 218999b69f8SDavid Howells struct sockaddr_rxrpc *srx, 2198c3e34a4SDavid Howells unsigned long user_call_ID, 2208c3e34a4SDavid Howells gfp_t gfp) 2218c3e34a4SDavid Howells { 2228c3e34a4SDavid Howells struct rxrpc_call *call, *xcall; 2238c3e34a4SDavid Howells struct rb_node *parent, **pp; 224e34d4234SDavid Howells const void *here = __builtin_return_address(0); 225999b69f8SDavid Howells int ret; 2268c3e34a4SDavid Howells 227999b69f8SDavid Howells _enter("%p,%lx", rx, user_call_ID); 2288c3e34a4SDavid Howells 229aa390bbeSDavid Howells call = rxrpc_alloc_client_call(rx, srx, gfp); 2308c3e34a4SDavid Howells if (IS_ERR(call)) { 2318c3e34a4SDavid Howells _leave(" = %ld", PTR_ERR(call)); 2328c3e34a4SDavid Howells return call; 2338c3e34a4SDavid Howells } 2348c3e34a4SDavid Howells 2352ab27215SDavid Howells trace_rxrpc_call(call, 0, atomic_read(&call->usage), here, 2362ab27215SDavid Howells (const void *)user_call_ID); 237e34d4234SDavid Howells 238999b69f8SDavid Howells /* Publish the call, even though it is incompletely set up as yet */ 2398c3e34a4SDavid Howells call->user_call_ID = user_call_ID; 2408c3e34a4SDavid Howells __set_bit(RXRPC_CALL_HAS_USERID, &call->flags); 2418c3e34a4SDavid Howells 2428c3e34a4SDavid Howells write_lock(&rx->call_lock); 2438c3e34a4SDavid Howells 2448c3e34a4SDavid Howells pp = &rx->calls.rb_node; 2458c3e34a4SDavid Howells parent = NULL; 2468c3e34a4SDavid Howells while (*pp) { 2478c3e34a4SDavid Howells parent = *pp; 2488c3e34a4SDavid Howells xcall = rb_entry(parent, struct rxrpc_call, sock_node); 2498c3e34a4SDavid Howells 2508c3e34a4SDavid Howells if (user_call_ID < xcall->user_call_ID) 2518c3e34a4SDavid Howells pp = &(*pp)->rb_left; 2528c3e34a4SDavid Howells else if (user_call_ID > xcall->user_call_ID) 2538c3e34a4SDavid Howells pp = &(*pp)->rb_right; 2548c3e34a4SDavid Howells else 2558c3e34a4SDavid Howells goto found_user_ID_now_present; 2568c3e34a4SDavid Howells } 2578c3e34a4SDavid Howells 258fff72429SDavid Howells rxrpc_get_call(call, rxrpc_call_got_userid); 2598c3e34a4SDavid Howells rb_link_node(&call->sock_node, parent, pp); 2608c3e34a4SDavid Howells rb_insert_color(&call->sock_node, &rx->calls); 2618c3e34a4SDavid Howells write_unlock(&rx->call_lock); 2628c3e34a4SDavid Howells 2638c3e34a4SDavid Howells write_lock_bh(&rxrpc_call_lock); 2648c3e34a4SDavid Howells list_add_tail(&call->link, &rxrpc_calls); 2658c3e34a4SDavid Howells write_unlock_bh(&rxrpc_call_lock); 2668c3e34a4SDavid Howells 267aa390bbeSDavid Howells ret = rxrpc_begin_client_call(call, cp, srx, gfp); 268999b69f8SDavid Howells if (ret < 0) 269999b69f8SDavid Howells goto error; 270999b69f8SDavid Howells 2718c3e34a4SDavid Howells _net("CALL new %d on CONN %d", call->debug_id, call->conn->debug_id); 2728c3e34a4SDavid Howells 2738c3e34a4SDavid Howells _leave(" = %p [new]", call); 2748c3e34a4SDavid Howells return call; 2758c3e34a4SDavid Howells 276999b69f8SDavid Howells error: 277999b69f8SDavid Howells write_lock(&rx->call_lock); 278999b69f8SDavid Howells rb_erase(&call->sock_node, &rx->calls); 279999b69f8SDavid Howells write_unlock(&rx->call_lock); 280fff72429SDavid Howells rxrpc_put_call(call, rxrpc_call_put_userid); 281999b69f8SDavid Howells 282999b69f8SDavid Howells write_lock_bh(&rxrpc_call_lock); 283d1e858c5SDavid Howells list_del_init(&call->link); 284999b69f8SDavid Howells write_unlock_bh(&rxrpc_call_lock); 285999b69f8SDavid Howells 2868d94aa38SDavid Howells error_out: 2878d94aa38SDavid Howells __rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR, 2888d94aa38SDavid Howells RX_CALL_DEAD, ret); 28917b963e3SDavid Howells set_bit(RXRPC_CALL_RELEASED, &call->flags); 290fff72429SDavid Howells rxrpc_put_call(call, rxrpc_call_put); 291999b69f8SDavid Howells _leave(" = %d", ret); 292999b69f8SDavid Howells return ERR_PTR(ret); 293999b69f8SDavid Howells 2948c3e34a4SDavid Howells /* We unexpectedly found the user ID in the list after taking 2958c3e34a4SDavid Howells * the call_lock. This shouldn't happen unless the user races 2968c3e34a4SDavid Howells * with itself and tries to add the same user ID twice at the 2978c3e34a4SDavid Howells * same time in different threads. 2988c3e34a4SDavid Howells */ 2998c3e34a4SDavid Howells found_user_ID_now_present: 3008c3e34a4SDavid Howells write_unlock(&rx->call_lock); 3018d94aa38SDavid Howells ret = -EEXIST; 3028d94aa38SDavid Howells goto error_out; 3038c3e34a4SDavid Howells } 3048c3e34a4SDavid Howells 3058c3e34a4SDavid Howells /* 3068c3e34a4SDavid Howells * set up an incoming call 3078c3e34a4SDavid Howells * - called in process context with IRQs enabled 3088c3e34a4SDavid Howells */ 3098c3e34a4SDavid Howells struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *rx, 3108c3e34a4SDavid Howells struct rxrpc_connection *conn, 31142886ffeSDavid Howells struct sk_buff *skb) 3128c3e34a4SDavid Howells { 31342886ffeSDavid Howells struct rxrpc_skb_priv *sp = rxrpc_skb(skb); 3148c3e34a4SDavid Howells struct rxrpc_call *call, *candidate; 315e34d4234SDavid Howells const void *here = __builtin_return_address(0); 316a1399f8bSDavid Howells u32 call_id, chan; 3178c3e34a4SDavid Howells 3188c3e34a4SDavid Howells _enter(",%d", conn->debug_id); 3198c3e34a4SDavid Howells 3208c3e34a4SDavid Howells ASSERT(rx != NULL); 3218c3e34a4SDavid Howells 3228c3e34a4SDavid Howells candidate = rxrpc_alloc_call(GFP_NOIO); 3238c3e34a4SDavid Howells if (!candidate) 3248c3e34a4SDavid Howells return ERR_PTR(-EBUSY); 3258c3e34a4SDavid Howells 326fff72429SDavid Howells trace_rxrpc_call(candidate, rxrpc_call_new_service, 3272ab27215SDavid Howells atomic_read(&candidate->usage), here, NULL); 328e34d4234SDavid Howells 329a1399f8bSDavid Howells chan = sp->hdr.cid & RXRPC_CHANNELMASK; 3308c3e34a4SDavid Howells candidate->conn = conn; 331df5d8bf7SDavid Howells candidate->peer = conn->params.peer; 33242886ffeSDavid Howells candidate->cid = sp->hdr.cid; 33342886ffeSDavid Howells candidate->call_id = sp->hdr.callNumber; 334278ac0cdSDavid Howells candidate->security_ix = sp->hdr.securityIndex; 3358c3e34a4SDavid Howells candidate->rx_data_post = 0; 3368c3e34a4SDavid Howells candidate->state = RXRPC_CALL_SERVER_ACCEPTING; 337dabe5a79SDavid Howells candidate->flags |= (1 << RXRPC_CALL_IS_SERVICE); 3388c3e34a4SDavid Howells if (conn->security_ix > 0) 3398c3e34a4SDavid Howells candidate->state = RXRPC_CALL_SERVER_SECURING; 3408d94aa38SDavid Howells rcu_assign_pointer(candidate->socket, rx); 3418c3e34a4SDavid Howells 342a1399f8bSDavid Howells spin_lock(&conn->channel_lock); 3438c3e34a4SDavid Howells 3448c3e34a4SDavid Howells /* set the channel for this call */ 345a1399f8bSDavid Howells call = rcu_dereference_protected(conn->channels[chan].call, 346a1399f8bSDavid Howells lockdep_is_held(&conn->channel_lock)); 347a1399f8bSDavid Howells 34801a90a45SDavid Howells _debug("channel[%u] is %p", candidate->cid & RXRPC_CHANNELMASK, call); 34942886ffeSDavid Howells if (call && call->call_id == sp->hdr.callNumber) { 3508c3e34a4SDavid Howells /* already set; must've been a duplicate packet */ 3518c3e34a4SDavid Howells _debug("extant call [%d]", call->state); 3528c3e34a4SDavid Howells ASSERTCMP(call->conn, ==, conn); 3538c3e34a4SDavid Howells 3548c3e34a4SDavid Howells read_lock(&call->state_lock); 3558c3e34a4SDavid Howells switch (call->state) { 3568c3e34a4SDavid Howells case RXRPC_CALL_LOCALLY_ABORTED: 3578c3e34a4SDavid Howells if (!test_and_set_bit(RXRPC_CALL_EV_ABORT, &call->events)) 3588c3e34a4SDavid Howells rxrpc_queue_call(call); 3598c3e34a4SDavid Howells case RXRPC_CALL_REMOTELY_ABORTED: 3608c3e34a4SDavid Howells read_unlock(&call->state_lock); 3618c3e34a4SDavid Howells goto aborted_call; 3628c3e34a4SDavid Howells default: 363fff72429SDavid Howells rxrpc_get_call(call, rxrpc_call_got); 3648c3e34a4SDavid Howells read_unlock(&call->state_lock); 3658c3e34a4SDavid Howells goto extant_call; 3668c3e34a4SDavid Howells } 3678c3e34a4SDavid Howells } 3688c3e34a4SDavid Howells 3698c3e34a4SDavid Howells if (call) { 3708c3e34a4SDavid Howells /* it seems the channel is still in use from the previous call 3718c3e34a4SDavid Howells * - ditch the old binding if its call is now complete */ 3728c3e34a4SDavid Howells _debug("CALL: %u { %s }", 3738c3e34a4SDavid Howells call->debug_id, rxrpc_call_states[call->state]); 3748c3e34a4SDavid Howells 375f5c17aaeSDavid Howells if (call->state == RXRPC_CALL_COMPLETE) { 37645025bceSDavid Howells __rxrpc_disconnect_call(conn, call); 3778c3e34a4SDavid Howells } else { 378a1399f8bSDavid Howells spin_unlock(&conn->channel_lock); 3798c3e34a4SDavid Howells kmem_cache_free(rxrpc_call_jar, candidate); 3808c3e34a4SDavid Howells _leave(" = -EBUSY"); 3818c3e34a4SDavid Howells return ERR_PTR(-EBUSY); 3828c3e34a4SDavid Howells } 3838c3e34a4SDavid Howells } 3848c3e34a4SDavid Howells 3858c3e34a4SDavid Howells /* check the call number isn't duplicate */ 3868c3e34a4SDavid Howells _debug("check dup"); 38742886ffeSDavid Howells call_id = sp->hdr.callNumber; 3888c3e34a4SDavid Howells 389a1399f8bSDavid Howells /* We just ignore calls prior to the current call ID. Terminated calls 390a1399f8bSDavid Howells * are handled via the connection. 3918c3e34a4SDavid Howells */ 392a1399f8bSDavid Howells if (call_id <= conn->channels[chan].call_counter) 393a1399f8bSDavid Howells goto old_call; /* TODO: Just drop packet */ 3948c3e34a4SDavid Howells 39500e90712SDavid Howells /* Temporary: Mirror the backlog prealloc ref (TODO: use prealloc) */ 39600e90712SDavid Howells rxrpc_get_call(candidate, rxrpc_call_got); 39700e90712SDavid Howells 3988c3e34a4SDavid Howells /* make the call available */ 3998c3e34a4SDavid Howells _debug("new call"); 4008c3e34a4SDavid Howells call = candidate; 4018c3e34a4SDavid Howells candidate = NULL; 402a1399f8bSDavid Howells conn->channels[chan].call_counter = call_id; 403a1399f8bSDavid Howells rcu_assign_pointer(conn->channels[chan].call, call); 4045627cc8bSDavid Howells rxrpc_get_connection(conn); 405df5d8bf7SDavid Howells rxrpc_get_peer(call->peer); 406a1399f8bSDavid Howells spin_unlock(&conn->channel_lock); 4078c3e34a4SDavid Howells 40885f32278SDavid Howells spin_lock(&conn->params.peer->lock); 40985f32278SDavid Howells hlist_add_head(&call->error_link, &conn->params.peer->error_targets); 41085f32278SDavid Howells spin_unlock(&conn->params.peer->lock); 4118c3e34a4SDavid Howells 4128c3e34a4SDavid Howells write_lock_bh(&rxrpc_call_lock); 4138c3e34a4SDavid Howells list_add_tail(&call->link, &rxrpc_calls); 4148c3e34a4SDavid Howells write_unlock_bh(&rxrpc_call_lock); 4158c3e34a4SDavid Howells 41619ffa01cSDavid Howells call->service_id = conn->params.service_id; 4178c3e34a4SDavid Howells 4188c3e34a4SDavid Howells _net("CALL incoming %d on CONN %d", call->debug_id, call->conn->debug_id); 4198c3e34a4SDavid Howells 4208c3e34a4SDavid Howells call->lifetimer.expires = jiffies + rxrpc_max_call_lifetime; 4218c3e34a4SDavid Howells add_timer(&call->lifetimer); 4228c3e34a4SDavid Howells _leave(" = %p {%d} [new]", call, call->debug_id); 4238c3e34a4SDavid Howells return call; 4248c3e34a4SDavid Howells 4258c3e34a4SDavid Howells extant_call: 426a1399f8bSDavid Howells spin_unlock(&conn->channel_lock); 4278c3e34a4SDavid Howells kmem_cache_free(rxrpc_call_jar, candidate); 4288c3e34a4SDavid Howells _leave(" = %p {%d} [extant]", call, call ? call->debug_id : -1); 4298c3e34a4SDavid Howells return call; 4308c3e34a4SDavid Howells 4318c3e34a4SDavid Howells aborted_call: 432a1399f8bSDavid Howells spin_unlock(&conn->channel_lock); 4338c3e34a4SDavid Howells kmem_cache_free(rxrpc_call_jar, candidate); 4348c3e34a4SDavid Howells _leave(" = -ECONNABORTED"); 4358c3e34a4SDavid Howells return ERR_PTR(-ECONNABORTED); 4368c3e34a4SDavid Howells 4378c3e34a4SDavid Howells old_call: 438a1399f8bSDavid Howells spin_unlock(&conn->channel_lock); 4398c3e34a4SDavid Howells kmem_cache_free(rxrpc_call_jar, candidate); 4408c3e34a4SDavid Howells _leave(" = -ECONNRESET [old]"); 4418c3e34a4SDavid Howells return ERR_PTR(-ECONNRESET); 4428c3e34a4SDavid Howells } 4438c3e34a4SDavid Howells 4448c3e34a4SDavid Howells /* 4458d94aa38SDavid Howells * Queue a call's work processor, getting a ref to pass to the work queue. 4468d94aa38SDavid Howells */ 4478d94aa38SDavid Howells bool rxrpc_queue_call(struct rxrpc_call *call) 4488d94aa38SDavid Howells { 4498d94aa38SDavid Howells const void *here = __builtin_return_address(0); 4508d94aa38SDavid Howells int n = __atomic_add_unless(&call->usage, 1, 0); 4518d94aa38SDavid Howells if (n == 0) 4528d94aa38SDavid Howells return false; 4538d94aa38SDavid Howells if (rxrpc_queue_work(&call->processor)) 4542ab27215SDavid Howells trace_rxrpc_call(call, rxrpc_call_queued, n + 1, here, NULL); 4558d94aa38SDavid Howells else 4568d94aa38SDavid Howells rxrpc_put_call(call, rxrpc_call_put_noqueue); 4578d94aa38SDavid Howells return true; 4588d94aa38SDavid Howells } 4598d94aa38SDavid Howells 4608d94aa38SDavid Howells /* 4618d94aa38SDavid Howells * Queue a call's work processor, passing the callers ref to the work queue. 4628d94aa38SDavid Howells */ 4638d94aa38SDavid Howells bool __rxrpc_queue_call(struct rxrpc_call *call) 4648d94aa38SDavid Howells { 4658d94aa38SDavid Howells const void *here = __builtin_return_address(0); 4668d94aa38SDavid Howells int n = atomic_read(&call->usage); 4678d94aa38SDavid Howells ASSERTCMP(n, >=, 1); 4688d94aa38SDavid Howells if (rxrpc_queue_work(&call->processor)) 4692ab27215SDavid Howells trace_rxrpc_call(call, rxrpc_call_queued_ref, n, here, NULL); 4708d94aa38SDavid Howells else 4718d94aa38SDavid Howells rxrpc_put_call(call, rxrpc_call_put_noqueue); 4728d94aa38SDavid Howells return true; 4738d94aa38SDavid Howells } 4748d94aa38SDavid Howells 4758d94aa38SDavid Howells /* 476e34d4234SDavid Howells * Note the re-emergence of a call. 477e34d4234SDavid Howells */ 478e34d4234SDavid Howells void rxrpc_see_call(struct rxrpc_call *call) 479e34d4234SDavid Howells { 480e34d4234SDavid Howells const void *here = __builtin_return_address(0); 481e34d4234SDavid Howells if (call) { 482e34d4234SDavid Howells int n = atomic_read(&call->usage); 483e34d4234SDavid Howells 4842ab27215SDavid Howells trace_rxrpc_call(call, rxrpc_call_seen, n, here, NULL); 485e34d4234SDavid Howells } 486e34d4234SDavid Howells } 487e34d4234SDavid Howells 488e34d4234SDavid Howells /* 489e34d4234SDavid Howells * Note the addition of a ref on a call. 490e34d4234SDavid Howells */ 491fff72429SDavid Howells void rxrpc_get_call(struct rxrpc_call *call, enum rxrpc_call_trace op) 492e34d4234SDavid Howells { 493e34d4234SDavid Howells const void *here = __builtin_return_address(0); 494e34d4234SDavid Howells int n = atomic_inc_return(&call->usage); 495e34d4234SDavid Howells 4962ab27215SDavid Howells trace_rxrpc_call(call, op, n, here, NULL); 497e34d4234SDavid Howells } 498e34d4234SDavid Howells 499e34d4234SDavid Howells /* 500e34d4234SDavid Howells * Note the addition of a ref on a call for a socket buffer. 501e34d4234SDavid Howells */ 502e34d4234SDavid Howells void rxrpc_get_call_for_skb(struct rxrpc_call *call, struct sk_buff *skb) 503e34d4234SDavid Howells { 504e34d4234SDavid Howells const void *here = __builtin_return_address(0); 505e34d4234SDavid Howells int n = atomic_inc_return(&call->usage); 506e34d4234SDavid Howells 5072ab27215SDavid Howells trace_rxrpc_call(call, rxrpc_call_got_skb, n, here, skb); 508e34d4234SDavid Howells } 509e34d4234SDavid Howells 510e34d4234SDavid Howells /* 5118c3e34a4SDavid Howells * detach a call from a socket and set up for release 5128c3e34a4SDavid Howells */ 5138d94aa38SDavid Howells void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call) 5148c3e34a4SDavid Howells { 5158c3e34a4SDavid Howells _enter("{%d,%d,%d,%d}", 5168c3e34a4SDavid Howells call->debug_id, atomic_read(&call->usage), 5178c3e34a4SDavid Howells atomic_read(&call->ackr_not_idle), 5188c3e34a4SDavid Howells call->rx_first_oos); 5198c3e34a4SDavid Howells 520e34d4234SDavid Howells rxrpc_see_call(call); 521e34d4234SDavid Howells 5228c3e34a4SDavid Howells spin_lock_bh(&call->lock); 5238c3e34a4SDavid Howells if (test_and_set_bit(RXRPC_CALL_RELEASED, &call->flags)) 5248c3e34a4SDavid Howells BUG(); 5258c3e34a4SDavid Howells spin_unlock_bh(&call->lock); 5268c3e34a4SDavid Howells 5278c3e34a4SDavid Howells /* dissociate from the socket 5288c3e34a4SDavid Howells * - the socket's ref on the call is passed to the death timer 5298c3e34a4SDavid Howells */ 5308d94aa38SDavid Howells _debug("RELEASE CALL %p (%d)", call, call->debug_id); 5318c3e34a4SDavid Howells 532f4fdb352SDavid Howells if (call->peer) { 533f4fdb352SDavid Howells spin_lock(&call->peer->lock); 534e653cfe4SDavid Howells hlist_del_init(&call->error_link); 535f4fdb352SDavid Howells spin_unlock(&call->peer->lock); 536f4fdb352SDavid Howells } 537e653cfe4SDavid Howells 5388c3e34a4SDavid Howells write_lock_bh(&rx->call_lock); 5398c3e34a4SDavid Howells if (!list_empty(&call->accept_link)) { 5408c3e34a4SDavid Howells _debug("unlinking once-pending call %p { e=%lx f=%lx }", 5418c3e34a4SDavid Howells call, call->events, call->flags); 5428c3e34a4SDavid Howells ASSERT(!test_bit(RXRPC_CALL_HAS_USERID, &call->flags)); 5438c3e34a4SDavid Howells list_del_init(&call->accept_link); 5448c3e34a4SDavid Howells sk_acceptq_removed(&rx->sk); 5458c3e34a4SDavid Howells } else if (test_bit(RXRPC_CALL_HAS_USERID, &call->flags)) { 5468c3e34a4SDavid Howells rb_erase(&call->sock_node, &rx->calls); 5478c3e34a4SDavid Howells memset(&call->sock_node, 0xdd, sizeof(call->sock_node)); 5488c3e34a4SDavid Howells clear_bit(RXRPC_CALL_HAS_USERID, &call->flags); 5498d94aa38SDavid Howells rxrpc_put_call(call, rxrpc_call_put_userid); 5508c3e34a4SDavid Howells } 5518c3e34a4SDavid Howells write_unlock_bh(&rx->call_lock); 5528c3e34a4SDavid Howells 5538c3e34a4SDavid Howells /* free up the channel for reuse */ 5548d94aa38SDavid Howells if (call->state == RXRPC_CALL_CLIENT_FINAL_ACK) { 5558d94aa38SDavid Howells clear_bit(RXRPC_CALL_EV_ACK_FINAL, &call->events); 5568d94aa38SDavid Howells rxrpc_send_call_packet(call, RXRPC_PACKET_TYPE_ACK); 5578d94aa38SDavid Howells rxrpc_call_completed(call); 5588d94aa38SDavid Howells } else { 559a1399f8bSDavid Howells write_lock_bh(&call->state_lock); 5608c3e34a4SDavid Howells 5618d94aa38SDavid Howells if (call->state < RXRPC_CALL_COMPLETE) { 5628c3e34a4SDavid Howells _debug("+++ ABORTING STATE %d +++\n", call->state); 5635a42976dSDavid Howells __rxrpc_abort_call("SKT", call, 0, RX_CALL_DEAD, ECONNRESET); 5648d94aa38SDavid Howells clear_bit(RXRPC_CALL_EV_ACK_FINAL, &call->events); 5658d94aa38SDavid Howells rxrpc_send_call_packet(call, RXRPC_PACKET_TYPE_ABORT); 5668c3e34a4SDavid Howells } 5678c3e34a4SDavid Howells 5688d94aa38SDavid Howells write_unlock_bh(&call->state_lock); 5698d94aa38SDavid Howells } 5708d94aa38SDavid Howells 5718d94aa38SDavid Howells if (call->conn) 572e653cfe4SDavid Howells rxrpc_disconnect_call(call); 573e653cfe4SDavid Howells 5748c3e34a4SDavid Howells /* clean up the Rx queue */ 5758c3e34a4SDavid Howells if (!skb_queue_empty(&call->rx_queue) || 5768c3e34a4SDavid Howells !skb_queue_empty(&call->rx_oos_queue)) { 5778c3e34a4SDavid Howells struct rxrpc_skb_priv *sp; 5788c3e34a4SDavid Howells struct sk_buff *skb; 5798c3e34a4SDavid Howells 5808c3e34a4SDavid Howells _debug("purge Rx queues"); 5818c3e34a4SDavid Howells 5828c3e34a4SDavid Howells spin_lock_bh(&call->lock); 5838c3e34a4SDavid Howells while ((skb = skb_dequeue(&call->rx_queue)) || 5848c3e34a4SDavid Howells (skb = skb_dequeue(&call->rx_oos_queue))) { 5858c3e34a4SDavid Howells spin_unlock_bh(&call->lock); 5868c3e34a4SDavid Howells 58755cae7a4SArnd Bergmann sp = rxrpc_skb(skb); 5888c3e34a4SDavid Howells _debug("- zap %s %%%u #%u", 5898c3e34a4SDavid Howells rxrpc_pkts[sp->hdr.type], 5908c3e34a4SDavid Howells sp->hdr.serial, sp->hdr.seq); 5918c3e34a4SDavid Howells rxrpc_free_skb(skb); 5928c3e34a4SDavid Howells spin_lock_bh(&call->lock); 5938c3e34a4SDavid Howells } 5948c3e34a4SDavid Howells spin_unlock_bh(&call->lock); 5958c3e34a4SDavid Howells } 5968d94aa38SDavid Howells rxrpc_purge_queue(&call->knlrecv_queue); 5978c3e34a4SDavid Howells 5988c3e34a4SDavid Howells del_timer_sync(&call->resend_timer); 5998c3e34a4SDavid Howells del_timer_sync(&call->ack_timer); 6008c3e34a4SDavid Howells del_timer_sync(&call->lifetimer); 6018c3e34a4SDavid Howells 60200e90712SDavid Howells /* We have to release the prealloc backlog ref */ 60300e90712SDavid Howells if (rxrpc_is_service_call(call)) 60400e90712SDavid Howells rxrpc_put_call(call, rxrpc_call_put); 6058c3e34a4SDavid Howells _leave(""); 6068c3e34a4SDavid Howells } 6078c3e34a4SDavid Howells 6088c3e34a4SDavid Howells /* 6098c3e34a4SDavid Howells * release all the calls associated with a socket 6108c3e34a4SDavid Howells */ 6118c3e34a4SDavid Howells void rxrpc_release_calls_on_socket(struct rxrpc_sock *rx) 6128c3e34a4SDavid Howells { 6138c3e34a4SDavid Howells struct rxrpc_call *call; 6148c3e34a4SDavid Howells struct rb_node *p; 6158c3e34a4SDavid Howells 6168c3e34a4SDavid Howells _enter("%p", rx); 6178c3e34a4SDavid Howells 6188c3e34a4SDavid Howells read_lock_bh(&rx->call_lock); 6198c3e34a4SDavid Howells 6208c3e34a4SDavid Howells /* kill the not-yet-accepted incoming calls */ 6218c3e34a4SDavid Howells list_for_each_entry(call, &rx->secureq, accept_link) { 6228d94aa38SDavid Howells rxrpc_release_call(rx, call); 6238c3e34a4SDavid Howells } 6248c3e34a4SDavid Howells 6258c3e34a4SDavid Howells list_for_each_entry(call, &rx->acceptq, accept_link) { 6268d94aa38SDavid Howells rxrpc_release_call(rx, call); 6278c3e34a4SDavid Howells } 6288c3e34a4SDavid Howells 629f36b5e44SDavid Howells /* mark all the calls as no longer wanting incoming packets */ 630f36b5e44SDavid Howells for (p = rb_first(&rx->calls); p; p = rb_next(p)) { 631f36b5e44SDavid Howells call = rb_entry(p, struct rxrpc_call, sock_node); 6328d94aa38SDavid Howells rxrpc_release_call(rx, call); 633f36b5e44SDavid Howells } 634f36b5e44SDavid Howells 6358c3e34a4SDavid Howells read_unlock_bh(&rx->call_lock); 6368c3e34a4SDavid Howells _leave(""); 6378c3e34a4SDavid Howells } 6388c3e34a4SDavid Howells 6398c3e34a4SDavid Howells /* 6408c3e34a4SDavid Howells * release a call 6418c3e34a4SDavid Howells */ 642fff72429SDavid Howells void rxrpc_put_call(struct rxrpc_call *call, enum rxrpc_call_trace op) 6438c3e34a4SDavid Howells { 644e34d4234SDavid Howells const void *here = __builtin_return_address(0); 6452ab27215SDavid Howells int n; 646e34d4234SDavid Howells 6478c3e34a4SDavid Howells ASSERT(call != NULL); 6488c3e34a4SDavid Howells 649e34d4234SDavid Howells n = atomic_dec_return(&call->usage); 6502ab27215SDavid Howells trace_rxrpc_call(call, op, n, here, NULL); 651e34d4234SDavid Howells ASSERTCMP(n, >=, 0); 652e34d4234SDavid Howells if (n == 0) { 6538c3e34a4SDavid Howells _debug("call %d dead", call->debug_id); 6548d94aa38SDavid Howells rxrpc_cleanup_call(call); 6558c3e34a4SDavid Howells } 656e34d4234SDavid Howells } 657e34d4234SDavid Howells 658e34d4234SDavid Howells /* 659e34d4234SDavid Howells * Release a call ref held by a socket buffer. 660e34d4234SDavid Howells */ 661e34d4234SDavid Howells void rxrpc_put_call_for_skb(struct rxrpc_call *call, struct sk_buff *skb) 662e34d4234SDavid Howells { 663e34d4234SDavid Howells const void *here = __builtin_return_address(0); 6642ab27215SDavid Howells int n; 665e34d4234SDavid Howells 666e34d4234SDavid Howells n = atomic_dec_return(&call->usage); 6672ab27215SDavid Howells trace_rxrpc_call(call, rxrpc_call_put_skb, n, here, skb); 668e34d4234SDavid Howells ASSERTCMP(n, >=, 0); 669e34d4234SDavid Howells if (n == 0) { 670e34d4234SDavid Howells _debug("call %d dead", call->debug_id); 6718d94aa38SDavid Howells rxrpc_cleanup_call(call); 672e34d4234SDavid Howells } 6738c3e34a4SDavid Howells } 6748c3e34a4SDavid Howells 6758c3e34a4SDavid Howells /* 676dee46364SDavid Howells * Final call destruction under RCU. 677dee46364SDavid Howells */ 678dee46364SDavid Howells static void rxrpc_rcu_destroy_call(struct rcu_head *rcu) 679dee46364SDavid Howells { 680dee46364SDavid Howells struct rxrpc_call *call = container_of(rcu, struct rxrpc_call, rcu); 681dee46364SDavid Howells 682dee46364SDavid Howells rxrpc_purge_queue(&call->rx_queue); 683d001648eSDavid Howells rxrpc_purge_queue(&call->knlrecv_queue); 684df5d8bf7SDavid Howells rxrpc_put_peer(call->peer); 685dee46364SDavid Howells kmem_cache_free(rxrpc_call_jar, call); 686dee46364SDavid Howells } 687dee46364SDavid Howells 688dee46364SDavid Howells /* 6898c3e34a4SDavid Howells * clean up a call 6908c3e34a4SDavid Howells */ 69100e90712SDavid Howells void rxrpc_cleanup_call(struct rxrpc_call *call) 6928c3e34a4SDavid Howells { 6938c3e34a4SDavid Howells _net("DESTROY CALL %d", call->debug_id); 6948c3e34a4SDavid Howells 6958d94aa38SDavid Howells write_lock_bh(&rxrpc_call_lock); 6968d94aa38SDavid Howells list_del_init(&call->link); 6978d94aa38SDavid Howells write_unlock_bh(&rxrpc_call_lock); 6988c3e34a4SDavid Howells 6998c3e34a4SDavid Howells memset(&call->sock_node, 0xcd, sizeof(call->sock_node)); 7008c3e34a4SDavid Howells 7018c3e34a4SDavid Howells del_timer_sync(&call->lifetimer); 7028c3e34a4SDavid Howells del_timer_sync(&call->ack_timer); 7038c3e34a4SDavid Howells del_timer_sync(&call->resend_timer); 7048c3e34a4SDavid Howells 7058d94aa38SDavid Howells ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE); 7068c3e34a4SDavid Howells ASSERT(test_bit(RXRPC_CALL_RELEASED, &call->flags)); 7078d94aa38SDavid Howells ASSERT(!work_pending(&call->processor)); 708e653cfe4SDavid Howells ASSERTCMP(call->conn, ==, NULL); 7098c3e34a4SDavid Howells 7108c3e34a4SDavid Howells if (call->acks_window) { 7118c3e34a4SDavid Howells _debug("kill Tx window %d", 7128c3e34a4SDavid Howells CIRC_CNT(call->acks_head, call->acks_tail, 7138c3e34a4SDavid Howells call->acks_winsz)); 7148c3e34a4SDavid Howells smp_mb(); 7158c3e34a4SDavid Howells while (CIRC_CNT(call->acks_head, call->acks_tail, 7168c3e34a4SDavid Howells call->acks_winsz) > 0) { 7178c3e34a4SDavid Howells struct rxrpc_skb_priv *sp; 7188c3e34a4SDavid Howells unsigned long _skb; 7198c3e34a4SDavid Howells 7208c3e34a4SDavid Howells _skb = call->acks_window[call->acks_tail] & ~1; 7218c3e34a4SDavid Howells sp = rxrpc_skb((struct sk_buff *)_skb); 7228c3e34a4SDavid Howells _debug("+++ clear Tx %u", sp->hdr.seq); 7238c3e34a4SDavid Howells rxrpc_free_skb((struct sk_buff *)_skb); 7248c3e34a4SDavid Howells call->acks_tail = 7258c3e34a4SDavid Howells (call->acks_tail + 1) & (call->acks_winsz - 1); 7268c3e34a4SDavid Howells } 7278c3e34a4SDavid Howells 7288c3e34a4SDavid Howells kfree(call->acks_window); 7298c3e34a4SDavid Howells } 7308c3e34a4SDavid Howells 7318c3e34a4SDavid Howells rxrpc_free_skb(call->tx_pending); 7328c3e34a4SDavid Howells 7338c3e34a4SDavid Howells rxrpc_purge_queue(&call->rx_queue); 7348c3e34a4SDavid Howells ASSERT(skb_queue_empty(&call->rx_oos_queue)); 735d001648eSDavid Howells rxrpc_purge_queue(&call->knlrecv_queue); 736dee46364SDavid Howells call_rcu(&call->rcu, rxrpc_rcu_destroy_call); 7378c3e34a4SDavid Howells } 7388c3e34a4SDavid Howells 7398c3e34a4SDavid Howells /* 7408d94aa38SDavid Howells * Make sure that all calls are gone. 7418c3e34a4SDavid Howells */ 7428c3e34a4SDavid Howells void __exit rxrpc_destroy_all_calls(void) 7438c3e34a4SDavid Howells { 7448c3e34a4SDavid Howells struct rxrpc_call *call; 7458c3e34a4SDavid Howells 7468c3e34a4SDavid Howells _enter(""); 7478d94aa38SDavid Howells 7488d94aa38SDavid Howells if (list_empty(&rxrpc_calls)) 7498d94aa38SDavid Howells return; 7508d94aa38SDavid Howells 7518c3e34a4SDavid Howells write_lock_bh(&rxrpc_call_lock); 7528c3e34a4SDavid Howells 7538c3e34a4SDavid Howells while (!list_empty(&rxrpc_calls)) { 7548c3e34a4SDavid Howells call = list_entry(rxrpc_calls.next, struct rxrpc_call, link); 7558c3e34a4SDavid Howells _debug("Zapping call %p", call); 7568c3e34a4SDavid Howells 757e34d4234SDavid Howells rxrpc_see_call(call); 7588c3e34a4SDavid Howells list_del_init(&call->link); 7598c3e34a4SDavid Howells 7608c3e34a4SDavid Howells pr_err("Call %p still in use (%d,%d,%s,%lx,%lx)!\n", 7618c3e34a4SDavid Howells call, atomic_read(&call->usage), 7628c3e34a4SDavid Howells atomic_read(&call->ackr_not_idle), 7638c3e34a4SDavid Howells rxrpc_call_states[call->state], 7648c3e34a4SDavid Howells call->flags, call->events); 7658c3e34a4SDavid Howells if (!skb_queue_empty(&call->rx_queue)) 7668c3e34a4SDavid Howells pr_err("Rx queue occupied\n"); 7678c3e34a4SDavid Howells if (!skb_queue_empty(&call->rx_oos_queue)) 7688c3e34a4SDavid Howells pr_err("OOS queue occupied\n"); 7698c3e34a4SDavid Howells 7708c3e34a4SDavid Howells write_unlock_bh(&rxrpc_call_lock); 7718c3e34a4SDavid Howells cond_resched(); 7728c3e34a4SDavid Howells write_lock_bh(&rxrpc_call_lock); 7738c3e34a4SDavid Howells } 7748c3e34a4SDavid Howells 7758c3e34a4SDavid Howells write_unlock_bh(&rxrpc_call_lock); 7768c3e34a4SDavid Howells _leave(""); 7778c3e34a4SDavid Howells } 7788c3e34a4SDavid Howells 7798c3e34a4SDavid Howells /* 7808c3e34a4SDavid Howells * handle call lifetime being exceeded 7818c3e34a4SDavid Howells */ 7828c3e34a4SDavid Howells static void rxrpc_call_life_expired(unsigned long _call) 7838c3e34a4SDavid Howells { 7848c3e34a4SDavid Howells struct rxrpc_call *call = (struct rxrpc_call *) _call; 7858c3e34a4SDavid Howells 786f5c17aaeSDavid Howells _enter("{%d}", call->debug_id); 787f5c17aaeSDavid Howells 788e34d4234SDavid Howells rxrpc_see_call(call); 7898c3e34a4SDavid Howells if (call->state >= RXRPC_CALL_COMPLETE) 7908c3e34a4SDavid Howells return; 7918c3e34a4SDavid Howells 7928c3e34a4SDavid Howells set_bit(RXRPC_CALL_EV_LIFE_TIMER, &call->events); 7938c3e34a4SDavid Howells rxrpc_queue_call(call); 7948c3e34a4SDavid Howells } 7958c3e34a4SDavid Howells 7968c3e34a4SDavid Howells /* 7978c3e34a4SDavid Howells * handle resend timer expiry 7988c3e34a4SDavid Howells * - may not take call->state_lock as this can deadlock against del_timer_sync() 7998c3e34a4SDavid Howells */ 8008c3e34a4SDavid Howells static void rxrpc_resend_time_expired(unsigned long _call) 8018c3e34a4SDavid Howells { 8028c3e34a4SDavid Howells struct rxrpc_call *call = (struct rxrpc_call *) _call; 8038c3e34a4SDavid Howells 8048c3e34a4SDavid Howells _enter("{%d}", call->debug_id); 8058c3e34a4SDavid Howells 806e34d4234SDavid Howells rxrpc_see_call(call); 8078c3e34a4SDavid Howells if (call->state >= RXRPC_CALL_COMPLETE) 8088c3e34a4SDavid Howells return; 8098c3e34a4SDavid Howells 8108c3e34a4SDavid Howells clear_bit(RXRPC_CALL_RUN_RTIMER, &call->flags); 8118c3e34a4SDavid Howells if (!test_and_set_bit(RXRPC_CALL_EV_RESEND_TIMER, &call->events)) 8128c3e34a4SDavid Howells rxrpc_queue_call(call); 8138c3e34a4SDavid Howells } 8148c3e34a4SDavid Howells 8158c3e34a4SDavid Howells /* 8168c3e34a4SDavid Howells * handle ACK timer expiry 8178c3e34a4SDavid Howells */ 8188c3e34a4SDavid Howells static void rxrpc_ack_time_expired(unsigned long _call) 8198c3e34a4SDavid Howells { 8208c3e34a4SDavid Howells struct rxrpc_call *call = (struct rxrpc_call *) _call; 8218c3e34a4SDavid Howells 8228c3e34a4SDavid Howells _enter("{%d}", call->debug_id); 8238c3e34a4SDavid Howells 824e34d4234SDavid Howells rxrpc_see_call(call); 8258c3e34a4SDavid Howells if (call->state >= RXRPC_CALL_COMPLETE) 8268c3e34a4SDavid Howells return; 8278c3e34a4SDavid Howells 828f5c17aaeSDavid Howells if (!test_and_set_bit(RXRPC_CALL_EV_ACK, &call->events)) 8298c3e34a4SDavid Howells rxrpc_queue_call(call); 8308c3e34a4SDavid Howells } 831