struct afs_addr_cursor ac = {
                .index = 0,
        };
+       struct afs_call *call;
        bool in_progress = false;
-       int err;
 
        _enter("%pU", &server->uuid);
 
        server->probe.rtt = UINT_MAX;
 
        for (ac.index = 0; ac.index < ac.alist->nr_addrs; ac.index++) {
-               err = afs_fs_get_capabilities(net, server, &ac, key, server_index,
-                                             true);
-               if (err == -EINPROGRESS)
+               call = afs_fs_get_capabilities(net, server, &ac, key, server_index);
+               if (!IS_ERR(call)) {
+                       afs_put_call(call);
                        in_progress = true;
-               else
-                       afs_prioritise_error(_e, err, ac.abort_code);
+               } else {
+                       afs_prioritise_error(_e, PTR_ERR(call), ac.abort_code);
+               }
        }
 
        if (!in_progress)
 
        call->cb_break = fc->cb_break;
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
        call->cb_break = fc->cb_break;
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
        call->cb_break = fc->cb_break;
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &dvnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &orig_dvnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
        *bp++ = htonl((u32) i_size);
 
        trace_afs_make_fs_call(call, &vnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
        *bp++ = htonl(FSGIVEUPALLCALLBACKS);
 
        /* Can't take a ref on server */
-       return afs_make_call(ac, call, GFP_NOFS, false);
+       afs_make_call(ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, ac);
 }
 
 /*
  * Probe a fileserver for the capabilities that it supports.  This can
  * return up to 196 words.
  */
-int afs_fs_get_capabilities(struct afs_net *net,
-                           struct afs_server *server,
-                           struct afs_addr_cursor *ac,
-                           struct key *key,
-                           unsigned int server_index,
-                           bool async)
+struct afs_call *afs_fs_get_capabilities(struct afs_net *net,
+                                        struct afs_server *server,
+                                        struct afs_addr_cursor *ac,
+                                        struct key *key,
+                                        unsigned int server_index)
 {
        struct afs_call *call;
        __be32 *bp;
 
        call = afs_alloc_flat_call(net, &afs_RXFSGetCapabilities, 1 * 4, 16 * 4);
        if (!call)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
 
        call->key = key;
        call->reply[0] = afs_get_server(server);
        call->reply[1] = (void *)(long)server_index;
        call->upgrade = true;
        call->want_reply_time = true;
+       call->async = true;
 
        /* marshall the parameters */
        bp = call->request;
 
        /* Can't take a ref on server */
        trace_afs_make_fs_call(call, NULL);
-       return afs_make_call(ac, call, GFP_NOFS, async);
+       afs_make_call(ac, call, GFP_NOFS);
+       return call;
 }
 
 /*
        call->cb_break = fc->cb_break;
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
        call->cb_break = fc->cb_break;
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &fids[0]);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 extern int afs_fs_release_lock(struct afs_fs_cursor *);
 extern int afs_fs_give_up_all_callbacks(struct afs_net *, struct afs_server *,
                                        struct afs_addr_cursor *, struct key *);
-extern int afs_fs_get_capabilities(struct afs_net *, struct afs_server *,
-                                  struct afs_addr_cursor *, struct key *, unsigned int, bool);
+extern struct afs_call *afs_fs_get_capabilities(struct afs_net *, struct afs_server *,
+                                               struct afs_addr_cursor *, struct key *,
+                                               unsigned int);
 extern int afs_fs_inline_bulk_status(struct afs_fs_cursor *, struct afs_net *,
                                     struct afs_fid *, struct afs_file_status *,
                                     struct afs_callback *, unsigned int,
 extern void __net_exit afs_close_socket(struct afs_net *);
 extern void afs_charge_preallocation(struct work_struct *);
 extern void afs_put_call(struct afs_call *);
-extern long afs_make_call(struct afs_addr_cursor *, struct afs_call *, gfp_t, bool);
+extern void afs_make_call(struct afs_addr_cursor *, struct afs_call *, gfp_t);
+extern long afs_wait_for_call_to_complete(struct afs_call *, struct afs_addr_cursor *);
 extern struct afs_call *afs_alloc_flat_call(struct afs_net *,
                                            const struct afs_call_type *,
                                            size_t, size_t);
 extern struct afs_vldb_entry *afs_vl_get_entry_by_name_u(struct afs_vl_cursor *,
                                                         const char *, int);
 extern struct afs_addr_list *afs_vl_get_addrs_u(struct afs_vl_cursor *, const uuid_t *);
-extern int afs_vl_get_capabilities(struct afs_net *, struct afs_addr_cursor *, struct key *,
-                                  struct afs_vlserver *, unsigned int, bool);
+extern struct afs_call *afs_vl_get_capabilities(struct afs_net *, struct afs_addr_cursor *,
+                                               struct key *, struct afs_vlserver *, unsigned int);
 extern struct afs_addr_list *afs_yfsvl_get_endpoints(struct afs_vl_cursor *, const uuid_t *);
 
 /*
 
 struct workqueue_struct *afs_async_calls;
 
 static void afs_wake_up_call_waiter(struct sock *, struct rxrpc_call *, unsigned long);
-static long afs_wait_for_call_to_complete(struct afs_call *, struct afs_addr_cursor *);
 static void afs_wake_up_async_call(struct sock *, struct rxrpc_call *, unsigned long);
 static void afs_delete_async_call(struct work_struct *);
 static void afs_process_async_call(struct work_struct *);
 }
 
 /*
- * initiate a call
+ * Initiate a call and synchronously queue up the parameters for dispatch.  Any
+ * error is stored into the call struct, which the caller must check for.
  */
