{
struct sdp_sock *ssk = sdp_sk(sk);
int rc = 0;
+ int old_state = sk->sk_state;
+ struct sdp_sock *s, *t;
+ struct rdma_cm_id *id = ssk->id;
+
sdp_dbg(sk, "%s\n", __func__);
if (ssk->id)
rc = rdma_disconnect(ssk->id);
- return rc;
+
+ if (old_state != TCP_LISTEN)
+ return rc;
+
+ sdp_set_state(sk, TCP_CLOSE);
+ ssk->id = NULL;
+ release_sock(sk); /* release socket since locking semantics is parent
+ inside child */
+ rdma_destroy_id(ssk->id);
+
+ list_for_each_entry_safe(s, t, &ssk->backlog_queue, backlog_queue) {
+ sk_common_release(&s->isk.sk);
+ }
+ list_for_each_entry_safe(s, t, &ssk->accept_queue, accept_queue) {
+ sk_common_release(&s->isk.sk);
+ }
+
+ lock_sock(sk);
+
+ return 0;
}
/* Like inet_csk_wait_for_connect */