bool upgrade)
 {
        struct rxrpc_conn_parameters cp;
+       struct rxrpc_call_params p;
        struct rxrpc_call *call;
        struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
        int ret;
        if (key && !key->payload.data[0])
                key = NULL; /* a no-security key */
 
+       memset(&p, 0, sizeof(p));
+       p.user_call_ID = user_call_ID;
+       p.tx_total_len = tx_total_len;
+
        memset(&cp, 0, sizeof(cp));
        cp.local                = rx->local;
        cp.key                  = key;
        cp.exclusive            = false;
        cp.upgrade              = upgrade;
        cp.service_id           = srx->srx_service;
-       call = rxrpc_new_client_call(rx, &cp, srx, user_call_ID, tx_total_len,
-                                    gfp);
+       call = rxrpc_new_client_call(rx, &cp, srx, &p, gfp);
        /* The socket has been unlocked. */
        if (!IS_ERR(call)) {
                call->notify_rx = notify_rx;
 
        u8                      cumulative_acks;
 };
 
+/*
+ * sendmsg() cmsg-specified parameters.
+ */
+enum rxrpc_command {
+       RXRPC_CMD_SEND_DATA,            /* send data message */
+       RXRPC_CMD_SEND_ABORT,           /* request abort generation */
+       RXRPC_CMD_ACCEPT,               /* [server] accept incoming call */
+       RXRPC_CMD_REJECT_BUSY,          /* [server] reject a call as busy */
+};
+
+struct rxrpc_call_params {
+       s64                     tx_total_len;   /* Total Tx data length (if send data) */
+       unsigned long           user_call_ID;   /* User's call ID */
+       struct {
+               u32             hard;           /* Maximum lifetime (sec) */
+               u32             idle;           /* Max time since last data packet (msec) */
+               u32             normal;         /* Max time since last call packet (msec) */
+       } timeouts;
+       u8                      nr_timeouts;    /* Number of timeouts specified */
+};
+
+struct rxrpc_send_params {
+       struct rxrpc_call_params call;
+       u32                     abort_code;     /* Abort code to Tx (if abort) */
+       enum rxrpc_command      command : 8;    /* The command to implement */
+       bool                    exclusive;      /* Shared or exclusive call */
+       bool                    upgrade;        /* If the connection is upgradeable */
+};
+
 #include <trace/events/rxrpc.h>
 
 /*
 struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *,
                                         struct rxrpc_conn_parameters *,
                                         struct sockaddr_rxrpc *,
-                                        unsigned long, s64, gfp_t);
+                                        struct rxrpc_call_params *, gfp_t);
 int rxrpc_retry_client_call(struct rxrpc_sock *,
                            struct rxrpc_call *,
                            struct rxrpc_conn_parameters *,
 
 struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
                                         struct rxrpc_conn_parameters *cp,
                                         struct sockaddr_rxrpc *srx,
-                                        unsigned long user_call_ID,
-                                        s64 tx_total_len,
+                                        struct rxrpc_call_params *p,
                                         gfp_t gfp)
        __releases(&rx->sk.sk_lock.slock)
 {
        const void *here = __builtin_return_address(0);
        int ret;
 
-       _enter("%p,%lx", rx, user_call_ID);
+       _enter("%p,%lx", rx, p->user_call_ID);
 
        call = rxrpc_alloc_client_call(rx, srx, gfp);
        if (IS_ERR(call)) {
                return call;
        }
 
-       call->tx_total_len = tx_total_len;
+       call->tx_total_len = p->tx_total_len;
        trace_rxrpc_call(call, rxrpc_call_new_client, atomic_read(&call->usage),
-                        here, (const void *)user_call_ID);
+                        here, (const void *)p->user_call_ID);
 
        /* We need to protect a partially set up call against the user as we
         * will be acting outside the socket lock.
                parent = *pp;
                xcall = rb_entry(parent, struct rxrpc_call, sock_node);
 
-               if (user_call_ID < xcall->user_call_ID)
+               if (p->user_call_ID < xcall->user_call_ID)
                        pp = &(*pp)->rb_left;
-               else if (user_call_ID > xcall->user_call_ID)
+               else if (p->user_call_ID > xcall->user_call_ID)
                        pp = &(*pp)->rb_right;
                else
                        goto error_dup_user_ID;
        }
 
        rcu_assign_pointer(call->socket, rx);
-       call->user_call_ID = user_call_ID;
+       call->user_call_ID = p->user_call_ID;
        __set_bit(RXRPC_CALL_HAS_USERID, &call->flags);
        rxrpc_get_call(call, rxrpc_call_got_userid);
        rb_link_node(&call->sock_node, parent, pp);
 
 #include <net/af_rxrpc.h>
 #include "ar-internal.h"
 
-enum rxrpc_command {
-       RXRPC_CMD_SEND_DATA,            /* send data message */
-       RXRPC_CMD_SEND_ABORT,           /* request abort generation */
-       RXRPC_CMD_ACCEPT,               /* [server] accept incoming call */
-       RXRPC_CMD_REJECT_BUSY,          /* [server] reject a call as busy */
-};
-
-struct rxrpc_send_params {
-       s64                     tx_total_len;   /* Total Tx data length (if send data) */
-       unsigned long           user_call_ID;   /* User's call ID */
-       u32                     abort_code;     /* Abort code to Tx (if abort) */
-       enum rxrpc_command      command : 8;    /* The command to implement */
-       bool                    exclusive;      /* Shared or exclusive call */
-       bool                    upgrade;        /* If the connection is upgradeable */
-};
-
 /*
  * Wait for space to appear in the Tx queue or a signal to occur.
  */
                        if (msg->msg_flags & MSG_CMSG_COMPAT) {
                                if (len != sizeof(u32))
                                        return -EINVAL;
-                               p->user_call_ID = *(u32 *)CMSG_DATA(cmsg);
+                               p->call.user_call_ID = *(u32 *)CMSG_DATA(cmsg);
                        } else {
                                if (len != sizeof(unsigned long))
                                        return -EINVAL;
-                               p->user_call_ID = *(unsigned long *)
+                               p->call.user_call_ID = *(unsigned long *)
                                        CMSG_DATA(cmsg);
                        }
                        got_user_ID = true;
                        break;
 
                case RXRPC_TX_LENGTH:
