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{ 54219820Sjeff struct ib_device_attr attr; 55219820Sjeff static int max_sges = -1; 56219820Sjeff 57219820Sjeff if (max_sges > 0) 58219820Sjeff goto out; 59219820Sjeff 60219820Sjeff ib_query_device(dev, &attr); 61219820Sjeff 62219820Sjeff max_sges = attr.max_sge; 63219820Sjeff 64219820Sjeffout: 65219820Sjeff return max_sges; 66219820Sjeff} 67219820Sjeff 68219820Sjeffstatic int 69219820Sjeffsdp_init_qp(struct socket *sk, struct rdma_cm_id *id) 70219820Sjeff{ 71219820Sjeff struct ib_qp_init_attr qp_init_attr = { 72219820Sjeff .event_handler = sdp_qp_event_handler, 73219820Sjeff .cap.max_send_wr = SDP_TX_SIZE, 74219820Sjeff .cap.max_recv_wr = SDP_RX_SIZE, 75219820Sjeff .sq_sig_type = IB_SIGNAL_REQ_WR, 76219820Sjeff .qp_type = IB_QPT_RC, 77219820Sjeff }; 78219820Sjeff struct ib_device *device = id->device; 79219820Sjeff struct sdp_sock *ssk; 80219820Sjeff int rc; 81219820Sjeff 82219820Sjeff sdp_dbg(sk, "%s\n", __func__); 83219820Sjeff 84219820Sjeff ssk = sdp_sk(sk); 85219820Sjeff ssk->max_sge = sdp_get_max_dev_sge(device); 86219820Sjeff sdp_dbg(sk, "Max sges: %d\n", ssk->max_sge); 87219820Sjeff 88219820Sjeff qp_init_attr.cap.max_send_sge = MIN(ssk->max_sge, SDP_MAX_SEND_SGES); 89219820Sjeff sdp_dbg(sk, "Setting max send sge to: %d\n", 90219820Sjeff qp_init_attr.cap.max_send_sge); 91219820Sjeff 92219820Sjeff qp_init_attr.cap.max_recv_sge = MIN(ssk->max_sge, SDP_MAX_RECV_SGES); 93219820Sjeff sdp_dbg(sk, "Setting max recv sge to: %d\n", 94219820Sjeff qp_init_attr.cap.max_recv_sge); 95219820Sjeff 96219820Sjeff ssk->sdp_dev = ib_get_client_data(device, &sdp_client); 97219820Sjeff if (!ssk->sdp_dev) { 98219820Sjeff sdp_warn(sk, "SDP not available on device %s\n", device->name); 99219820Sjeff rc = -ENODEV; 100219820Sjeff goto err_rx; 101219820Sjeff } 102219820Sjeff 103219820Sjeff rc = sdp_rx_ring_create(ssk, device); 104219820Sjeff if (rc) 105219820Sjeff goto err_rx; 106219820Sjeff 107219820Sjeff rc = sdp_tx_ring_create(ssk, device); 108219820Sjeff if (rc) 109219820Sjeff goto err_tx; 110219820Sjeff 111219820Sjeff qp_init_attr.recv_cq = ssk->rx_ring.cq; 112219820Sjeff qp_init_attr.send_cq = ssk->tx_ring.cq; 113219820Sjeff 114219820Sjeff rc = rdma_create_qp(id, ssk->sdp_dev->pd, &qp_init_attr); 115219820Sjeff if (rc) { 116219820Sjeff sdp_warn(sk, "Unable to create QP: %d.\n", rc); 117219820Sjeff goto err_qp; 118219820Sjeff } 119219820Sjeff ssk->qp = id->qp; 120219820Sjeff ssk->ib_device = device; 121219820Sjeff ssk->qp_active = 1; 122219820Sjeff ssk->context.device = device; 123219820Sjeff 124219820Sjeff sdp_dbg(sk, "%s done\n", __func__); 125219820Sjeff return 0; 126219820Sjeff 127219820Sjefferr_qp: 128219820Sjeff sdp_tx_ring_destroy(ssk); 129219820Sjefferr_tx: 130219820Sjeff sdp_rx_ring_destroy(ssk); 131219820Sjefferr_rx: 132219820Sjeff return rc; 133219820Sjeff} 134219820Sjeff 135219820Sjeffstatic int 136219820Sjeffsdp_connect_handler(struct socket *sk, struct rdma_cm_id *id, 137219820Sjeff struct rdma_cm_event *event) 138219820Sjeff{ 139219820Sjeff struct sockaddr_in *src_addr; 140219820Sjeff struct sockaddr_in *dst_addr; 141219820Sjeff struct socket *child; 142219820Sjeff const struct sdp_hh *h; 143219820Sjeff struct sdp_sock *ssk; 144219820Sjeff int rc; 145219820Sjeff 146219820Sjeff sdp_dbg(sk, "%s %p -> %p\n", __func__, sdp_sk(sk)->id, id); 147219820Sjeff 148219820Sjeff h = event->param.conn.private_data; 149219820Sjeff SDP_DUMP_PACKET(sk, "RX", NULL, &h->bsdh); 150219820Sjeff 151219820Sjeff if (!h->max_adverts) 152219820Sjeff return -EINVAL; 153219820Sjeff 154219820Sjeff child = sonewconn(sk, SS_ISCONNECTED); 155219820Sjeff if (!child) 156219820Sjeff return -ENOMEM; 157219820Sjeff 158219820Sjeff ssk = sdp_sk(child); 159219820Sjeff rc = sdp_init_qp(child, id); 160219820Sjeff if (rc) 161219820Sjeff return rc; 162219820Sjeff SDP_WLOCK(ssk); 163219820Sjeff id->context = ssk; 164219820Sjeff ssk->id = id; 165219820Sjeff ssk->socket = child; 166219820Sjeff ssk->cred = crhold(child->so_cred); 167219820Sjeff dst_addr = (struct sockaddr_in *)&id->route.addr.dst_addr; 168219820Sjeff src_addr = (struct sockaddr_in *)&id->route.addr.src_addr; 169219820Sjeff ssk->fport = dst_addr->sin_port; 170219820Sjeff ssk->faddr = dst_addr->sin_addr.s_addr; 171219820Sjeff ssk->lport = src_addr->sin_port; 172219820Sjeff ssk->max_bufs = ntohs(h->bsdh.bufs); 173219820Sjeff atomic_set(&ssk->tx_ring.credits, ssk->max_bufs); 174219820Sjeff ssk->min_bufs = tx_credits(ssk) / 4; 175219820Sjeff ssk->xmit_size_goal = ntohl(h->localrcvsz) - sizeof(struct sdp_bsdh); 176219820Sjeff sdp_init_buffers(ssk, rcvbuf_initial_size); 177219820Sjeff ssk->state = TCPS_SYN_RECEIVED; 178219820Sjeff SDP_WUNLOCK(ssk); 179219820Sjeff 180219820Sjeff return 0; 181219820Sjeff} 182219820Sjeff 183219820Sjeffstatic int 184219820Sjeffsdp_response_handler(struct socket *sk, struct rdma_cm_id *id, 185219820Sjeff struct rdma_cm_event *event) 186219820Sjeff{ 187219820Sjeff const struct sdp_hah *h; 188219820Sjeff struct sockaddr_in *dst_addr; 189219820Sjeff struct sdp_sock *ssk; 190219820Sjeff sdp_dbg(sk, "%s\n", __func__); 191219820Sjeff 192219820Sjeff ssk = sdp_sk(sk); 193219820Sjeff SDP_WLOCK(ssk); 194219820Sjeff ssk->state = TCPS_ESTABLISHED; 195219820Sjeff sdp_set_default_moderation(ssk); 196219820Sjeff if (ssk->flags & SDP_DROPPED) { 197219820Sjeff SDP_WUNLOCK(ssk); 198219820Sjeff return 0; 199219820Sjeff } 200219820Sjeff if (sk->so_options & SO_KEEPALIVE) 201219820Sjeff sdp_start_keepalive_timer(sk); 202219820Sjeff h = event->param.conn.private_data; 203219820Sjeff SDP_DUMP_PACKET(sk, "RX", NULL, &h->bsdh); 204219820Sjeff ssk->max_bufs = ntohs(h->bsdh.bufs); 205219820Sjeff atomic_set(&ssk->tx_ring.credits, ssk->max_bufs); 206219820Sjeff ssk->min_bufs = tx_credits(ssk) / 4; 207219820Sjeff ssk->xmit_size_goal = 208219820Sjeff ntohl(h->actrcvsz) - sizeof(struct sdp_bsdh); 209219820Sjeff ssk->poll_cq = 1; 210219820Sjeff 211219820Sjeff dst_addr = (struct sockaddr_in *)&id->route.addr.dst_addr; 212219820Sjeff ssk->fport = dst_addr->sin_port; 213219820Sjeff ssk->faddr = dst_addr->sin_addr.s_addr; 214219820Sjeff soisconnected(sk); 215219820Sjeff SDP_WUNLOCK(ssk); 216219820Sjeff 217219820Sjeff return 0; 218219820Sjeff} 219219820Sjeff 220219820Sjeffstatic int 221219820Sjeffsdp_connected_handler(struct socket *sk, struct rdma_cm_event *event) 222219820Sjeff{ 223219820Sjeff struct sdp_sock *ssk; 224219820Sjeff 225219820Sjeff sdp_dbg(sk, "%s\n", __func__); 226219820Sjeff 227219820Sjeff ssk = sdp_sk(sk); 228219820Sjeff SDP_WLOCK(ssk); 229219820Sjeff ssk->state = TCPS_ESTABLISHED; 230219820Sjeff 231219820Sjeff sdp_set_default_moderation(ssk); 232219820Sjeff 233219820Sjeff if (sk->so_options & SO_KEEPALIVE) 234219820Sjeff sdp_start_keepalive_timer(sk); 235219820Sjeff 236219820Sjeff if ((ssk->flags & SDP_DROPPED) == 0) 237219820Sjeff soisconnected(sk); 238219820Sjeff SDP_WUNLOCK(ssk); 239219820Sjeff return 0; 240219820Sjeff} 241219820Sjeff 242219820Sjeffstatic int 243219820Sjeffsdp_disconnected_handler(struct socket *sk) 244219820Sjeff{ 245219820Sjeff struct sdp_sock *ssk; 246219820Sjeff 247219820Sjeff ssk = sdp_sk(sk); 248219820Sjeff sdp_dbg(sk, "%s\n", __func__); 249219820Sjeff 250219820Sjeff SDP_WLOCK_ASSERT(ssk); 251219820Sjeff if (sdp_sk(sk)->state == TCPS_SYN_RECEIVED) { 252219820Sjeff sdp_connected_handler(sk, NULL); 253219820Sjeff 254219820Sjeff if (rcv_nxt(ssk)) 255219820Sjeff return 0; 256219820Sjeff } 257219820Sjeff 258219820Sjeff return -ECONNRESET; 259219820Sjeff} 260219820Sjeff 261219820Sjeffint 262219820Sjeffsdp_cma_handler(struct rdma_cm_id *id, struct rdma_cm_event *event) 263219820Sjeff{ 264219820Sjeff struct rdma_conn_param conn_param; 265219820Sjeff struct socket *sk; 266219820Sjeff struct sdp_sock *ssk; 267219820Sjeff struct sdp_hah hah; 268219820Sjeff struct sdp_hh hh; 269219820Sjeff 270219820Sjeff int rc = 0; 271219820Sjeff 272219820Sjeff ssk = id->context; 273219820Sjeff sk = NULL; 274219820Sjeff if (ssk) 275219820Sjeff sk = ssk->socket; 276219820Sjeff if (!ssk || !sk || !ssk->id) { 277219820Sjeff sdp_dbg(sk, 278219820Sjeff "cm_id is being torn down, event %d, ssk %p, sk %p, id %p\n", 279219820Sjeff event->event, ssk, sk, id); 280219820Sjeff return event->event == RDMA_CM_EVENT_CONNECT_REQUEST ? 281219820Sjeff -EINVAL : 0; 282219820Sjeff } 283219820Sjeff 284219820Sjeff sdp_dbg(sk, "%s event %d id %p\n", __func__, event->event, id); 285219820Sjeff switch (event->event) { 286219820Sjeff case RDMA_CM_EVENT_ADDR_RESOLVED: 287219820Sjeff sdp_dbg(sk, "RDMA_CM_EVENT_ADDR_RESOLVED\n"); 288219820Sjeff 289219820Sjeff if (sdp_link_layer_ib_only && 290219820Sjeff rdma_node_get_transport(id->device->node_type) == 291219820Sjeff RDMA_TRANSPORT_IB && 292219820Sjeff rdma_port_get_link_layer(id->device, id->port_num) != 293219820Sjeff IB_LINK_LAYER_INFINIBAND) { 294219820Sjeff sdp_dbg(sk, "Link layer is: %d. Only IB link layer " 295219820Sjeff "is allowed\n", 296219820Sjeff rdma_port_get_link_layer(id->device, id->port_num)); 297219820Sjeff rc = -ENETUNREACH; 298219820Sjeff break; 299219820Sjeff } 300219820Sjeff 301219820Sjeff rc = rdma_resolve_route(id, SDP_ROUTE_TIMEOUT); 302219820Sjeff break; 303219820Sjeff case RDMA_CM_EVENT_ADDR_ERROR: 304219820Sjeff sdp_dbg(sk, "RDMA_CM_EVENT_ADDR_ERROR\n"); 305219820Sjeff rc = -ENETUNREACH; 306219820Sjeff break; 307219820Sjeff case RDMA_CM_EVENT_ROUTE_RESOLVED: 308219820Sjeff sdp_dbg(sk, "RDMA_CM_EVENT_ROUTE_RESOLVED : %p\n", id); 309219820Sjeff rc = sdp_init_qp(sk, id); 310219820Sjeff if (rc) 311219820Sjeff break; 312219820Sjeff atomic_set(&sdp_sk(sk)->remote_credits, 313219820Sjeff rx_ring_posted(sdp_sk(sk))); 314219820Sjeff memset(&hh, 0, sizeof hh); 315219820Sjeff hh.bsdh.mid = SDP_MID_HELLO; 316219820Sjeff hh.bsdh.len = htonl(sizeof(struct sdp_hh)); 317219820Sjeff hh.max_adverts = 1; 318219820Sjeff hh.ipv_cap = 0x40; 319219820Sjeff hh.majv_minv = SDP_MAJV_MINV; 320219820Sjeff sdp_init_buffers(sdp_sk(sk), rcvbuf_initial_size); 321219820Sjeff hh.bsdh.bufs = htons(rx_ring_posted(sdp_sk(sk))); 322219820Sjeff hh.localrcvsz = hh.desremrcvsz = htonl(sdp_sk(sk)->recv_bytes); 323219820Sjeff hh.max_adverts = 0x1; 324219820Sjeff sdp_sk(sk)->laddr = 325219820Sjeff ((struct sockaddr_in *)&id->route.addr.src_addr)->sin_addr.s_addr; 326219820Sjeff memset(&conn_param, 0, sizeof conn_param); 327219820Sjeff conn_param.private_data_len = sizeof hh; 328219820Sjeff conn_param.private_data = &hh; 329219820Sjeff conn_param.responder_resources = 4 /* TODO */; 330219820Sjeff conn_param.initiator_depth = 4 /* TODO */; 331219820Sjeff conn_param.retry_count = SDP_RETRY_COUNT; 332219820Sjeff SDP_DUMP_PACKET(NULL, "TX", NULL, &hh.bsdh); 333219820Sjeff rc = rdma_connect(id, &conn_param); 334219820Sjeff break; 335219820Sjeff case RDMA_CM_EVENT_ROUTE_ERROR: 336219820Sjeff sdp_dbg(sk, "RDMA_CM_EVENT_ROUTE_ERROR : %p\n", id); 337219820Sjeff rc = -ETIMEDOUT; 338219820Sjeff break; 339219820Sjeff case RDMA_CM_EVENT_CONNECT_REQUEST: 340219820Sjeff sdp_dbg(sk, "RDMA_CM_EVENT_CONNECT_REQUEST\n"); 341219820Sjeff rc = sdp_connect_handler(sk, id, event); 342219820Sjeff if (rc) { 343219820Sjeff sdp_dbg(sk, "Destroying qp\n"); 344219820Sjeff rdma_reject(id, NULL, 0); 345219820Sjeff break; 346219820Sjeff } 347219820Sjeff ssk = id->context; 348219820Sjeff atomic_set(&ssk->remote_credits, rx_ring_posted(ssk)); 349219820Sjeff memset(&hah, 0, sizeof hah); 350219820Sjeff hah.bsdh.mid = SDP_MID_HELLO_ACK; 351219820Sjeff hah.bsdh.bufs = htons(rx_ring_posted(ssk)); 352219820Sjeff hah.bsdh.len = htonl(sizeof(struct sdp_hah)); 353219820Sjeff hah.majv_minv = SDP_MAJV_MINV; 354219820Sjeff hah.ext_max_adverts = 1; /* Doesn't seem to be mandated by spec, 355219820Sjeff but just in case */ 356219820Sjeff hah.actrcvsz = htonl(ssk->recv_bytes); 357219820Sjeff memset(&conn_param, 0, sizeof conn_param); 358219820Sjeff conn_param.private_data_len = sizeof hah; 359219820Sjeff conn_param.private_data = &hah; 360219820Sjeff conn_param.responder_resources = 4 /* TODO */; 361219820Sjeff conn_param.initiator_depth = 4 /* TODO */; 362219820Sjeff conn_param.retry_count = SDP_RETRY_COUNT; 363219820Sjeff SDP_DUMP_PACKET(sk, "TX", NULL, &hah.bsdh); 364219820Sjeff rc = rdma_accept(id, &conn_param); 365219820Sjeff if (rc) { 366219820Sjeff ssk->id = NULL; 367219820Sjeff id->qp = NULL; 368219820Sjeff id->context = NULL; 369219820Sjeff } 370219820Sjeff break; 371219820Sjeff case RDMA_CM_EVENT_CONNECT_RESPONSE: 372219820Sjeff sdp_dbg(sk, "RDMA_CM_EVENT_CONNECT_RESPONSE\n"); 373219820Sjeff rc = sdp_response_handler(sk, id, event); 374219820Sjeff if (rc) { 375219820Sjeff sdp_dbg(sk, "Destroying qp\n"); 376219820Sjeff rdma_reject(id, NULL, 0); 377219820Sjeff } else 378219820Sjeff rc = rdma_accept(id, NULL); 379219820Sjeff break; 380219820Sjeff case RDMA_CM_EVENT_CONNECT_ERROR: 381219820Sjeff sdp_dbg(sk, "RDMA_CM_EVENT_CONNECT_ERROR\n"); 382219820Sjeff rc = -ETIMEDOUT; 383219820Sjeff break; 384219820Sjeff case RDMA_CM_EVENT_UNREACHABLE: 385219820Sjeff sdp_dbg(sk, "RDMA_CM_EVENT_UNREACHABLE\n"); 386219820Sjeff rc = -ENETUNREACH; 387219820Sjeff break; 388219820Sjeff case RDMA_CM_EVENT_REJECTED: 389219820Sjeff sdp_dbg(sk, "RDMA_CM_EVENT_REJECTED\n"); 390219820Sjeff rc = -ECONNREFUSED; 391219820Sjeff break; 392219820Sjeff case RDMA_CM_EVENT_ESTABLISHED: 393219820Sjeff sdp_dbg(sk, "RDMA_CM_EVENT_ESTABLISHED\n"); 394219820Sjeff sdp_sk(sk)->laddr = 395219820Sjeff ((struct sockaddr_in *)&id->route.addr.src_addr)->sin_addr.s_addr; 396219820Sjeff rc = sdp_connected_handler(sk, event); 397219820Sjeff break; 398219820Sjeff case RDMA_CM_EVENT_DISCONNECTED: /* This means DREQ/DREP received */ 399219820Sjeff sdp_dbg(sk, "RDMA_CM_EVENT_DISCONNECTED\n"); 400219820Sjeff 401219820Sjeff SDP_WLOCK(ssk); 402219820Sjeff if (ssk->state == TCPS_LAST_ACK) { 403219820Sjeff sdp_cancel_dreq_wait_timeout(ssk); 404219820Sjeff 405219820Sjeff sdp_dbg(sk, "%s: waiting for Infiniband tear down\n", 406219820Sjeff __func__); 407219820Sjeff } 408219820Sjeff ssk->qp_active = 0; 409219820Sjeff SDP_WUNLOCK(ssk); 410219820Sjeff rdma_disconnect(id); 411219820Sjeff SDP_WLOCK(ssk); 412219820Sjeff if (ssk->state != TCPS_TIME_WAIT) { 413219820Sjeff if (ssk->state == TCPS_CLOSE_WAIT) { 414219820Sjeff sdp_dbg(sk, "IB teardown while in " 415219820Sjeff "TCPS_CLOSE_WAIT taking reference to " 416219820Sjeff "let close() finish the work\n"); 417219820Sjeff } 418219820Sjeff rc = sdp_disconnected_handler(sk); 419219820Sjeff if (rc) 420219820Sjeff rc = -EPIPE; 421219820Sjeff } 422219820Sjeff SDP_WUNLOCK(ssk); 423219820Sjeff break; 424219820Sjeff case RDMA_CM_EVENT_TIMEWAIT_EXIT: 425219820Sjeff sdp_dbg(sk, "RDMA_CM_EVENT_TIMEWAIT_EXIT\n"); 426219820Sjeff SDP_WLOCK(ssk); 427219820Sjeff rc = sdp_disconnected_handler(sk); 428219820Sjeff SDP_WUNLOCK(ssk); 429219820Sjeff break; 430219820Sjeff case RDMA_CM_EVENT_DEVICE_REMOVAL: 431219820Sjeff sdp_dbg(sk, "RDMA_CM_EVENT_DEVICE_REMOVAL\n"); 432219820Sjeff rc = -ENETRESET; 433219820Sjeff break; 434219820Sjeff default: 435219820Sjeff printk(KERN_ERR "SDP: Unexpected CMA event: %d\n", 436219820Sjeff event->event); 437219820Sjeff rc = -ECONNABORTED; 438219820Sjeff break; 439219820Sjeff } 440219820Sjeff 441219820Sjeff sdp_dbg(sk, "event %d done. status %d\n", event->event, rc); 442219820Sjeff 443219820Sjeff if (rc) { 444219820Sjeff SDP_WLOCK(ssk); 445219820Sjeff if (ssk->id == id) { 446219820Sjeff ssk->id = NULL; 447219820Sjeff id->qp = NULL; 448219820Sjeff id->context = NULL; 449219820Sjeff if (sdp_notify(ssk, -rc)) 450219820Sjeff SDP_WUNLOCK(ssk); 451219820Sjeff } else 452219820Sjeff SDP_WUNLOCK(ssk); 453219820Sjeff } 454219820Sjeff 455219820Sjeff return rc; 456219820Sjeff} 457