-long afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call,
-                  gfp_t gfp, bool async)
+void afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call, gfp_t gfp)
 {
        struct sockaddr_rxrpc *srx = &ac->alist->addrs[ac->index];
        struct rxrpc_call *rxcall;
               call, call->type->name, key_serial(call->key),
               atomic_read(&call->net->nr_outstanding_calls));
 
-       call->async = async;
        call->addr_ix = ac->index;
        call->alist = afs_get_addrlist(ac->alist);
 
        rxcall = rxrpc_kernel_begin_call(call->net->socket, srx, call->key,
                                         (unsigned long)call,
                                         tx_total_len, gfp,
-                                        (async ?
+                                        (call->async ?
                                          afs_wake_up_async_call :
                                          afs_wake_up_call_waiter),
                                         call->upgrade,
 
        /* Note that at this point, we may have received the reply or an abort
         * - and an asynchronous call may already have completed.
+        *
+        * afs_wait_for_call_to_complete(call, ac)
+        * must be called to synchronously clean up.
         */
-       if (call->async) {
-               afs_put_call(call);
-               return -EINPROGRESS;
-       }
-
-       return afs_wait_for_call_to_complete(call, ac);
+       return;
 
 error_do_abort:
        if (ret != -ECONNABORTED) {
 
        ac->error = ret;
        call->state = AFS_CALL_COMPLETE;
-       afs_put_call(call);
        _leave(" = %d", ret);
-       return ret;
 }
 
 /*
 }
 
 /*
- * wait synchronously for a call to complete
+ * Wait synchronously for a call to complete and clean up the call struct.
  */
-static long afs_wait_for_call_to_complete(struct afs_call *call,
-                                         struct afs_addr_cursor *ac)
+long afs_wait_for_call_to_complete(struct afs_call *call,
+                                  struct afs_addr_cursor *ac)
 {
        signed long rtt2, timeout;
        long ret;
 
        _enter("");
 
+       ret = call->error;
+       if (ret < 0)
+               goto out;
+
        rtt = rxrpc_kernel_get_rtt(call->net->socket, call->rxcall);
        rtt2 = nsecs_to_jiffies64(rtt) * 2;
        if (rtt2 < 2)
                break;
        }
 
+out:
        _debug("call complete");
        afs_put_call(call);
        _leave(" = %p", (void *)ret);
 
        struct afs_addr_cursor ac = {
                .index = 0,
        };
+       struct afs_call *call;
        bool in_progress = false;
-       int err;
 
        _enter("%s", server->name);
 
        server->probe.rtt = UINT_MAX;
 
        for (ac.index = 0; ac.index < ac.alist->nr_addrs; ac.index++) {
-               err = afs_vl_get_capabilities(net, &ac, key, server,
-                                             server_index, true);
-               if (err == -EINPROGRESS)
+               call = afs_vl_get_capabilities(net, &ac, key, server,
+                                              server_index);
+               if (!IS_ERR(call)) {
+                       afs_put_call(call);
                        in_progress = true;
-               else
-                       afs_prioritise_error(_e, err, ac.abort_code);
+               } else {
+                       afs_prioritise_error(_e, PTR_ERR(call), ac.abort_code);
+               }
        }
 
        if (!in_progress)
 
                memset((void *)bp + volnamesz, 0, padsz);
 
        trace_afs_make_vl_call(call);
-       return (struct afs_vldb_entry *)afs_make_call(&vc->ac, call, GFP_KERNEL, false);
+       afs_make_call(&vc->ac, call, GFP_KERNEL);
+       return (struct afs_vldb_entry *)afs_wait_for_call_to_complete(call, &vc->ac);
 }
 
 /*
                r->uuid.node[i] = htonl(u->node[i]);
 
        trace_afs_make_vl_call(call);
-       return (struct afs_addr_list *)afs_make_call(&vc->ac, call, GFP_KERNEL, false);
+       afs_make_call(&vc->ac, call, GFP_KERNEL);
+       return (struct afs_addr_list *)afs_wait_for_call_to_complete(call, &vc->ac);
 }
 
 /*
  * We use this to probe for service upgrade to determine what the server at the
  * other end supports.
  */
-int afs_vl_get_capabilities(struct afs_net *net,
-                           struct afs_addr_cursor *ac,
-                           struct key *key,
-                           struct afs_vlserver *server,
-                           unsigned int server_index,
-                           bool async)
+struct afs_call *afs_vl_get_capabilities(struct afs_net *net,
+                                        struct afs_addr_cursor *ac,
+                                        struct key *key,
+                                        struct afs_vlserver *server,
+                                        unsigned int server_index)
 {
        struct afs_call *call;
        __be32 *bp;
 
        call = afs_alloc_flat_call(net, &afs_RXVLGetCapabilities, 1 * 4, 16 * 4);
        if (!call)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
 
        call->key = key;
        call->reply[0] = afs_get_vlserver(server);
        call->reply[1] = (void *)(long)server_index;
        call->upgrade = true;
        call->want_reply_time = true;
+       call->async = true;
 
        /* marshall the parameters */
        bp = call->request;
 
        /* Can't take a ref on server */
        trace_afs_make_vl_call(call);
-       return afs_make_call(ac, call, GFP_KERNEL, async);
+       afs_make_call(ac, call, GFP_KERNEL);
+       return call;
 }
 
 /*
        memcpy(bp, uuid, sizeof(*uuid)); /* Type opr_uuid */
 
        trace_afs_make_vl_call(call);
-       return (struct afs_addr_list *)afs_make_call(&vc->ac, call, GFP_KERNEL, false);
+       afs_make_call(&vc->ac, call, GFP_KERNEL);
+       return (struct afs_addr_list *)afs_wait_for_call_to_complete(call, &vc->ac);
 }
 
        call->cb_break = fc->cb_break;
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
        call->cb_break = fc->cb_break;
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 static const struct afs_call_type yfs_RXFSMakeDir = {
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &dvnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &dvnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &dvnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &orig_dvnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
        call->cb_break = fc->cb_break;
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, fid);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
        call->cb_break = fc->cb_break;
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &fids[0]);
-       return afs_make_call(&fc->ac, call, GFP_NOFS, false);
+       afs_make_call(&fc->ac, call, GFP_NOFS);
+       return afs_wait_for_call_to_complete(call, &fc->ac);
 }