1*1249c01aSStefan Metzmacher // SPDX-License-Identifier: GPL-2.0-or-later 2*1249c01aSStefan Metzmacher /* 3*1249c01aSStefan Metzmacher * Copyright (c) 2012,2016,2017,2025 Stefan Metzmacher 4*1249c01aSStefan Metzmacher */ 5*1249c01aSStefan Metzmacher 6*1249c01aSStefan Metzmacher #include "internal.h" 7*1249c01aSStefan Metzmacher #include "../common/smb2status.h" 8*1249c01aSStefan Metzmacher 9*1249c01aSStefan Metzmacher static int smbdirect_connect_setup_connection(struct smbdirect_socket *sc); 10*1249c01aSStefan Metzmacher static int smbdirect_connect_resolve_addr(struct smbdirect_socket *sc, 11*1249c01aSStefan Metzmacher const struct sockaddr *src, 12*1249c01aSStefan Metzmacher const struct sockaddr *dst); 13*1249c01aSStefan Metzmacher static int smbdirect_connect_rdma_event_handler(struct rdma_cm_id *id, 14*1249c01aSStefan Metzmacher struct rdma_cm_event *event); 15*1249c01aSStefan Metzmacher static int smbdirect_connect_negotiate_start(struct smbdirect_socket *sc); 16*1249c01aSStefan Metzmacher static void smbdirect_connect_negotiate_send_done(struct ib_cq *cq, struct ib_wc *wc); 17*1249c01aSStefan Metzmacher static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc *wc); 18*1249c01aSStefan Metzmacher 19*1249c01aSStefan Metzmacher int smbdirect_connect(struct smbdirect_socket *sc, const struct sockaddr *dst) 20*1249c01aSStefan Metzmacher { 21*1249c01aSStefan Metzmacher const struct sockaddr *src = NULL; 22*1249c01aSStefan Metzmacher union { 23*1249c01aSStefan Metzmacher struct sockaddr sa; 24*1249c01aSStefan Metzmacher struct sockaddr_storage ss; 25*1249c01aSStefan Metzmacher } src_addr = { 26*1249c01aSStefan Metzmacher .sa = { 27*1249c01aSStefan Metzmacher .sa_family = AF_UNSPEC, 28*1249c01aSStefan Metzmacher }, 29*1249c01aSStefan Metzmacher }; 30*1249c01aSStefan Metzmacher int ret; 31*1249c01aSStefan Metzmacher 32*1249c01aSStefan Metzmacher if (sc->first_error) 33*1249c01aSStefan Metzmacher return -ENOTCONN; 34*1249c01aSStefan Metzmacher 35*1249c01aSStefan Metzmacher if (sc->status != SMBDIRECT_SOCKET_CREATED) 36*1249c01aSStefan Metzmacher return -EALREADY; 37*1249c01aSStefan Metzmacher 38*1249c01aSStefan Metzmacher if (WARN_ON_ONCE(!sc->rdma.cm_id)) 39*1249c01aSStefan Metzmacher return -EINVAL; 40*1249c01aSStefan Metzmacher 41*1249c01aSStefan Metzmacher src_addr.ss = sc->rdma.cm_id->route.addr.src_addr; 42*1249c01aSStefan Metzmacher if (src_addr.sa.sa_family != AF_UNSPEC) 43*1249c01aSStefan Metzmacher src = &src_addr.sa; 44*1249c01aSStefan Metzmacher 45*1249c01aSStefan Metzmacher smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO, 46*1249c01aSStefan Metzmacher "connect: src: %pISpsfc dst: %pISpsfc\n", 47*1249c01aSStefan Metzmacher src, dst); 48*1249c01aSStefan Metzmacher 49*1249c01aSStefan Metzmacher ret = smbdirect_connect_setup_connection(sc); 50*1249c01aSStefan Metzmacher if (ret) 51*1249c01aSStefan Metzmacher return ret; 52*1249c01aSStefan Metzmacher 53*1249c01aSStefan Metzmacher ret = smbdirect_connect_resolve_addr(sc, src, dst); 54*1249c01aSStefan Metzmacher if (ret) 55*1249c01aSStefan Metzmacher return ret; 56*1249c01aSStefan Metzmacher 57*1249c01aSStefan Metzmacher /* 58*1249c01aSStefan Metzmacher * The rest happens async via smbdirect_connect_rdma_event_handler() 59*1249c01aSStefan Metzmacher * the caller will decide to wait or not. 60*1249c01aSStefan Metzmacher */ 61*1249c01aSStefan Metzmacher return 0; 62*1249c01aSStefan Metzmacher } 63*1249c01aSStefan Metzmacher __SMBDIRECT_EXPORT_SYMBOL__(smbdirect_connect); 64*1249c01aSStefan Metzmacher 65*1249c01aSStefan Metzmacher static int smbdirect_connect_setup_connection(struct smbdirect_socket *sc) 66*1249c01aSStefan Metzmacher { 67*1249c01aSStefan Metzmacher rdma_lock_handler(sc->rdma.cm_id); 68*1249c01aSStefan Metzmacher sc->rdma.cm_id->event_handler = smbdirect_connect_rdma_event_handler; 69*1249c01aSStefan Metzmacher rdma_unlock_handler(sc->rdma.cm_id); 70*1249c01aSStefan Metzmacher 71*1249c01aSStefan Metzmacher if (SMBDIRECT_CHECK_STATUS_WARN(sc, SMBDIRECT_SOCKET_CREATED)) 72*1249c01aSStefan Metzmacher return -EINVAL; 73*1249c01aSStefan Metzmacher sc->status = SMBDIRECT_SOCKET_RESOLVE_ADDR_NEEDED; 74*1249c01aSStefan Metzmacher 75*1249c01aSStefan Metzmacher return 0; 76*1249c01aSStefan Metzmacher } 77*1249c01aSStefan Metzmacher 78*1249c01aSStefan Metzmacher static int smbdirect_connect_resolve_addr(struct smbdirect_socket *sc, 79*1249c01aSStefan Metzmacher const struct sockaddr *src, 80*1249c01aSStefan Metzmacher const struct sockaddr *dst) 81*1249c01aSStefan Metzmacher { 82*1249c01aSStefan Metzmacher const struct smbdirect_socket_parameters *sp = &sc->parameters; 83*1249c01aSStefan Metzmacher struct sockaddr *src_addr = NULL; 84*1249c01aSStefan Metzmacher struct sockaddr *dst_addr = NULL; 85*1249c01aSStefan Metzmacher int ret; 86*1249c01aSStefan Metzmacher 87*1249c01aSStefan Metzmacher src_addr = (struct sockaddr *)src; 88*1249c01aSStefan Metzmacher if (src_addr && src_addr->sa_family == AF_UNSPEC) 89*1249c01aSStefan Metzmacher src_addr = NULL; 90*1249c01aSStefan Metzmacher dst_addr = (struct sockaddr *)dst; 91*1249c01aSStefan Metzmacher 92*1249c01aSStefan Metzmacher if (SMBDIRECT_CHECK_STATUS_WARN(sc, SMBDIRECT_SOCKET_RESOLVE_ADDR_NEEDED)) 93*1249c01aSStefan Metzmacher return -EINVAL; 94*1249c01aSStefan Metzmacher sc->status = SMBDIRECT_SOCKET_RESOLVE_ADDR_RUNNING; 95*1249c01aSStefan Metzmacher sc->rdma.expected_event = RDMA_CM_EVENT_ADDR_RESOLVED; 96*1249c01aSStefan Metzmacher ret = rdma_resolve_addr(sc->rdma.cm_id, src_addr, dst_addr, 97*1249c01aSStefan Metzmacher sp->resolve_addr_timeout_msec); 98*1249c01aSStefan Metzmacher if (ret) { 99*1249c01aSStefan Metzmacher smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR, 100*1249c01aSStefan Metzmacher "rdma_resolve_addr() failed %1pe\n", 101*1249c01aSStefan Metzmacher SMBDIRECT_DEBUG_ERR_PTR(ret)); 102*1249c01aSStefan Metzmacher return ret; 103*1249c01aSStefan Metzmacher } 104*1249c01aSStefan Metzmacher 105*1249c01aSStefan Metzmacher return 0; 106*1249c01aSStefan Metzmacher } 107*1249c01aSStefan Metzmacher 108*1249c01aSStefan Metzmacher static int smbdirect_connect_resolve_route(struct smbdirect_socket *sc) 109*1249c01aSStefan Metzmacher { 110*1249c01aSStefan Metzmacher const struct smbdirect_socket_parameters *sp = &sc->parameters; 111*1249c01aSStefan Metzmacher int ret; 112*1249c01aSStefan Metzmacher 113*1249c01aSStefan Metzmacher if (SMBDIRECT_CHECK_STATUS_DISCONNECT(sc, SMBDIRECT_SOCKET_RESOLVE_ROUTE_NEEDED)) 114*1249c01aSStefan Metzmacher return sc->first_error; 115*1249c01aSStefan Metzmacher sc->status = SMBDIRECT_SOCKET_RESOLVE_ROUTE_RUNNING; 116*1249c01aSStefan Metzmacher sc->rdma.expected_event = RDMA_CM_EVENT_ROUTE_RESOLVED; 117*1249c01aSStefan Metzmacher ret = rdma_resolve_route(sc->rdma.cm_id, sp->resolve_route_timeout_msec); 118*1249c01aSStefan Metzmacher if (ret) { 119*1249c01aSStefan Metzmacher smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR, 120*1249c01aSStefan Metzmacher "rdma_resolve_route() failed %1pe\n", 121*1249c01aSStefan Metzmacher SMBDIRECT_DEBUG_ERR_PTR(ret)); 122*1249c01aSStefan Metzmacher return ret; 123*1249c01aSStefan Metzmacher } 124*1249c01aSStefan Metzmacher 125*1249c01aSStefan Metzmacher return 0; 126*1249c01aSStefan Metzmacher } 127*1249c01aSStefan Metzmacher 128*1249c01aSStefan Metzmacher static int smbdirect_connect_rdma_connect(struct smbdirect_socket *sc) 129*1249c01aSStefan Metzmacher { 130*1249c01aSStefan Metzmacher struct smbdirect_socket_parameters *sp = &sc->parameters; 131*1249c01aSStefan Metzmacher struct rdma_conn_param conn_param; 132*1249c01aSStefan Metzmacher __be32 ird_ord_hdr[2]; 133*1249c01aSStefan Metzmacher int ret; 134*1249c01aSStefan Metzmacher 135*1249c01aSStefan Metzmacher sc->ib.dev = sc->rdma.cm_id->device; 136*1249c01aSStefan Metzmacher 137*1249c01aSStefan Metzmacher if (!smbdirect_frwr_is_supported(&sc->ib.dev->attrs)) { 138*1249c01aSStefan Metzmacher smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR, 139*1249c01aSStefan Metzmacher "Fast Registration Work Requests (FRWR) is not supported device %.*s\n", 140*1249c01aSStefan Metzmacher IB_DEVICE_NAME_MAX, 141*1249c01aSStefan Metzmacher sc->ib.dev->name); 142*1249c01aSStefan Metzmacher smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR, 143*1249c01aSStefan Metzmacher "Device capability flags = %llx max_fast_reg_page_list_len = %u\n", 144*1249c01aSStefan Metzmacher sc->ib.dev->attrs.device_cap_flags, 145*1249c01aSStefan Metzmacher sc->ib.dev->attrs.max_fast_reg_page_list_len); 146*1249c01aSStefan Metzmacher return -EPROTONOSUPPORT; 147*1249c01aSStefan Metzmacher } 148*1249c01aSStefan Metzmacher 149*1249c01aSStefan Metzmacher if (sp->flags & SMBDIRECT_FLAG_PORT_RANGE_ONLY_IB && 150*1249c01aSStefan Metzmacher !rdma_ib_or_roce(sc->ib.dev, sc->rdma.cm_id->port_num)) { 151*1249c01aSStefan Metzmacher smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR, 152*1249c01aSStefan Metzmacher "Not IB: device: %.*s IW:%u local: %pISpsfc remote: %pISpsfc\n", 153*1249c01aSStefan Metzmacher IB_DEVICE_NAME_MAX, 154*1249c01aSStefan Metzmacher sc->ib.dev->name, 155*1249c01aSStefan Metzmacher rdma_protocol_iwarp(sc->ib.dev, sc->rdma.cm_id->port_num), 156*1249c01aSStefan Metzmacher &sc->rdma.cm_id->route.addr.src_addr, 157*1249c01aSStefan Metzmacher &sc->rdma.cm_id->route.addr.dst_addr); 158*1249c01aSStefan Metzmacher return -EPROTONOSUPPORT; 159*1249c01aSStefan Metzmacher } 160*1249c01aSStefan Metzmacher if (sp->flags & SMBDIRECT_FLAG_PORT_RANGE_ONLY_IW && 161*1249c01aSStefan Metzmacher !rdma_protocol_iwarp(sc->ib.dev, sc->rdma.cm_id->port_num)) { 162*1249c01aSStefan Metzmacher smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR, 163*1249c01aSStefan Metzmacher "Not IW: device: %.*s IB:%u local: %pISpsfc remote: %pISpsfc\n", 164*1249c01aSStefan Metzmacher IB_DEVICE_NAME_MAX, 165*1249c01aSStefan Metzmacher sc->ib.dev->name, 166*1249c01aSStefan Metzmacher rdma_ib_or_roce(sc->ib.dev, sc->rdma.cm_id->port_num), 167*1249c01aSStefan Metzmacher &sc->rdma.cm_id->route.addr.src_addr, 168*1249c01aSStefan Metzmacher &sc->rdma.cm_id->route.addr.dst_addr); 169*1249c01aSStefan Metzmacher return -EPROTONOSUPPORT; 170*1249c01aSStefan Metzmacher } 171*1249c01aSStefan Metzmacher 172*1249c01aSStefan Metzmacher smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO, 173*1249c01aSStefan Metzmacher "rdma connect: device: %.*s local: %pISpsfc remote: %pISpsfc\n", 174*1249c01aSStefan Metzmacher IB_DEVICE_NAME_MAX, 175*1249c01aSStefan Metzmacher sc->ib.dev->name, 176*1249c01aSStefan Metzmacher &sc->rdma.cm_id->route.addr.src_addr, 177*1249c01aSStefan Metzmacher &sc->rdma.cm_id->route.addr.dst_addr); 178*1249c01aSStefan Metzmacher 179*1249c01aSStefan Metzmacher sp->max_frmr_depth = min_t(u32, sp->max_frmr_depth, 180*1249c01aSStefan Metzmacher sc->ib.dev->attrs.max_fast_reg_page_list_len); 181*1249c01aSStefan Metzmacher sc->mr_io.type = IB_MR_TYPE_MEM_REG; 182*1249c01aSStefan Metzmacher if (sc->ib.dev->attrs.kernel_cap_flags & IBK_SG_GAPS_REG) 183*1249c01aSStefan Metzmacher sc->mr_io.type = IB_MR_TYPE_SG_GAPS; 184*1249c01aSStefan Metzmacher 185*1249c01aSStefan Metzmacher sp->responder_resources = min_t(u8, sp->responder_resources, 186*1249c01aSStefan Metzmacher sc->ib.dev->attrs.max_qp_rd_atom); 187*1249c01aSStefan Metzmacher smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_INFO, 188*1249c01aSStefan Metzmacher "responder_resources=%d\n", 189*1249c01aSStefan Metzmacher sp->responder_resources); 190*1249c01aSStefan Metzmacher 191*1249c01aSStefan Metzmacher ret = smbdirect_connection_create_qp(sc); 192*1249c01aSStefan Metzmacher if (ret) { 193*1249c01aSStefan Metzmacher smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR, 194*1249c01aSStefan Metzmacher "smbdirect_connection_create_qp() failed %1pe\n", 195*1249c01aSStefan Metzmacher SMBDIRECT_DEBUG_ERR_PTR(ret)); 196*1249c01aSStefan Metzmacher return ret; 197*1249c01aSStefan Metzmacher } 198*1249c01aSStefan Metzmacher 199*1249c01aSStefan Metzmacher memset(&conn_param, 0, sizeof(conn_param)); 200*1249c01aSStefan Metzmacher conn_param.initiator_depth = sp->initiator_depth; 201*1249c01aSStefan Metzmacher conn_param.responder_resources = sp->responder_resources; 202*1249c01aSStefan Metzmacher 203*1249c01aSStefan Metzmacher /* Need to send IRD/ORD in private data for iWARP */ 204*1249c01aSStefan Metzmacher if (rdma_protocol_iwarp(sc->ib.dev, sc->rdma.cm_id->port_num)) { 205*1249c01aSStefan Metzmacher ird_ord_hdr[0] = cpu_to_be32(conn_param.responder_resources); 206*1249c01aSStefan Metzmacher ird_ord_hdr[1] = cpu_to_be32(conn_param.initiator_depth); 207*1249c01aSStefan Metzmacher conn_param.private_data = ird_ord_hdr; 208*1249c01aSStefan Metzmacher conn_param.private_data_len = sizeof(ird_ord_hdr); 209*1249c01aSStefan Metzmacher } else { 210*1249c01aSStefan Metzmacher conn_param.private_data = NULL; 211*1249c01aSStefan Metzmacher conn_param.private_data_len = 0; 212*1249c01aSStefan Metzmacher } 213*1249c01aSStefan Metzmacher 214*1249c01aSStefan Metzmacher conn_param.retry_count = SMBDIRECT_RDMA_CM_RETRY; 215*1249c01aSStefan Metzmacher conn_param.rnr_retry_count = SMBDIRECT_RDMA_CM_RNR_RETRY; 216*1249c01aSStefan Metzmacher conn_param.flow_control = 0; 217*1249c01aSStefan Metzmacher 218*1249c01aSStefan Metzmacher if (SMBDIRECT_CHECK_STATUS_DISCONNECT(sc, SMBDIRECT_SOCKET_RDMA_CONNECT_NEEDED)) 219*1249c01aSStefan Metzmacher return sc->first_error; 220*1249c01aSStefan Metzmacher sc->status = SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING; 221*1249c01aSStefan Metzmacher sc->rdma.expected_event = RDMA_CM_EVENT_ESTABLISHED; 222*1249c01aSStefan Metzmacher ret = rdma_connect_locked(sc->rdma.cm_id, &conn_param); 223*1249c01aSStefan Metzmacher if (ret) { 224*1249c01aSStefan Metzmacher smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR, 225*1249c01aSStefan Metzmacher "rdma_connect_locked() failed %1pe\n", 226*1249c01aSStefan Metzmacher SMBDIRECT_DEBUG_ERR_PTR(ret)); 227*1249c01aSStefan Metzmacher return ret; 228*1249c01aSStefan Metzmacher } 229*1249c01aSStefan Metzmacher 230*1249c01aSStefan Metzmacher /* 231*1249c01aSStefan Metzmacher * start with the rdma connect timeout and SMBDIRECT_KEEPALIVE_PENDING 232*1249c01aSStefan Metzmacher * so that the timer will cause a disconnect. 233*1249c01aSStefan Metzmacher */ 234*1249c01aSStefan Metzmacher INIT_DELAYED_WORK(&sc->idle.timer_work, smbdirect_connection_idle_timer_work); 235*1249c01aSStefan Metzmacher sc->idle.keepalive = SMBDIRECT_KEEPALIVE_PENDING; 236*1249c01aSStefan Metzmacher mod_delayed_work(sc->workqueues.idle, &sc->idle.timer_work, 237*1249c01aSStefan Metzmacher msecs_to_jiffies(sp->rdma_connect_timeout_msec)); 238*1249c01aSStefan Metzmacher 239*1249c01aSStefan Metzmacher return 0; 240*1249c01aSStefan Metzmacher } 241*1249c01aSStefan Metzmacher 242*1249c01aSStefan Metzmacher static int smbdirect_connect_rdma_event_handler(struct rdma_cm_id *id, 243*1249c01aSStefan Metzmacher struct rdma_cm_event *event) 244*1249c01aSStefan Metzmacher { 245*1249c01aSStefan Metzmacher struct smbdirect_socket *sc = id->context; 246*1249c01aSStefan Metzmacher u8 peer_initiator_depth; 247*1249c01aSStefan Metzmacher u8 peer_responder_resources; 248*1249c01aSStefan Metzmacher int ret; 249*1249c01aSStefan Metzmacher 250*1249c01aSStefan Metzmacher /* 251*1249c01aSStefan Metzmacher * cma_cm_event_handler() has 252*1249c01aSStefan Metzmacher * lockdep_assert_held(&id_priv->handler_mutex); 253*1249c01aSStefan Metzmacher * 254*1249c01aSStefan Metzmacher * Mutexes are not allowed in interrupts, 255*1249c01aSStefan Metzmacher * and we rely on not being in an interrupt here, 256*1249c01aSStefan Metzmacher * as we might sleep. 257*1249c01aSStefan Metzmacher * 258*1249c01aSStefan Metzmacher * We didn't timeout so we cancel our idle timer, 259*1249c01aSStefan Metzmacher * it will be scheduled again if needed. 260*1249c01aSStefan Metzmacher */ 261*1249c01aSStefan Metzmacher WARN_ON_ONCE(in_interrupt()); 262*1249c01aSStefan Metzmacher sc->idle.keepalive = SMBDIRECT_KEEPALIVE_NONE; 263*1249c01aSStefan Metzmacher cancel_delayed_work_sync(&sc->idle.timer_work); 264*1249c01aSStefan Metzmacher 265*1249c01aSStefan Metzmacher if (event->status || event->event != sc->rdma.expected_event) { 266*1249c01aSStefan Metzmacher int lvl = SMBDIRECT_LOG_ERR; 267*1249c01aSStefan Metzmacher 268*1249c01aSStefan Metzmacher ret = -ECONNABORTED; 269*1249c01aSStefan Metzmacher 270*1249c01aSStefan Metzmacher if (event->event == RDMA_CM_EVENT_REJECTED) 271*1249c01aSStefan Metzmacher ret = -ECONNREFUSED; 272*1249c01aSStefan Metzmacher if (event->event == RDMA_CM_EVENT_DEVICE_REMOVAL) 273*1249c01aSStefan Metzmacher ret = -ENETDOWN; 274*1249c01aSStefan Metzmacher if (IS_ERR(SMBDIRECT_DEBUG_ERR_PTR(event->status))) 275*1249c01aSStefan Metzmacher ret = event->status; 276*1249c01aSStefan Metzmacher 277*1249c01aSStefan Metzmacher if (ret == -ENODEV) 278*1249c01aSStefan Metzmacher lvl = SMBDIRECT_LOG_INFO; 279*1249c01aSStefan Metzmacher 280*1249c01aSStefan Metzmacher smbdirect_log_rdma_event(sc, lvl, 281*1249c01aSStefan Metzmacher "%s (first_error=%1pe, expected=%s) => event=%s status=%d => ret=%1pe\n", 282*1249c01aSStefan Metzmacher smbdirect_socket_status_string(sc->status), 283*1249c01aSStefan Metzmacher SMBDIRECT_DEBUG_ERR_PTR(sc->first_error), 284*1249c01aSStefan Metzmacher rdma_event_msg(sc->rdma.expected_event), 285*1249c01aSStefan Metzmacher rdma_event_msg(event->event), 286*1249c01aSStefan Metzmacher event->status, 287*1249c01aSStefan Metzmacher SMBDIRECT_DEBUG_ERR_PTR(ret)); 288*1249c01aSStefan Metzmacher 289*1249c01aSStefan Metzmacher smbdirect_socket_schedule_cleanup_lvl(sc, 290*1249c01aSStefan Metzmacher lvl, 291*1249c01aSStefan Metzmacher ret); 292*1249c01aSStefan Metzmacher return 0; 293*1249c01aSStefan Metzmacher } 294*1249c01aSStefan Metzmacher 295*1249c01aSStefan Metzmacher smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO, 296*1249c01aSStefan Metzmacher "%s (first_error=%1pe) event=%s\n", 297*1249c01aSStefan Metzmacher smbdirect_socket_status_string(sc->status), 298*1249c01aSStefan Metzmacher SMBDIRECT_DEBUG_ERR_PTR(sc->first_error), 299*1249c01aSStefan Metzmacher rdma_event_msg(event->event)); 300*1249c01aSStefan Metzmacher 301*1249c01aSStefan Metzmacher if (sc->first_error) 302*1249c01aSStefan Metzmacher return 0; 303*1249c01aSStefan Metzmacher 304*1249c01aSStefan Metzmacher switch (event->event) { 305*1249c01aSStefan Metzmacher case RDMA_CM_EVENT_ADDR_RESOLVED: 306*1249c01aSStefan Metzmacher if (SMBDIRECT_CHECK_STATUS_DISCONNECT(sc, SMBDIRECT_SOCKET_RESOLVE_ADDR_RUNNING)) 307*1249c01aSStefan Metzmacher return 0; 308*1249c01aSStefan Metzmacher sc->status = SMBDIRECT_SOCKET_RESOLVE_ROUTE_NEEDED; 309*1249c01aSStefan Metzmacher 310*1249c01aSStefan Metzmacher ret = smbdirect_connect_resolve_route(sc); 311*1249c01aSStefan Metzmacher if (ret) 312*1249c01aSStefan Metzmacher smbdirect_socket_schedule_cleanup(sc, ret); 313*1249c01aSStefan Metzmacher return 0; 314*1249c01aSStefan Metzmacher 315*1249c01aSStefan Metzmacher case RDMA_CM_EVENT_ROUTE_RESOLVED: 316*1249c01aSStefan Metzmacher if (SMBDIRECT_CHECK_STATUS_DISCONNECT(sc, SMBDIRECT_SOCKET_RESOLVE_ROUTE_RUNNING)) 317*1249c01aSStefan Metzmacher return 0; 318*1249c01aSStefan Metzmacher sc->status = SMBDIRECT_SOCKET_RDMA_CONNECT_NEEDED; 319*1249c01aSStefan Metzmacher 320*1249c01aSStefan Metzmacher ret = smbdirect_connect_rdma_connect(sc); 321*1249c01aSStefan Metzmacher if (ret) 322*1249c01aSStefan Metzmacher smbdirect_socket_schedule_cleanup(sc, ret); 323*1249c01aSStefan Metzmacher return 0; 324*1249c01aSStefan Metzmacher 325*1249c01aSStefan Metzmacher case RDMA_CM_EVENT_ESTABLISHED: 326*1249c01aSStefan Metzmacher smbdirect_connection_rdma_established(sc); 327*1249c01aSStefan Metzmacher 328*1249c01aSStefan Metzmacher if (SMBDIRECT_CHECK_STATUS_DISCONNECT(sc, SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING)) 329*1249c01aSStefan Metzmacher return 0; 330*1249c01aSStefan Metzmacher sc->status = SMBDIRECT_SOCKET_NEGOTIATE_NEEDED; 331*1249c01aSStefan Metzmacher 332*1249c01aSStefan Metzmacher /* 333*1249c01aSStefan Metzmacher * Here we work around an inconsistency between 334*1249c01aSStefan Metzmacher * iWarp and other devices (at least rxe and irdma using RoCEv2) 335*1249c01aSStefan Metzmacher */ 336*1249c01aSStefan Metzmacher if (rdma_protocol_iwarp(id->device, id->port_num)) { 337*1249c01aSStefan Metzmacher /* 338*1249c01aSStefan Metzmacher * iWarp devices report the peer's values 339*1249c01aSStefan Metzmacher * with the perspective of the peer here. 340*1249c01aSStefan Metzmacher * Tested with siw and irdma (in iwarp mode) 341*1249c01aSStefan Metzmacher * We need to change to our perspective here, 342*1249c01aSStefan Metzmacher * so we need to switch the values. 343*1249c01aSStefan Metzmacher */ 344*1249c01aSStefan Metzmacher peer_initiator_depth = event->param.conn.responder_resources; 345*1249c01aSStefan Metzmacher peer_responder_resources = event->param.conn.initiator_depth; 346*1249c01aSStefan Metzmacher } else { 347*1249c01aSStefan Metzmacher /* 348*1249c01aSStefan Metzmacher * Non iWarp devices report the peer's values 349*1249c01aSStefan Metzmacher * already changed to our perspective here. 350*1249c01aSStefan Metzmacher * Tested with rxe and irdma (in roce mode). 351*1249c01aSStefan Metzmacher */ 352*1249c01aSStefan Metzmacher peer_initiator_depth = event->param.conn.initiator_depth; 353*1249c01aSStefan Metzmacher peer_responder_resources = event->param.conn.responder_resources; 354*1249c01aSStefan Metzmacher } 355*1249c01aSStefan Metzmacher smbdirect_connection_negotiate_rdma_resources(sc, 356*1249c01aSStefan Metzmacher peer_initiator_depth, 357*1249c01aSStefan Metzmacher peer_responder_resources, 358*1249c01aSStefan Metzmacher &event->param.conn); 359*1249c01aSStefan Metzmacher 360*1249c01aSStefan Metzmacher ret = smbdirect_connect_negotiate_start(sc); 361*1249c01aSStefan Metzmacher if (ret) 362*1249c01aSStefan Metzmacher smbdirect_socket_schedule_cleanup(sc, ret); 363*1249c01aSStefan Metzmacher return 0; 364*1249c01aSStefan Metzmacher 365*1249c01aSStefan Metzmacher default: 366*1249c01aSStefan Metzmacher break; 367*1249c01aSStefan Metzmacher } 368*1249c01aSStefan Metzmacher 369*1249c01aSStefan Metzmacher /* 370*1249c01aSStefan Metzmacher * This is an internal error 371*1249c01aSStefan Metzmacher */ 372*1249c01aSStefan Metzmacher WARN_ON_ONCE(sc->rdma.expected_event != RDMA_CM_EVENT_ESTABLISHED); 373*1249c01aSStefan Metzmacher smbdirect_socket_schedule_cleanup(sc, -ECONNABORTED); 374*1249c01aSStefan Metzmacher return 0; 375*1249c01aSStefan Metzmacher } 376*1249c01aSStefan Metzmacher 377*1249c01aSStefan Metzmacher static int smbdirect_connect_negotiate_start(struct smbdirect_socket *sc) 378*1249c01aSStefan Metzmacher { 379*1249c01aSStefan Metzmacher const struct smbdirect_socket_parameters *sp = &sc->parameters; 380*1249c01aSStefan Metzmacher struct smbdirect_recv_io *recv_io = NULL; 381*1249c01aSStefan Metzmacher struct smbdirect_send_io *send_io = NULL; 382*1249c01aSStefan Metzmacher struct smbdirect_negotiate_req *nreq = NULL; 383*1249c01aSStefan Metzmacher int ret; 384*1249c01aSStefan Metzmacher 385*1249c01aSStefan Metzmacher if (SMBDIRECT_CHECK_STATUS_DISCONNECT(sc, SMBDIRECT_SOCKET_NEGOTIATE_NEEDED)) 386*1249c01aSStefan Metzmacher return sc->first_error; 387*1249c01aSStefan Metzmacher sc->status = SMBDIRECT_SOCKET_NEGOTIATE_RUNNING; 388*1249c01aSStefan Metzmacher 389*1249c01aSStefan Metzmacher ret = smbdirect_connection_create_mem_pools(sc); 390*1249c01aSStefan Metzmacher if (ret) { 391*1249c01aSStefan Metzmacher smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR, 392*1249c01aSStefan Metzmacher "smbdirect_connection_create_mem_pools() failed %1pe\n", 393*1249c01aSStefan Metzmacher SMBDIRECT_DEBUG_ERR_PTR(ret)); 394*1249c01aSStefan Metzmacher goto create_mem_pools_failed; 395*1249c01aSStefan Metzmacher } 396*1249c01aSStefan Metzmacher 397*1249c01aSStefan Metzmacher /* 398*1249c01aSStefan Metzmacher * There is only a single batch credit 399*1249c01aSStefan Metzmacher */ 400*1249c01aSStefan Metzmacher atomic_set(&sc->send_io.bcredits.count, 1); 401*1249c01aSStefan Metzmacher 402*1249c01aSStefan Metzmacher /* 403*1249c01aSStefan Metzmacher * Initialize the local credits to post 404*1249c01aSStefan Metzmacher * IB_WR_SEND[_WITH_INV]. 405*1249c01aSStefan Metzmacher */ 406*1249c01aSStefan Metzmacher atomic_set(&sc->send_io.lcredits.count, sp->send_credit_target); 407*1249c01aSStefan Metzmacher 408*1249c01aSStefan Metzmacher recv_io = smbdirect_connection_get_recv_io(sc); 409*1249c01aSStefan Metzmacher if (WARN_ON_ONCE(!recv_io)) { 410*1249c01aSStefan Metzmacher ret = -EINVAL; 411*1249c01aSStefan Metzmacher smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR, 412*1249c01aSStefan Metzmacher "smbdirect_connection_get_recv_io() failed %1pe\n", 413*1249c01aSStefan Metzmacher SMBDIRECT_DEBUG_ERR_PTR(ret)); 414*1249c01aSStefan Metzmacher goto get_recv_io_failed; 415*1249c01aSStefan Metzmacher } 416*1249c01aSStefan Metzmacher recv_io->cqe.done = smbdirect_connect_negotiate_recv_done; 417*1249c01aSStefan Metzmacher 418*1249c01aSStefan Metzmacher send_io = smbdirect_connection_alloc_send_io(sc); 419*1249c01aSStefan Metzmacher if (IS_ERR(send_io)) { 420*1249c01aSStefan Metzmacher ret = PTR_ERR(send_io); 421*1249c01aSStefan Metzmacher smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR, 422*1249c01aSStefan Metzmacher "smbdirect_connection_alloc_send_io() failed %1pe\n", 423*1249c01aSStefan Metzmacher SMBDIRECT_DEBUG_ERR_PTR(ret)); 424*1249c01aSStefan Metzmacher goto alloc_send_io_failed; 425*1249c01aSStefan Metzmacher } 426*1249c01aSStefan Metzmacher send_io->cqe.done = smbdirect_connect_negotiate_send_done; 427*1249c01aSStefan Metzmacher 428*1249c01aSStefan Metzmacher nreq = (struct smbdirect_negotiate_req *)send_io->packet; 429*1249c01aSStefan Metzmacher nreq->min_version = cpu_to_le16(SMBDIRECT_V1); 430*1249c01aSStefan Metzmacher nreq->max_version = cpu_to_le16(SMBDIRECT_V1); 431*1249c01aSStefan Metzmacher nreq->reserved = 0; 432*1249c01aSStefan Metzmacher nreq->credits_requested = cpu_to_le16(sp->send_credit_target); 433*1249c01aSStefan Metzmacher nreq->preferred_send_size = cpu_to_le32(sp->max_send_size); 434*1249c01aSStefan Metzmacher nreq->max_receive_size = cpu_to_le32(sp->max_recv_size); 435*1249c01aSStefan Metzmacher nreq->max_fragmented_size = cpu_to_le32(sp->max_fragmented_recv_size); 436*1249c01aSStefan Metzmacher 437*1249c01aSStefan Metzmacher smbdirect_log_negotiate(sc, SMBDIRECT_LOG_INFO, 438*1249c01aSStefan Metzmacher "ReqOut: %s%x, %s%x, %s%u, %s%u, %s%u, %s%u\n", 439*1249c01aSStefan Metzmacher "MinVersion=0x", 440*1249c01aSStefan Metzmacher le16_to_cpu(nreq->min_version), 441*1249c01aSStefan Metzmacher "MaxVersion=0x", 442*1249c01aSStefan Metzmacher le16_to_cpu(nreq->max_version), 443*1249c01aSStefan Metzmacher "CreditsRequested=", 444*1249c01aSStefan Metzmacher le16_to_cpu(nreq->credits_requested), 445*1249c01aSStefan Metzmacher "PreferredSendSize=", 446*1249c01aSStefan Metzmacher le32_to_cpu(nreq->preferred_send_size), 447*1249c01aSStefan Metzmacher "MaxRecvSize=", 448*1249c01aSStefan Metzmacher le32_to_cpu(nreq->max_receive_size), 449*1249c01aSStefan Metzmacher "MaxFragmentedSize=", 450*1249c01aSStefan Metzmacher le32_to_cpu(nreq->max_fragmented_size)); 451*1249c01aSStefan Metzmacher 452*1249c01aSStefan Metzmacher send_io->sge[0].addr = ib_dma_map_single(sc->ib.dev, 453*1249c01aSStefan Metzmacher nreq, 454*1249c01aSStefan Metzmacher sizeof(*nreq), 455*1249c01aSStefan Metzmacher DMA_TO_DEVICE); 456*1249c01aSStefan Metzmacher ret = ib_dma_mapping_error(sc->ib.dev, send_io->sge[0].addr); 457*1249c01aSStefan Metzmacher if (ret) { 458*1249c01aSStefan Metzmacher smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR, 459*1249c01aSStefan Metzmacher "ib_dma_mapping_error() failed %1pe\n", 460*1249c01aSStefan Metzmacher SMBDIRECT_DEBUG_ERR_PTR(ret)); 461*1249c01aSStefan Metzmacher goto dma_mapping_failed; 462*1249c01aSStefan Metzmacher } 463*1249c01aSStefan Metzmacher 464*1249c01aSStefan Metzmacher send_io->sge[0].length = sizeof(*nreq); 465*1249c01aSStefan Metzmacher send_io->sge[0].lkey = sc->ib.pd->local_dma_lkey; 466*1249c01aSStefan Metzmacher send_io->num_sge = 1; 467*1249c01aSStefan Metzmacher 468*1249c01aSStefan Metzmacher ib_dma_sync_single_for_device(sc->ib.dev, 469*1249c01aSStefan Metzmacher send_io->sge[0].addr, 470*1249c01aSStefan Metzmacher send_io->sge[0].length, 471*1249c01aSStefan Metzmacher DMA_TO_DEVICE); 472*1249c01aSStefan Metzmacher 473*1249c01aSStefan Metzmacher smbdirect_log_rdma_send(sc, SMBDIRECT_LOG_INFO, 474*1249c01aSStefan Metzmacher "sge addr=0x%llx length=%u lkey=0x%x\n", 475*1249c01aSStefan Metzmacher send_io->sge[0].addr, 476*1249c01aSStefan Metzmacher send_io->sge[0].length, 477*1249c01aSStefan Metzmacher send_io->sge[0].lkey); 478*1249c01aSStefan Metzmacher 479*1249c01aSStefan Metzmacher /* 480*1249c01aSStefan Metzmacher * Now post the recv_io buffer in order to get 481*1249c01aSStefan Metzmacher * the negotiate response 482*1249c01aSStefan Metzmacher */ 483*1249c01aSStefan Metzmacher sc->recv_io.expected = SMBDIRECT_EXPECT_NEGOTIATE_REP; 484*1249c01aSStefan Metzmacher ret = smbdirect_connection_post_recv_io(recv_io); 485*1249c01aSStefan Metzmacher if (ret) { 486*1249c01aSStefan Metzmacher smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR, 487*1249c01aSStefan Metzmacher "smbdirect_connection_post_recv_io() failed %1pe\n", 488*1249c01aSStefan Metzmacher SMBDIRECT_DEBUG_ERR_PTR(ret)); 489*1249c01aSStefan Metzmacher goto post_recv_io_failed; 490*1249c01aSStefan Metzmacher } 491*1249c01aSStefan Metzmacher 492*1249c01aSStefan Metzmacher send_io->wr.next = NULL; 493*1249c01aSStefan Metzmacher send_io->wr.wr_cqe = &send_io->cqe; 494*1249c01aSStefan Metzmacher send_io->wr.sg_list = send_io->sge; 495*1249c01aSStefan Metzmacher send_io->wr.num_sge = send_io->num_sge; 496*1249c01aSStefan Metzmacher send_io->wr.opcode = IB_WR_SEND; 497*1249c01aSStefan Metzmacher send_io->wr.send_flags = IB_SEND_SIGNALED; 498*1249c01aSStefan Metzmacher 499*1249c01aSStefan Metzmacher ret = smbdirect_connection_post_send_wr(sc, &send_io->wr); 500*1249c01aSStefan Metzmacher if (ret) { 501*1249c01aSStefan Metzmacher /* if we reach here, post send failed */ 502*1249c01aSStefan Metzmacher smbdirect_log_rdma_send(sc, SMBDIRECT_LOG_ERR, 503*1249c01aSStefan Metzmacher "smbdirect_connection_post_send_wr() failed %1pe\n", 504*1249c01aSStefan Metzmacher SMBDIRECT_DEBUG_ERR_PTR(ret)); 505*1249c01aSStefan Metzmacher goto post_send_wr_failed; 506*1249c01aSStefan Metzmacher } 507*1249c01aSStefan Metzmacher 508*1249c01aSStefan Metzmacher /* 509*1249c01aSStefan Metzmacher * start with the negotiate timeout and SMBDIRECT_KEEPALIVE_PENDING 510*1249c01aSStefan Metzmacher * so that the timer will cause a disconnect. 511*1249c01aSStefan Metzmacher */ 512*1249c01aSStefan Metzmacher sc->idle.keepalive = SMBDIRECT_KEEPALIVE_PENDING; 513*1249c01aSStefan Metzmacher mod_delayed_work(sc->workqueues.idle, &sc->idle.timer_work, 514*1249c01aSStefan Metzmacher msecs_to_jiffies(sp->negotiate_timeout_msec)); 515*1249c01aSStefan Metzmacher 516*1249c01aSStefan Metzmacher return 0; 517*1249c01aSStefan Metzmacher 518*1249c01aSStefan Metzmacher post_send_wr_failed: 519*1249c01aSStefan Metzmacher /* 520*1249c01aSStefan Metzmacher * ib_dma_unmap_single is called in 521*1249c01aSStefan Metzmacher * smbdirect_connection_free_send_io() 522*1249c01aSStefan Metzmacher */ 523*1249c01aSStefan Metzmacher smbdirect_connection_free_send_io(send_io); 524*1249c01aSStefan Metzmacher /* 525*1249c01aSStefan Metzmacher * recv_io is given to the rdma layer, 526*1249c01aSStefan Metzmacher * we should not put it even on error 527*1249c01aSStefan Metzmacher * nor call smbdirect_connection_destroy_mem_pools() 528*1249c01aSStefan Metzmacher * it will be cleaned up during disconnect. 529*1249c01aSStefan Metzmacher */ 530*1249c01aSStefan Metzmacher return ret; 531*1249c01aSStefan Metzmacher 532*1249c01aSStefan Metzmacher post_recv_io_failed: 533*1249c01aSStefan Metzmacher /* 534*1249c01aSStefan Metzmacher * ib_dma_unmap_single is called in 535*1249c01aSStefan Metzmacher * smbdirect_connection_free_send_io() 536*1249c01aSStefan Metzmacher */ 537*1249c01aSStefan Metzmacher dma_mapping_failed: 538*1249c01aSStefan Metzmacher smbdirect_connection_free_send_io(send_io); 539*1249c01aSStefan Metzmacher 540*1249c01aSStefan Metzmacher alloc_send_io_failed: 541*1249c01aSStefan Metzmacher smbdirect_connection_put_recv_io(recv_io); 542*1249c01aSStefan Metzmacher 543*1249c01aSStefan Metzmacher get_recv_io_failed: 544*1249c01aSStefan Metzmacher smbdirect_connection_destroy_mem_pools(sc); 545*1249c01aSStefan Metzmacher 546*1249c01aSStefan Metzmacher create_mem_pools_failed: 547*1249c01aSStefan Metzmacher return ret; 548*1249c01aSStefan Metzmacher } 549*1249c01aSStefan Metzmacher 550*1249c01aSStefan Metzmacher static void smbdirect_connect_negotiate_send_done(struct ib_cq *cq, struct ib_wc *wc) 551*1249c01aSStefan Metzmacher { 552*1249c01aSStefan Metzmacher struct smbdirect_send_io *send_io = 553*1249c01aSStefan Metzmacher container_of(wc->wr_cqe, struct smbdirect_send_io, cqe); 554*1249c01aSStefan Metzmacher struct smbdirect_socket *sc = send_io->socket; 555*1249c01aSStefan Metzmacher 556*1249c01aSStefan Metzmacher smbdirect_log_rdma_send(sc, SMBDIRECT_LOG_INFO, 557*1249c01aSStefan Metzmacher "smbdirect_send_io completed. status='%s (%d)', opcode=%d\n", 558*1249c01aSStefan Metzmacher ib_wc_status_msg(wc->status), wc->status, wc->opcode); 559*1249c01aSStefan Metzmacher 560*1249c01aSStefan Metzmacher /* Note this frees wc->wr_cqe, but not wc */ 561*1249c01aSStefan Metzmacher smbdirect_connection_free_send_io(send_io); 562*1249c01aSStefan Metzmacher atomic_dec(&sc->send_io.pending.count); 563*1249c01aSStefan Metzmacher 564*1249c01aSStefan Metzmacher if (unlikely(wc->status != IB_WC_SUCCESS || WARN_ON_ONCE(wc->opcode != IB_WC_SEND))) { 565*1249c01aSStefan Metzmacher if (wc->status != IB_WC_WR_FLUSH_ERR) 566*1249c01aSStefan Metzmacher smbdirect_log_rdma_send(sc, SMBDIRECT_LOG_ERR, 567*1249c01aSStefan Metzmacher "wc->status=%s (%d) wc->opcode=%d\n", 568*1249c01aSStefan Metzmacher ib_wc_status_msg(wc->status), wc->status, wc->opcode); 569*1249c01aSStefan Metzmacher smbdirect_socket_schedule_cleanup(sc, -ECONNABORTED); 570*1249c01aSStefan Metzmacher return; 571*1249c01aSStefan Metzmacher } 572*1249c01aSStefan Metzmacher } 573*1249c01aSStefan Metzmacher 574*1249c01aSStefan Metzmacher static void smbdirect_connect_negotiate_recv_work(struct work_struct *work); 575*1249c01aSStefan Metzmacher 576*1249c01aSStefan Metzmacher static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc *wc) 577*1249c01aSStefan Metzmacher { 578*1249c01aSStefan Metzmacher struct smbdirect_recv_io *recv_io = 579*1249c01aSStefan Metzmacher container_of(wc->wr_cqe, struct smbdirect_recv_io, cqe); 580*1249c01aSStefan Metzmacher struct smbdirect_socket *sc = recv_io->socket; 581*1249c01aSStefan Metzmacher unsigned long flags; 582*1249c01aSStefan Metzmacher 583*1249c01aSStefan Metzmacher if (unlikely(wc->status != IB_WC_SUCCESS || WARN_ON_ONCE(wc->opcode != IB_WC_RECV))) { 584*1249c01aSStefan Metzmacher if (wc->status != IB_WC_WR_FLUSH_ERR) 585*1249c01aSStefan Metzmacher smbdirect_log_rdma_recv(sc, SMBDIRECT_LOG_ERR, 586*1249c01aSStefan Metzmacher "wc->status=%s (%d) wc->opcode=%d\n", 587*1249c01aSStefan Metzmacher ib_wc_status_msg(wc->status), wc->status, wc->opcode); 588*1249c01aSStefan Metzmacher goto error; 589*1249c01aSStefan Metzmacher } 590*1249c01aSStefan Metzmacher 591*1249c01aSStefan Metzmacher smbdirect_log_rdma_recv(sc, SMBDIRECT_LOG_INFO, 592*1249c01aSStefan Metzmacher "smbdirect_recv_io completed. status='%s (%d)', opcode=%d\n", 593*1249c01aSStefan Metzmacher ib_wc_status_msg(wc->status), wc->status, wc->opcode); 594*1249c01aSStefan Metzmacher 595*1249c01aSStefan Metzmacher /* 596*1249c01aSStefan Metzmacher * This is an internal error! 597*1249c01aSStefan Metzmacher */ 598*1249c01aSStefan Metzmacher if (WARN_ON_ONCE(sc->recv_io.expected != SMBDIRECT_EXPECT_NEGOTIATE_REP)) 599*1249c01aSStefan Metzmacher goto error; 600*1249c01aSStefan Metzmacher 601*1249c01aSStefan Metzmacher /* 602*1249c01aSStefan Metzmacher * Don't reset timer to the keepalive interval in 603*1249c01aSStefan Metzmacher * this will be done in smbdirect_accept_direct_negotiate_recv_work. 604*1249c01aSStefan Metzmacher */ 605*1249c01aSStefan Metzmacher 606*1249c01aSStefan Metzmacher ib_dma_sync_single_for_cpu(sc->ib.dev, 607*1249c01aSStefan Metzmacher recv_io->sge.addr, 608*1249c01aSStefan Metzmacher recv_io->sge.length, 609*1249c01aSStefan Metzmacher DMA_FROM_DEVICE); 610*1249c01aSStefan Metzmacher 611*1249c01aSStefan Metzmacher /* 612*1249c01aSStefan Metzmacher * Only remember recv_io if it has enough bytes, 613*1249c01aSStefan Metzmacher * this gives smbdirect_accept_negotiate_recv_work enough 614*1249c01aSStefan Metzmacher * information in order to disconnect if it was not 615*1249c01aSStefan Metzmacher * valid. 616*1249c01aSStefan Metzmacher */ 617*1249c01aSStefan Metzmacher sc->recv_io.reassembly.full_packet_received = true; 618*1249c01aSStefan Metzmacher if (wc->byte_len >= sizeof(struct smbdirect_negotiate_resp)) 619*1249c01aSStefan Metzmacher smbdirect_connection_reassembly_append_recv_io(sc, recv_io, 0); 620*1249c01aSStefan Metzmacher else 621*1249c01aSStefan Metzmacher smbdirect_connection_put_recv_io(recv_io); 622*1249c01aSStefan Metzmacher 623*1249c01aSStefan Metzmacher /* 624*1249c01aSStefan Metzmacher * We continue via the workqueue as we may have 625*1249c01aSStefan Metzmacher * complex work that might sleep. 626*1249c01aSStefan Metzmacher * 627*1249c01aSStefan Metzmacher * So we defer further processing of the negotiation 628*1249c01aSStefan Metzmacher * to smbdirect_connect_negotiate_recv_work(). 629*1249c01aSStefan Metzmacher */ 630*1249c01aSStefan Metzmacher spin_lock_irqsave(&sc->connect.lock, flags); 631*1249c01aSStefan Metzmacher if (!sc->first_error) { 632*1249c01aSStefan Metzmacher INIT_WORK(&sc->connect.work, smbdirect_connect_negotiate_recv_work); 633*1249c01aSStefan Metzmacher if (sc->status == SMBDIRECT_SOCKET_NEGOTIATE_RUNNING) 634*1249c01aSStefan Metzmacher queue_work(sc->workqueues.connect, &sc->connect.work); 635*1249c01aSStefan Metzmacher } 636*1249c01aSStefan Metzmacher spin_unlock_irqrestore(&sc->connect.lock, flags); 637*1249c01aSStefan Metzmacher 638*1249c01aSStefan Metzmacher return; 639*1249c01aSStefan Metzmacher 640*1249c01aSStefan Metzmacher error: 641*1249c01aSStefan Metzmacher /* 642*1249c01aSStefan Metzmacher * recv_io.posted.refill_work is still disabled, 643*1249c01aSStefan Metzmacher * so smbdirect_connection_put_recv_io() won't 644*1249c01aSStefan Metzmacher * start it. 645*1249c01aSStefan Metzmacher */ 646*1249c01aSStefan Metzmacher smbdirect_connection_put_recv_io(recv_io); 647*1249c01aSStefan Metzmacher smbdirect_socket_schedule_cleanup(sc, -ECONNABORTED); 648*1249c01aSStefan Metzmacher } 649*1249c01aSStefan Metzmacher 650*1249c01aSStefan Metzmacher static void smbdirect_connect_negotiate_recv_work(struct work_struct *work) 651*1249c01aSStefan Metzmacher { 652*1249c01aSStefan Metzmacher struct smbdirect_socket *sc = 653*1249c01aSStefan Metzmacher container_of(work, struct smbdirect_socket, connect.work); 654*1249c01aSStefan Metzmacher struct smbdirect_socket_parameters *sp = &sc->parameters; 655*1249c01aSStefan Metzmacher struct smbdirect_recv_io *recv_io; 656*1249c01aSStefan Metzmacher struct smbdirect_negotiate_resp *nrep; 657*1249c01aSStefan Metzmacher unsigned long flags; 658*1249c01aSStefan Metzmacher u16 negotiated_version; 659*1249c01aSStefan Metzmacher u16 credits_requested; 660*1249c01aSStefan Metzmacher u16 credits_granted; 661*1249c01aSStefan Metzmacher u32 status; 662*1249c01aSStefan Metzmacher u32 max_readwrite_size; 663*1249c01aSStefan Metzmacher u32 preferred_send_size; 664*1249c01aSStefan Metzmacher u32 max_receive_size; 665*1249c01aSStefan Metzmacher u32 max_fragmented_size; 666*1249c01aSStefan Metzmacher int posted; 667*1249c01aSStefan Metzmacher int ret; 668*1249c01aSStefan Metzmacher 669*1249c01aSStefan Metzmacher if (sc->first_error) 670*1249c01aSStefan Metzmacher return; 671*1249c01aSStefan Metzmacher 672*1249c01aSStefan Metzmacher /* 673*1249c01aSStefan Metzmacher * make sure we won't start again... 674*1249c01aSStefan Metzmacher */ 675*1249c01aSStefan Metzmacher disable_work(work); 676*1249c01aSStefan Metzmacher 677*1249c01aSStefan Metzmacher /* 678*1249c01aSStefan Metzmacher * Reset timer to the keepalive interval in 679*1249c01aSStefan Metzmacher * order to trigger our next keepalive message. 680*1249c01aSStefan Metzmacher */ 681*1249c01aSStefan Metzmacher sc->idle.keepalive = SMBDIRECT_KEEPALIVE_NONE; 682*1249c01aSStefan Metzmacher mod_delayed_work(sc->workqueues.idle, &sc->idle.timer_work, 683*1249c01aSStefan Metzmacher msecs_to_jiffies(sp->keepalive_interval_msec)); 684*1249c01aSStefan Metzmacher 685*1249c01aSStefan Metzmacher /* 686*1249c01aSStefan Metzmacher * If smbdirect_connect_negotiate_recv_done() detected an 687*1249c01aSStefan Metzmacher * invalid request we want to disconnect. 688*1249c01aSStefan Metzmacher */ 689*1249c01aSStefan Metzmacher recv_io = smbdirect_connection_reassembly_first_recv_io(sc); 690*1249c01aSStefan Metzmacher if (!recv_io) { 691*1249c01aSStefan Metzmacher smbdirect_socket_schedule_cleanup(sc, -ECONNABORTED); 692*1249c01aSStefan Metzmacher return; 693*1249c01aSStefan Metzmacher } 694*1249c01aSStefan Metzmacher spin_lock_irqsave(&sc->recv_io.reassembly.lock, flags); 695*1249c01aSStefan Metzmacher sc->recv_io.reassembly.queue_length--; 696*1249c01aSStefan Metzmacher list_del(&recv_io->list); 697*1249c01aSStefan Metzmacher spin_unlock_irqrestore(&sc->recv_io.reassembly.lock, flags); 698*1249c01aSStefan Metzmacher smbdirect_connection_put_recv_io(recv_io); 699*1249c01aSStefan Metzmacher 700*1249c01aSStefan Metzmacher if (SMBDIRECT_CHECK_STATUS_DISCONNECT(sc, SMBDIRECT_SOCKET_NEGOTIATE_RUNNING)) 701*1249c01aSStefan Metzmacher return; 702*1249c01aSStefan Metzmacher 703*1249c01aSStefan Metzmacher /* 704*1249c01aSStefan Metzmacher * Note recv_io is already part of the free list, 705*1249c01aSStefan Metzmacher * as we just called smbdirect_connection_put_recv_io(), 706*1249c01aSStefan Metzmacher * but it won't be reused before we call 707*1249c01aSStefan Metzmacher * smbdirect_connection_recv_io_refill() below. 708*1249c01aSStefan Metzmacher */ 709*1249c01aSStefan Metzmacher 710*1249c01aSStefan Metzmacher nrep = (struct smbdirect_negotiate_resp *)recv_io->packet; 711*1249c01aSStefan Metzmacher negotiated_version = le16_to_cpu(nrep->negotiated_version); 712*1249c01aSStefan Metzmacher credits_requested = le16_to_cpu(nrep->credits_requested); 713*1249c01aSStefan Metzmacher credits_granted = le16_to_cpu(nrep->credits_granted); 714*1249c01aSStefan Metzmacher status = le32_to_cpu(nrep->status); 715*1249c01aSStefan Metzmacher max_readwrite_size = le32_to_cpu(nrep->max_readwrite_size); 716*1249c01aSStefan Metzmacher preferred_send_size = le32_to_cpu(nrep->preferred_send_size); 717*1249c01aSStefan Metzmacher max_receive_size = le32_to_cpu(nrep->max_receive_size); 718*1249c01aSStefan Metzmacher max_fragmented_size = le32_to_cpu(nrep->max_fragmented_size); 719*1249c01aSStefan Metzmacher 720*1249c01aSStefan Metzmacher smbdirect_log_negotiate(sc, SMBDIRECT_LOG_INFO, 721*1249c01aSStefan Metzmacher "RepIn: %s%x, %s%x, %s%x, %s%u, %s%u, %s%x, %s%u, %s%u, %s%u, %s%u\n", 722*1249c01aSStefan Metzmacher "MinVersion=0x", 723*1249c01aSStefan Metzmacher le16_to_cpu(nrep->min_version), 724*1249c01aSStefan Metzmacher "MaxVersion=0x", 725*1249c01aSStefan Metzmacher le16_to_cpu(nrep->max_version), 726*1249c01aSStefan Metzmacher "NegotiatedVersion=0x", 727*1249c01aSStefan Metzmacher le16_to_cpu(nrep->negotiated_version), 728*1249c01aSStefan Metzmacher "CreditsRequested=", 729*1249c01aSStefan Metzmacher le16_to_cpu(nrep->credits_requested), 730*1249c01aSStefan Metzmacher "CreditsGranted=", 731*1249c01aSStefan Metzmacher le16_to_cpu(nrep->credits_granted), 732*1249c01aSStefan Metzmacher "Status=0x", 733*1249c01aSStefan Metzmacher le32_to_cpu(nrep->status), 734*1249c01aSStefan Metzmacher "MaxReadWriteSize=", 735*1249c01aSStefan Metzmacher le32_to_cpu(nrep->max_readwrite_size), 736*1249c01aSStefan Metzmacher "PreferredSendSize=", 737*1249c01aSStefan Metzmacher le32_to_cpu(nrep->preferred_send_size), 738*1249c01aSStefan Metzmacher "MaxRecvSize=", 739*1249c01aSStefan Metzmacher le32_to_cpu(nrep->max_receive_size), 740*1249c01aSStefan Metzmacher "MaxFragmentedSize=", 741*1249c01aSStefan Metzmacher le32_to_cpu(nrep->max_fragmented_size)); 742*1249c01aSStefan Metzmacher 743*1249c01aSStefan Metzmacher if (negotiated_version != SMBDIRECT_V1) { 744*1249c01aSStefan Metzmacher smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR, 745*1249c01aSStefan Metzmacher "invalid: negotiated_version=0x%x\n", 746*1249c01aSStefan Metzmacher negotiated_version); 747*1249c01aSStefan Metzmacher smbdirect_socket_schedule_cleanup(sc, -ECONNREFUSED); 748*1249c01aSStefan Metzmacher return; 749*1249c01aSStefan Metzmacher } 750*1249c01aSStefan Metzmacher 751*1249c01aSStefan Metzmacher if (status != le32_to_cpu(STATUS_SUCCESS)) { 752*1249c01aSStefan Metzmacher smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR, 753*1249c01aSStefan Metzmacher "invalid: status=0x%x != 0x0\n", 754*1249c01aSStefan Metzmacher status); 755*1249c01aSStefan Metzmacher smbdirect_socket_schedule_cleanup(sc, -ECONNREFUSED); 756*1249c01aSStefan Metzmacher return; 757*1249c01aSStefan Metzmacher } 758*1249c01aSStefan Metzmacher 759*1249c01aSStefan Metzmacher if (max_receive_size < SMBDIRECT_MIN_RECEIVE_SIZE) { 760*1249c01aSStefan Metzmacher smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR, 761*1249c01aSStefan Metzmacher "invalid: max_receive_size=%u < %u\n", 762*1249c01aSStefan Metzmacher max_receive_size, 763*1249c01aSStefan Metzmacher SMBDIRECT_MIN_RECEIVE_SIZE); 764*1249c01aSStefan Metzmacher smbdirect_socket_schedule_cleanup(sc, -ECONNABORTED); 765*1249c01aSStefan Metzmacher return; 766*1249c01aSStefan Metzmacher } 767*1249c01aSStefan Metzmacher 768*1249c01aSStefan Metzmacher if (max_fragmented_size < SMBDIRECT_MIN_FRAGMENTED_SIZE) { 769*1249c01aSStefan Metzmacher smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR, 770*1249c01aSStefan Metzmacher "invalid: max_fragmented_size=%u < %u\n", 771*1249c01aSStefan Metzmacher max_fragmented_size, 772*1249c01aSStefan Metzmacher SMBDIRECT_MIN_FRAGMENTED_SIZE); 773*1249c01aSStefan Metzmacher smbdirect_socket_schedule_cleanup(sc, -ECONNABORTED); 774*1249c01aSStefan Metzmacher return; 775*1249c01aSStefan Metzmacher } 776*1249c01aSStefan Metzmacher 777*1249c01aSStefan Metzmacher if (credits_granted == 0) { 778*1249c01aSStefan Metzmacher smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR, 779*1249c01aSStefan Metzmacher "invalid: credits_granted == 0\n"); 780*1249c01aSStefan Metzmacher smbdirect_socket_schedule_cleanup(sc, -ECONNABORTED); 781*1249c01aSStefan Metzmacher return; 782*1249c01aSStefan Metzmacher } 783*1249c01aSStefan Metzmacher 784*1249c01aSStefan Metzmacher if (credits_requested == 0) { 785*1249c01aSStefan Metzmacher smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR, 786*1249c01aSStefan Metzmacher "invalid: credits_requested == 0\n"); 787*1249c01aSStefan Metzmacher smbdirect_socket_schedule_cleanup(sc, -ECONNABORTED); 788*1249c01aSStefan Metzmacher return; 789*1249c01aSStefan Metzmacher } 790*1249c01aSStefan Metzmacher 791*1249c01aSStefan Metzmacher if (preferred_send_size > sp->max_recv_size) { 792*1249c01aSStefan Metzmacher smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR, 793*1249c01aSStefan Metzmacher "invalid: preferred_send_size=%u > max_recv_size=%u\n", 794*1249c01aSStefan Metzmacher preferred_send_size, 795*1249c01aSStefan Metzmacher sp->max_recv_size); 796*1249c01aSStefan Metzmacher smbdirect_socket_schedule_cleanup(sc, -ECONNABORTED); 797*1249c01aSStefan Metzmacher return; 798*1249c01aSStefan Metzmacher } 799*1249c01aSStefan Metzmacher 800*1249c01aSStefan Metzmacher /* 801*1249c01aSStefan Metzmacher * We take the value from the peer, which is checked to be higher than 0, 802*1249c01aSStefan Metzmacher * but we limit it to the max value we support in order to have 803*1249c01aSStefan Metzmacher * the main logic simpler. 804*1249c01aSStefan Metzmacher */ 805*1249c01aSStefan Metzmacher sc->recv_io.credits.target = credits_requested; 806*1249c01aSStefan Metzmacher sc->recv_io.credits.target = min_t(u16, sc->recv_io.credits.target, 807*1249c01aSStefan Metzmacher sp->recv_credit_max); 808*1249c01aSStefan Metzmacher 809*1249c01aSStefan Metzmacher /* 810*1249c01aSStefan Metzmacher * At least the value of SMBDIRECT_MIN_RECEIVE_SIZE is used. 811*1249c01aSStefan Metzmacher */ 812*1249c01aSStefan Metzmacher sp->max_recv_size = min_t(u32, sp->max_recv_size, preferred_send_size); 813*1249c01aSStefan Metzmacher sp->max_recv_size = max_t(u32, sp->max_recv_size, SMBDIRECT_MIN_RECEIVE_SIZE); 814*1249c01aSStefan Metzmacher 815*1249c01aSStefan Metzmacher /* 816*1249c01aSStefan Metzmacher * We already sent our sp->max_fragmented_recv_size 817*1249c01aSStefan Metzmacher * to the peer, so we can't lower it here any more. 818*1249c01aSStefan Metzmacher * 819*1249c01aSStefan Metzmacher * TODO: but if the peer lowered sp->max_recv_size 820*1249c01aSStefan Metzmacher * we will have to adjust our number of buffers. 821*1249c01aSStefan Metzmacher * 822*1249c01aSStefan Metzmacher * But for now we keep it as the cifs.ko code 823*1249c01aSStefan Metzmacher * worked before. 824*1249c01aSStefan Metzmacher */ 825*1249c01aSStefan Metzmacher 826*1249c01aSStefan Metzmacher /* 827*1249c01aSStefan Metzmacher * Note nrep->max_receive_size was already checked against 828*1249c01aSStefan Metzmacher * SMBDIRECT_MIN_RECEIVE_SIZE above. 829*1249c01aSStefan Metzmacher */ 830*1249c01aSStefan Metzmacher sp->max_send_size = min_t(u32, sp->max_send_size, max_receive_size); 831*1249c01aSStefan Metzmacher 832*1249c01aSStefan Metzmacher /* 833*1249c01aSStefan Metzmacher * Make sure the resulting max_frmr_depth is at least 1, 834*1249c01aSStefan Metzmacher * which means max_read_write_size needs to be at least PAGE_SIZE. 835*1249c01aSStefan Metzmacher */ 836*1249c01aSStefan Metzmacher sp->max_read_write_size = min_t(u32, sp->max_frmr_depth * PAGE_SIZE, 837*1249c01aSStefan Metzmacher max_readwrite_size); 838*1249c01aSStefan Metzmacher if (sp->max_read_write_size < PAGE_SIZE) { 839*1249c01aSStefan Metzmacher smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR, 840*1249c01aSStefan Metzmacher "invalid: max_readwrite_size=%u < PAGE_SIZE(%lu)\n", 841*1249c01aSStefan Metzmacher max_readwrite_size, 842*1249c01aSStefan Metzmacher PAGE_SIZE); 843*1249c01aSStefan Metzmacher smbdirect_socket_schedule_cleanup(sc, -ECONNABORTED); 844*1249c01aSStefan Metzmacher return; 845*1249c01aSStefan Metzmacher } 846*1249c01aSStefan Metzmacher sp->max_frmr_depth = sp->max_read_write_size / PAGE_SIZE; 847*1249c01aSStefan Metzmacher 848*1249c01aSStefan Metzmacher /* 849*1249c01aSStefan Metzmacher * Note nrep->credits_granted was already checked against 0 above. 850*1249c01aSStefan Metzmacher */ 851*1249c01aSStefan Metzmacher atomic_set(&sc->send_io.credits.count, credits_granted); 852*1249c01aSStefan Metzmacher 853*1249c01aSStefan Metzmacher /* 854*1249c01aSStefan Metzmacher * Note nrep->max_fragmented_size was already checked against 855*1249c01aSStefan Metzmacher * SMBDIRECT_MIN_FRAGMENTED_SIZE above. 856*1249c01aSStefan Metzmacher */ 857*1249c01aSStefan Metzmacher sp->max_fragmented_send_size = max_fragmented_size; 858*1249c01aSStefan Metzmacher 859*1249c01aSStefan Metzmacher ret = smbdirect_connection_create_mr_list(sc); 860*1249c01aSStefan Metzmacher if (ret) { 861*1249c01aSStefan Metzmacher smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR, 862*1249c01aSStefan Metzmacher "smbdirect_connection_create_mr_list() failed %1pe\n", 863*1249c01aSStefan Metzmacher SMBDIRECT_DEBUG_ERR_PTR(ret)); 864*1249c01aSStefan Metzmacher smbdirect_socket_schedule_cleanup(sc, ret); 865*1249c01aSStefan Metzmacher return; 866*1249c01aSStefan Metzmacher } 867*1249c01aSStefan Metzmacher 868*1249c01aSStefan Metzmacher /* 869*1249c01aSStefan Metzmacher * Prepare for receiving data_transfer messages 870*1249c01aSStefan Metzmacher */ 871*1249c01aSStefan Metzmacher sc->recv_io.reassembly.full_packet_received = true; 872*1249c01aSStefan Metzmacher sc->recv_io.expected = SMBDIRECT_EXPECT_DATA_TRANSFER; 873*1249c01aSStefan Metzmacher list_for_each_entry(recv_io, &sc->recv_io.free.list, list) 874*1249c01aSStefan Metzmacher recv_io->cqe.done = smbdirect_connection_recv_io_done; 875*1249c01aSStefan Metzmacher recv_io = NULL; 876*1249c01aSStefan Metzmacher 877*1249c01aSStefan Metzmacher /* 878*1249c01aSStefan Metzmacher * We should at least post 1 smbdirect_recv_io! 879*1249c01aSStefan Metzmacher */ 880*1249c01aSStefan Metzmacher posted = smbdirect_connection_recv_io_refill(sc); 881*1249c01aSStefan Metzmacher if (posted < 1) { 882*1249c01aSStefan Metzmacher smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR, 883*1249c01aSStefan Metzmacher "smbdirect_connection_recv_io_refill() failed %1pe\n", 884*1249c01aSStefan Metzmacher SMBDIRECT_DEBUG_ERR_PTR(ret)); 885*1249c01aSStefan Metzmacher smbdirect_socket_schedule_cleanup(sc, -ECONNABORTED); 886*1249c01aSStefan Metzmacher return; 887*1249c01aSStefan Metzmacher } 888*1249c01aSStefan Metzmacher 889*1249c01aSStefan Metzmacher /* 890*1249c01aSStefan Metzmacher * smbdirect_connection_negotiation_done() 891*1249c01aSStefan Metzmacher * will setup all required things and wake up 892*1249c01aSStefan Metzmacher * the waiter. 893*1249c01aSStefan Metzmacher */ 894*1249c01aSStefan Metzmacher smbdirect_connection_negotiation_done(sc); 895*1249c01aSStefan Metzmacher } 896*1249c01aSStefan Metzmacher 897*1249c01aSStefan Metzmacher int smbdirect_connect_sync(struct smbdirect_socket *sc, 898*1249c01aSStefan Metzmacher const struct sockaddr *dst) 899*1249c01aSStefan Metzmacher { 900*1249c01aSStefan Metzmacher int ret; 901*1249c01aSStefan Metzmacher 902*1249c01aSStefan Metzmacher ret = smbdirect_connect(sc, dst); 903*1249c01aSStefan Metzmacher if (ret) { 904*1249c01aSStefan Metzmacher smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR, 905*1249c01aSStefan Metzmacher "smbdirect_connect(%pISpsfc) failed %1pe\n", 906*1249c01aSStefan Metzmacher dst, SMBDIRECT_DEBUG_ERR_PTR(ret)); 907*1249c01aSStefan Metzmacher return ret; 908*1249c01aSStefan Metzmacher } 909*1249c01aSStefan Metzmacher 910*1249c01aSStefan Metzmacher ret = smbdirect_connection_wait_for_connected(sc); 911*1249c01aSStefan Metzmacher if (ret) { 912*1249c01aSStefan Metzmacher int lvl = SMBDIRECT_LOG_ERR; 913*1249c01aSStefan Metzmacher 914*1249c01aSStefan Metzmacher if (ret == -ENODEV) 915*1249c01aSStefan Metzmacher lvl = SMBDIRECT_LOG_INFO; 916*1249c01aSStefan Metzmacher 917*1249c01aSStefan Metzmacher smbdirect_log_rdma_event(sc, lvl, 918*1249c01aSStefan Metzmacher "wait for smbdirect_connect(%pISpsfc) failed %1pe\n", 919*1249c01aSStefan Metzmacher dst, SMBDIRECT_DEBUG_ERR_PTR(ret)); 920*1249c01aSStefan Metzmacher return ret; 921*1249c01aSStefan Metzmacher } 922*1249c01aSStefan Metzmacher 923*1249c01aSStefan Metzmacher return 0; 924*1249c01aSStefan Metzmacher } 925*1249c01aSStefan Metzmacher __SMBDIRECT_EXPORT_SYMBOL__(smbdirect_connect_sync); 926