-                       if (p->tx_total_len != -1 || len != sizeof(__s64))
+                       if (p->call.tx_total_len != -1 || len != sizeof(__s64))
                                return -EINVAL;
-                       p->tx_total_len = *(__s64 *)CMSG_DATA(cmsg);
-                       if (p->tx_total_len < 0)
+                       p->call.tx_total_len = *(__s64 *)CMSG_DATA(cmsg);
+                       if (p->call.tx_total_len < 0)
                                return -EINVAL;
                        break;
 
 
        if (!got_user_ID)
                return -EINVAL;
-       if (p->tx_total_len != -1 && p->command != RXRPC_CMD_SEND_DATA)
+       if (p->call.tx_total_len != -1 && p->command != RXRPC_CMD_SEND_DATA)
                return -EINVAL;
        _leave(" = 0");
        return 0;
        cp.exclusive            = rx->exclusive | p->exclusive;
        cp.upgrade              = p->upgrade;
        cp.service_id           = srx->srx_service;
-       call = rxrpc_new_client_call(rx, &cp, srx, p->user_call_ID,
-                                    p->tx_total_len, GFP_KERNEL);
+       call = rxrpc_new_client_call(rx, &cp, srx, &p->call, GFP_KERNEL);
        /* The socket is now unlocked */
 
        _leave(" = %p\n", call);
        int ret;
 
        struct rxrpc_send_params p = {
-               .tx_total_len   = -1,
-               .user_call_ID   = 0,
-               .abort_code     = 0,
-               .command        = RXRPC_CMD_SEND_DATA,
-               .exclusive      = false,
-               .upgrade        = false,
+               .call.tx_total_len      = -1,
+               .call.user_call_ID      = 0,
+               .abort_code             = 0,
+               .command                = RXRPC_CMD_SEND_DATA,
+               .exclusive              = false,
+               .upgrade                = false,
        };
 
        _enter("");
                ret = -EINVAL;
                if (rx->sk.sk_state != RXRPC_SERVER_LISTENING)
                        goto error_release_sock;
-               call = rxrpc_accept_call(rx, p.user_call_ID, NULL);
+               call = rxrpc_accept_call(rx, p.call.user_call_ID, NULL);
                /* The socket is now unlocked. */
                if (IS_ERR(call))
                        return PTR_ERR(call);
                goto out_put_unlock;
        }
 
-       call = rxrpc_find_call_by_user_ID(rx, p.user_call_ID);
+       call = rxrpc_find_call_by_user_ID(rx, p.call.user_call_ID);
        if (!call) {
                ret = -EBADSLT;
                if (p.command != RXRPC_CMD_SEND_DATA)
                        goto error_put;
                }
 
-               if (p.tx_total_len != -1) {
+               if (p.call.tx_total_len != -1) {
                        ret = -EINVAL;
                        if (call->tx_total_len != -1 ||
                            call->tx_pending ||
                            call->tx_top != 0)
                                goto error_put;
-                       call->tx_total_len = p.tx_total_len;
+                       call->tx_total_len = p.call.tx_total_len;
                }
        }