1219820Sjeff/* 2219820Sjeff * Copyright (c) 2006 Mellanox Technologies Ltd. All rights reserved. 3219820Sjeff * 4219820Sjeff * This software is available to you under a choice of one of two 5219820Sjeff * licenses. You may choose to be licensed under the terms of the GNU 6219820Sjeff * General Public License (GPL) Version 2, available from the file 7219820Sjeff * COPYING in the main directory of this source tree, or the 8219820Sjeff * OpenIB.org BSD license below: 9219820Sjeff * 10219820Sjeff * Redistribution and use in source and binary forms, with or 11219820Sjeff * without modification, are permitted provided that the following 12219820Sjeff * conditions are met: 13219820Sjeff * 14219820Sjeff * - Redistributions of source code must retain the above 15219820Sjeff * copyright notice, this list of conditions and the following 16219820Sjeff * disclaimer. 17219820Sjeff * 18219820Sjeff * - Redistributions in binary form must reproduce the above 19219820Sjeff * copyright notice, this list of conditions and the following 20219820Sjeff * disclaimer in the documentation and/or other materials 21219820Sjeff * provided with the distribution. 22219820Sjeff * 23219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30219820Sjeff * SOFTWARE. 31219820Sjeff * 32219820Sjeff * $Id$ 33219820Sjeff */ 34219820Sjeff#include "sdp.h" 35219820Sjeff 36219820Sjeff#define SDP_MAJV_MINV 0x22 37219820Sjeff 38219820SjeffSDP_MODPARAM_SINT(sdp_link_layer_ib_only, 1, "Support only link layer of " 39219820Sjeff "type Infiniband"); 40219820Sjeff 41219820Sjeffenum { 42219820Sjeff SDP_HH_SIZE = 76, 43219820Sjeff SDP_HAH_SIZE = 180, 44219820Sjeff}; 45219820Sjeff 46219820Sjeffstatic void 47219820Sjeffsdp_qp_event_handler(struct ib_event *event, void *data) 48219820Sjeff{ 49219820Sjeff} 50219820Sjeff 51219820Sjeffstatic int 52219820Sjeffsdp_get_max_dev_sge(struct ib_device *dev) 53219820Sjeff{ 54331769Shselasky struct ib_device_attr *device_attr; 55219820Sjeff static int max_sges = -1; 56219820Sjeff 57219820Sjeff if (max_sges > 0) 58219820Sjeff goto out; 59219820Sjeff 60331769Shselasky device_attr = &dev->attrs; 61331769Shselasky max_sges = device_attr->max_sge; 62219820Sjeff 63219820Sjeffout: 64219820Sjeff return max_sges; 65219820Sjeff} 66219820Sjeff 67219820Sjeffstatic int 68219820Sjeffsdp_init_qp(struct socket *sk, struct rdma_cm_id *id) 69219820Sjeff{ 70219820Sjeff struct ib_qp_init_attr qp_init_attr = { 71219820Sjeff .event_handler = sdp_qp_event_handler, 72219820Sjeff .cap.max_send_wr = SDP_TX_SIZE, 73219820Sjeff .cap.max_recv_wr = SDP_RX_SIZE, 74219820Sjeff .sq_sig_type = IB_SIGNAL_REQ_WR, 75219820Sjeff .qp_type = IB_QPT_RC, 76219820Sjeff }; 77219820Sjeff struct ib_device *device = id->device; 78219820Sjeff struct sdp_sock *ssk; 79219820Sjeff int rc; 80219820Sjeff 81219820Sjeff sdp_dbg(sk, "%s\n", __func__); 82219820Sjeff 83219820Sjeff ssk = sdp_sk(sk); 84219820Sjeff ssk->max_sge = sdp_get_max_dev_sge(device); 85219820Sjeff sdp_dbg(sk, "Max sges: %d\n", ssk->max_sge); 86219820Sjeff 87219820Sjeff qp_init_attr.cap.max_send_sge = MIN(ssk->max_sge, SDP_MAX_SEND_SGES); 88219820Sjeff sdp_dbg(sk, "Setting max send sge to: %d\n", 89219820Sjeff qp_init_attr.cap.max_send_sge); 90219820Sjeff 91219820Sjeff qp_init_attr.cap.max_recv_sge = MIN(ssk->max_sge, SDP_MAX_RECV_SGES); 92219820Sjeff sdp_dbg(sk, "Setting max recv sge to: %d\n", 93219820Sjeff qp_init_attr.cap.max_recv_sge); 94219820Sjeff 95219820Sjeff ssk->sdp_dev = ib_get_client_data(device, &sdp_client); 96219820Sjeff if (!ssk->sdp_dev) { 97219820Sjeff sdp_warn(sk, "SDP not available on device %s\n", device->name); 98219820Sjeff rc = -ENODEV; 99219820Sjeff goto err_rx; 100219820Sjeff } 101219820Sjeff 102219820Sjeff rc = sdp_rx_ring_create(ssk, device); 103219820Sjeff if (rc) 104219820Sjeff goto err_rx; 105219820Sjeff 106219820Sjeff rc = sdp_tx_ring_create(ssk, device); 107219820Sjeff if (rc) 108219820Sjeff goto err_tx; 109219820Sjeff 110219820Sjeff qp_init_attr.recv_cq = ssk->rx_ring.cq; 111219820Sjeff qp_init_attr.send_cq = ssk->tx_ring.cq; 112219820Sjeff 113219820Sjeff rc = rdma_create_qp(id, ssk->sdp_dev->pd, &qp_init_attr); 114219820Sjeff if (rc) { 115219820Sjeff sdp_warn(sk, "Unable to create QP: %d.\n", rc); 116219820Sjeff goto err_qp; 117219820Sjeff } 118219820Sjeff ssk->qp = id->qp; 119219820Sjeff ssk->ib_device = device; 120219820Sjeff ssk->qp_active = 1; 121219820Sjeff ssk->context.device = device; 122219820Sjeff 123219820Sjeff sdp_dbg(sk, "%s done\n", __func__); 124219820Sjeff return 0; 125219820Sjeff 126219820Sjefferr_qp: 127219820Sjeff sdp_tx_ring_destroy(ssk); 128219820Sjefferr_tx: 129219820Sjeff sdp_rx_ring_destroy(ssk); 130219820Sjefferr_rx: 131219820Sjeff return rc; 132219820Sjeff} 133219820Sjeff 134219820Sjeffstatic int 135219820Sjeffsdp_connect_handler(struct socket *sk, struct rdma_cm_id *id, 136219820Sjeff struct rdma_cm_event *event) 137219820Sjeff{ 138219820Sjeff struct sockaddr_in *src_addr; 139219820Sjeff struct sockaddr_in *dst_addr; 140219820Sjeff struct socket *child; 141219820Sjeff const struct sdp_hh *h; 142219820Sjeff struct sdp_sock *ssk; 143219820Sjeff int rc; 144219820Sjeff 145219820Sjeff sdp_dbg(sk, "%s %p -> %p\n", __func__, sdp_sk(sk)->id, id); 146219820Sjeff 147219820Sjeff h = event->param.conn.private_data; 148219820Sjeff SDP_DUMP_PACKET(sk, "RX", NULL, &h->bsdh); 149219820Sjeff 150219820Sjeff if (!h->max_adverts) 151219820Sjeff return -EINVAL; 152219820Sjeff 153219820Sjeff child = sonewconn(sk, SS_ISCONNECTED); 154219820Sjeff if (!child) 155219820Sjeff return -ENOMEM; 156219820Sjeff 157219820Sjeff ssk = sdp_sk(child); 158219820Sjeff rc = sdp_init_qp(child, id); 159219820Sjeff if (rc) 160219820Sjeff return rc; 161219820Sjeff SDP_WLOCK(ssk); 162219820Sjeff id->context = ssk; 163219820Sjeff ssk->id = id; 164219820Sjeff ssk->socket = child; 165219820Sjeff ssk->cred = crhold(child->so_cred); 166219820Sjeff dst_addr = (struct sockaddr_in *)&id->route.addr.dst_addr; 167219820Sjeff src_addr = (struct sockaddr_in *)&id->route.addr.src_addr; 168219820Sjeff ssk->fport = dst_addr->sin_port; 169219820Sjeff ssk->faddr = dst_addr->sin_addr.s_addr; 170219820Sjeff ssk->lport = src_addr->sin_port; 171219820Sjeff ssk->max_bufs = ntohs(h->bsdh.bufs); 172219820Sjeff atomic_set(&ssk->tx_ring.credits, ssk->max_bufs); 173219820Sjeff ssk->min_bufs = tx_credits(ssk) / 4; 174219820Sjeff ssk->xmit_size_goal = ntohl(h->localrcvsz) - sizeof(struct sdp_bsdh); 175219820Sjeff sdp_init_buffers(ssk, rcvbuf_initial_size); 176219820Sjeff ssk->state = TCPS_SYN_RECEIVED; 177219820Sjeff SDP_WUNLOCK(ssk); 178219820Sjeff 179219820Sjeff return 0; 180219820Sjeff} 181219820Sjeff 182219820Sjeffstatic int 183219820Sjeffsdp_response_handler(struct socket *sk, struct rdma_cm_id *id, 184219820Sjeff struct rdma_cm_event *event) 185219820Sjeff{ 186219820Sjeff const struct sdp_hah *h; 187219820Sjeff struct sockaddr_in *dst_addr; 188219820Sjeff struct sdp_sock *ssk; 189219820Sjeff sdp_dbg(sk, "%s\n", __func__); 190219820Sjeff 191219820Sjeff ssk = sdp_sk(sk); 192219820Sjeff SDP_WLOCK(ssk); 193219820Sjeff ssk->state = TCPS_ESTABLISHED; 194219820Sjeff sdp_set_default_moderation(ssk); 195219820Sjeff if (ssk->flags & SDP_DROPPED) { 196219820Sjeff SDP_WUNLOCK(ssk); 197219820Sjeff return 0; 198219820Sjeff } 199219820Sjeff if (sk->so_options & SO_KEEPALIVE) 200219820Sjeff sdp_start_keepalive_timer(sk); 201219820Sjeff h = event->param.conn.private_data; 202219820Sjeff SDP_DUMP_PACKET(sk, "RX", NULL, &h->bsdh); 203219820Sjeff ssk->max_bufs = ntohs(h->bsdh.bufs); 204219820Sjeff atomic_set(&ssk->tx_ring.credits, ssk->max_bufs); 205219820Sjeff ssk->min_bufs = tx_credits(ssk) / 4; 206219820Sjeff ssk->xmit_size_goal = 207219820Sjeff ntohl(h->actrcvsz) - sizeof(struct sdp_bsdh); 208219820Sjeff ssk->poll_cq = 1; 209219820Sjeff 210219820Sjeff dst_addr = (struct sockaddr_in *)&id->route.addr.dst_addr; 211219820Sjeff ssk->fport = dst_addr->sin_port; 212219820Sjeff ssk->faddr = dst_addr->sin_addr.s_addr; 213219820Sjeff soisconnected(sk); 214219820Sjeff SDP_WUNLOCK(ssk); 215219820Sjeff 216219820Sjeff return 0; 217219820Sjeff} 218219820Sjeff 219219820Sjeffstatic int 220219820Sjeffsdp_connected_handler(struct socket *sk, struct rdma_cm_event *event) 221219820Sjeff{ 222219820Sjeff struct sdp_sock *ssk; 223219820Sjeff 224219820Sjeff sdp_dbg(sk, "%s\n", __func__); 225219820Sjeff 226219820Sjeff ssk = sdp_sk(sk); 227219820Sjeff SDP_WLOCK(ssk); 228219820Sjeff ssk->state = TCPS_ESTABLISHED; 229219820Sjeff 230219820Sjeff sdp_set_default_moderation(ssk); 231219820Sjeff 232219820Sjeff if (sk->so_options & SO_KEEPALIVE) 233219820Sjeff sdp_start_keepalive_timer(sk); 234219820Sjeff 235219820Sjeff if ((ssk->flags & SDP_DROPPED) == 0) 236219820Sjeff soisconnected(sk); 237219820Sjeff SDP_WUNLOCK(ssk); 238219820Sjeff return 0; 239219820Sjeff} 240219820Sjeff 241219820Sjeffstatic int 242219820Sjeffsdp_disconnected_handler(struct socket *sk) 243219820Sjeff{ 244219820Sjeff struct sdp_sock *ssk; 245219820Sjeff 246219820Sjeff ssk = sdp_sk(sk); 247219820Sjeff sdp_dbg(sk, "%s\n", __func__); 248219820Sjeff 249219820Sjeff SDP_WLOCK_ASSERT(ssk); 250219820Sjeff if (sdp_sk(sk)->state == TCPS_SYN_RECEIVED) { 251219820Sjeff sdp_connected_handler(sk, NULL); 252219820Sjeff 253219820Sjeff if (rcv_nxt(ssk)) 254219820Sjeff return 0; 255219820Sjeff } 256219820Sjeff 257219820Sjeff return -ECONNRESET; 258219820Sjeff} 259219820Sjeff 260219820Sjeffint 261219820Sjeffsdp_cma_handler(struct rdma_cm_id *id, struct rdma_cm_event *event) 262219820Sjeff{ 263219820Sjeff struct rdma_conn_param conn_param; 264219820Sjeff struct socket *sk; 265219820Sjeff struct sdp_sock *ssk; 266219820Sjeff struct sdp_hah hah; 267219820Sjeff struct sdp_hh hh; 268219820Sjeff 269219820Sjeff int rc = 0; 270219820Sjeff 271219820Sjeff ssk = id->context; 272219820Sjeff sk = NULL; 273219820Sjeff if (ssk) 274219820Sjeff sk = ssk->socket; 275219820Sjeff if (!ssk || !sk || !ssk->id) { 276219820Sjeff sdp_dbg(sk, 277219820Sjeff "cm_id is being torn down, event %d, ssk %p, sk %p, id %p\n", 278219820Sjeff event->event, ssk, sk, id); 279219820Sjeff return event->event == RDMA_CM_EVENT_CONNECT_REQUEST ? 280219820Sjeff -EINVAL : 0; 281219820Sjeff } 282219820Sjeff 283219820Sjeff sdp_dbg(sk, "%s event %d id %p\n", __func__, event->event, id); 284219820Sjeff switch (event->event) { 285219820Sjeff case RDMA_CM_EVENT_ADDR_RESOLVED: 286219820Sjeff sdp_dbg(sk, "RDMA_CM_EVENT_ADDR_RESOLVED\n"); 287219820Sjeff 288219820Sjeff if (sdp_link_layer_ib_only && 289219820Sjeff rdma_node_get_transport(id->device->node_type) == 290219820Sjeff RDMA_TRANSPORT_IB && 291219820Sjeff rdma_port_get_link_layer(id->device, id->port_num) != 292219820Sjeff IB_LINK_LAYER_INFINIBAND) { 293219820Sjeff sdp_dbg(sk, "Link layer is: %d. Only IB link layer " 294219820Sjeff "is allowed\n", 295219820Sjeff rdma_port_get_link_layer(id->device, id->port_num)); 296219820Sjeff rc = -ENETUNREACH; 297219820Sjeff break; 298219820Sjeff } 299219820Sjeff 300219820Sjeff rc = rdma_resolve_route(id, SDP_ROUTE_TIMEOUT); 301219820Sjeff break; 302219820Sjeff case RDMA_CM_EVENT_ADDR_ERROR: 303219820Sjeff sdp_dbg(sk, "RDMA_CM_EVENT_ADDR_ERROR\n"); 304219820Sjeff rc = -ENETUNREACH; 305219820Sjeff break; 306219820Sjeff case RDMA_CM_EVENT_ROUTE_RESOLVED: 307219820Sjeff sdp_dbg(sk, "RDMA_CM_EVENT_ROUTE_RESOLVED : %p\n", id); 308219820Sjeff rc = sdp_init_qp(sk, id); 309219820Sjeff if (rc) 310219820Sjeff break; 311219820Sjeff atomic_set(&sdp_sk(sk)->remote_credits, 312219820Sjeff rx_ring_posted(sdp_sk(sk))); 313219820Sjeff memset(&hh, 0, sizeof hh); 314219820Sjeff hh.bsdh.mid = SDP_MID_HELLO; 315219820Sjeff hh.bsdh.len = htonl(sizeof(struct sdp_hh)); 316219820Sjeff hh.max_adverts = 1; 317219820Sjeff hh.ipv_cap = 0x40; 318219820Sjeff hh.majv_minv = SDP_MAJV_MINV; 319219820Sjeff sdp_init_buffers(sdp_sk(sk), rcvbuf_initial_size); 320219820Sjeff hh.bsdh.bufs = htons(rx_ring_posted(sdp_sk(sk))); 321219820Sjeff hh.localrcvsz = hh.desremrcvsz = htonl(sdp_sk(sk)->recv_bytes); 322219820Sjeff hh.max_adverts = 0x1; 323219820Sjeff sdp_sk(sk)->laddr = 324219820Sjeff ((struct sockaddr_in *)&id->route.addr.src_addr)->sin_addr.s_addr; 325219820Sjeff memset(&conn_param, 0, sizeof conn_param); 326219820Sjeff conn_param.private_data_len = sizeof hh; 327219820Sjeff conn_param.private_data = &hh; 328219820Sjeff conn_param.responder_resources = 4 /* TODO */; 329219820Sjeff conn_param.initiator_depth = 4 /* TODO */; 330219820Sjeff conn_param.retry_count = SDP_RETRY_COUNT; 331219820Sjeff SDP_DUMP_PACKET(NULL, "TX", NULL, &hh.bsdh); 332219820Sjeff rc = rdma_connect(id, &conn_param); 333219820Sjeff break; 334219820Sjeff case RDMA_CM_EVENT_ROUTE_ERROR: 335219820Sjeff sdp_dbg(sk, "RDMA_CM_EVENT_ROUTE_ERROR : %p\n", id); 336219820Sjeff rc = -ETIMEDOUT; 337219820Sjeff break; 338219820Sjeff case RDMA_CM_EVENT_CONNECT_REQUEST: 339219820Sjeff sdp_dbg(sk, "RDMA_CM_EVENT_CONNECT_REQUEST\n"); 340219820Sjeff rc = sdp_connect_handler(sk, id, event); 341219820Sjeff if (rc) { 342219820Sjeff sdp_dbg(sk, "Destroying qp\n"); 343219820Sjeff rdma_reject(id, NULL, 0); 344219820Sjeff break; 345219820Sjeff } 346219820Sjeff ssk = id->context; 347219820Sjeff atomic_set(&ssk->remote_credits, rx_ring_posted(ssk)); 348219820Sjeff memset(&hah, 0, sizeof hah); 349219820Sjeff hah.bsdh.mid = SDP_MID_HELLO_ACK; 350219820Sjeff hah.bsdh.bufs = htons(rx_ring_posted(ssk)); 351219820Sjeff hah.bsdh.len = htonl(sizeof(struct sdp_hah)); 352219820Sjeff hah.majv_minv = SDP_MAJV_MINV; 353219820Sjeff hah.ext_max_adverts = 1; /* Doesn't seem to be mandated by spec, 354219820Sjeff but just in case */ 355219820Sjeff hah.actrcvsz = htonl(ssk->recv_bytes); 356219820Sjeff memset(&conn_param, 0, sizeof conn_param); 357219820Sjeff conn_param.private_data_len = sizeof hah; 358219820Sjeff conn_param.private_data = &hah; 359219820Sjeff conn_param.responder_resources = 4 /* TODO */; 360219820Sjeff conn_param.initiator_depth = 4 /* TODO */; 361219820Sjeff conn_param.retry_count = SDP_RETRY_COUNT; 362219820Sjeff SDP_DUMP_PACKET(sk, "TX", NULL, &hah.bsdh); 363219820Sjeff rc = rdma_accept(id, &conn_param); 364219820Sjeff if (rc) { 365219820Sjeff ssk->id = NULL; 366219820Sjeff id->qp = NULL; 367219820Sjeff id->context = NULL; 368219820Sjeff } 369219820Sjeff break; 370219820Sjeff case RDMA_CM_EVENT_CONNECT_RESPONSE: 371219820Sjeff sdp_dbg(sk, "RDMA_CM_EVENT_CONNECT_RESPONSE\n"); 372219820Sjeff rc = sdp_response_handler(sk, id, event); 373219820Sjeff if (rc) { 374219820Sjeff sdp_dbg(sk, "Destroying qp\n"); 375219820Sjeff rdma_reject(id, NULL, 0); 376219820Sjeff } else 377219820Sjeff rc = rdma_accept(id, NULL); 378219820Sjeff break; 379219820Sjeff case RDMA_CM_EVENT_CONNECT_ERROR: 380219820Sjeff sdp_dbg(sk, "RDMA_CM_EVENT_CONNECT_ERROR\n"); 381219820Sjeff rc = -ETIMEDOUT; 382219820Sjeff break; 383219820Sjeff case RDMA_CM_EVENT_UNREACHABLE: 384219820Sjeff sdp_dbg(sk, "RDMA_CM_EVENT_UNREACHABLE\n"); 385219820Sjeff rc = -ENETUNREACH; 386219820Sjeff break; 387219820Sjeff case RDMA_CM_EVENT_REJECTED: 388219820Sjeff sdp_dbg(sk, "RDMA_CM_EVENT_REJECTED\n"); 389219820Sjeff rc = -ECONNREFUSED; 390219820Sjeff break; 391219820Sjeff case RDMA_CM_EVENT_ESTABLISHED: 392219820Sjeff sdp_dbg(sk, "RDMA_CM_EVENT_ESTABLISHED\n"); 393219820Sjeff sdp_sk(sk)->laddr = 394219820Sjeff ((struct sockaddr_in *)&id->route.addr.src_addr)->sin_addr.s_addr; 395219820Sjeff rc = sdp_connected_handler(sk, event); 396219820Sjeff break; 397219820Sjeff case RDMA_CM_EVENT_DISCONNECTED: /* This means DREQ/DREP received */ 398219820Sjeff sdp_dbg(sk, "RDMA_CM_EVENT_DISCONNECTED\n"); 399219820Sjeff 400219820Sjeff SDP_WLOCK(ssk); 401219820Sjeff if (ssk->state == TCPS_LAST_ACK) { 402219820Sjeff sdp_cancel_dreq_wait_timeout(ssk); 403219820Sjeff 404219820Sjeff sdp_dbg(sk, "%s: waiting for Infiniband tear down\n", 405219820Sjeff __func__); 406219820Sjeff } 407219820Sjeff ssk->qp_active = 0; 408219820Sjeff SDP_WUNLOCK(ssk); 409219820Sjeff rdma_disconnect(id); 410219820Sjeff SDP_WLOCK(ssk); 411219820Sjeff if (ssk->state != TCPS_TIME_WAIT) { 412219820Sjeff if (ssk->state == TCPS_CLOSE_WAIT) { 413219820Sjeff sdp_dbg(sk, "IB teardown while in " 414219820Sjeff "TCPS_CLOSE_WAIT taking reference to " 415219820Sjeff "let close() finish the work\n"); 416219820Sjeff } 417219820Sjeff rc = sdp_disconnected_handler(sk); 418219820Sjeff if (rc) 419219820Sjeff rc = -EPIPE; 420219820Sjeff } 421219820Sjeff SDP_WUNLOCK(ssk); 422219820Sjeff break; 423219820Sjeff case RDMA_CM_EVENT_TIMEWAIT_EXIT: 424219820Sjeff sdp_dbg(sk, "RDMA_CM_EVENT_TIMEWAIT_EXIT\n"); 425219820Sjeff SDP_WLOCK(ssk); 426219820Sjeff rc = sdp_disconnected_handler(sk); 427219820Sjeff SDP_WUNLOCK(ssk); 428219820Sjeff break; 429219820Sjeff case RDMA_CM_EVENT_DEVICE_REMOVAL: 430219820Sjeff sdp_dbg(sk, "RDMA_CM_EVENT_DEVICE_REMOVAL\n"); 431219820Sjeff rc = -ENETRESET; 432219820Sjeff break; 433219820Sjeff default: 434219820Sjeff printk(KERN_ERR "SDP: Unexpected CMA event: %d\n", 435219820Sjeff event->event); 436219820Sjeff rc = -ECONNABORTED; 437219820Sjeff break; 438219820Sjeff } 439219820Sjeff 440219820Sjeff sdp_dbg(sk, "event %d done. status %d\n", event->event, rc); 441219820Sjeff 442219820Sjeff if (rc) { 443219820Sjeff SDP_WLOCK(ssk); 444219820Sjeff if (ssk->id == id) { 445219820Sjeff ssk->id = NULL; 446219820Sjeff id->qp = NULL; 447219820Sjeff id->context = NULL; 448219820Sjeff if (sdp_notify(ssk, -rc)) 449219820Sjeff SDP_WUNLOCK(ssk); 450219820Sjeff } else 451219820Sjeff SDP_WUNLOCK(ssk); 452219820Sjeff } 453219820Sjeff 454219820Sjeff return rc; 455219820Sjeff} 456