aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/sw/siw/siw_cm.h
blob: 8c59cb3e28683db357b114c30312af0e7f4e8980 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */

/* Authors: Bernard Metzler <bmt@zurich.ibm.com> */
/*          Greg Joyce <greg@opengridcomputing.com> */
/* Copyright (c) 2008-2019, IBM Corporation */
/* Copyright (c) 2017, Open Grid Computing, Inc. */

#ifndef _SIW_CM_H
#define _SIW_CM_H

#include <net/sock.h>
#include <linux/tcp.h>

#include <rdma/iw_cm.h>

enum siw_cep_state {
	SIW_EPSTATE_IDLE = 1,
	SIW_EPSTATE_LISTENING,
	SIW_EPSTATE_CONNECTING,
	SIW_EPSTATE_AWAIT_MPAREQ,
	SIW_EPSTATE_RECVD_MPAREQ,
	SIW_EPSTATE_AWAIT_MPAREP,
	SIW_EPSTATE_RDMA_MODE,
	SIW_EPSTATE_CLOSED
};

struct siw_mpa_info {
	struct mpa_rr hdr; /* peer mpa hdr in host byte order */
	struct mpa_v2_data v2_ctrl;
	struct mpa_v2_data v2_ctrl_req;
	char *pdata;
	int bytes_rcvd;
};

struct siw_device;

struct siw_cep {
	struct iw_cm_id *cm_id;
	struct siw_device *sdev;
	struct list_head devq;
	spinlock_t lock;
	struct kref ref;
	int in_use;
	wait_queue_head_t waitq;
	enum siw_cep_state state;

	struct list_head listenq;
	struct siw_cep *listen_cep;

	struct siw_qp *qp;
	struct socket *sock;

	struct siw_cm_work *mpa_timer;
	struct list_head work_freelist;

	struct siw_mpa_info mpa;
	int ord;
	int ird;
	bool enhanced_rdma_conn_est;

	/* Saved upcalls of socket */
	void (*sk_state_change)(struct sock *sk);
	void (*sk_data_ready)(struct sock *sk);
	void (*sk_write_space)(struct sock *sk);
	void (*sk_error_report)(struct sock *sk);
};

/*
 * Connection initiator waits 10 seconds to receive an
 * MPA reply after sending out MPA request. Reponder waits for
 * 5 seconds for MPA request to arrive if new TCP connection
 * was set up.
 */
#define MPAREQ_TIMEOUT (HZ * 10)
#define MPAREP_TIMEOUT (HZ * 5)

enum siw_work_type {
	SIW_CM_WORK_ACCEPT = 1,
	SIW_CM_WORK_READ_MPAHDR,
	SIW_CM_WORK_CLOSE_LLP, /* close socket */
	SIW_CM_WORK_PEER_CLOSE, /* socket indicated peer close */
	SIW_CM_WORK_MPATIMEOUT
};

struct siw_cm_work {
	struct delayed_work work;
	struct list_head list;
	enum siw_work_type type;
	struct siw_cep *cep;
};

#define to_sockaddr_in(a) (*(struct sockaddr_in *)(&(a)))
#define to_sockaddr_in6(a) (*(struct sockaddr_in6 *)(&(a)))

static inline int getname_peer(struct socket *s, struct sockaddr_storage *a)
{
	return s->ops->getname(s, (struct sockaddr *)a, 1);
}

static inline int getname_local(struct socket *s, struct sockaddr_storage *a)
{
	return s->ops->getname(s, (struct sockaddr *)a, 0);
}

static inline int ksock_recv(struct socket *sock, char *buf, size_t size,
			     int flags)
{
	struct kvec iov = { buf, size };
	struct msghdr msg = { .msg_name = NULL, .msg_flags = flags };

	return kernel_recvmsg(sock, &msg, &iov, 1, size, flags);
}

int siw_connect(struct iw_cm_id *id, struct iw_cm_conn_param *parm);
int siw_accept(struct iw_cm_id *id, struct iw_cm_conn_param *param);
int siw_reject(struct iw_cm_id *id, const void *data, u8 len);
int siw_create_listen(struct iw_cm_id *id, int backlog);
int siw_destroy_listen(struct iw_cm_id *id);

void siw_cep_get(struct siw_cep *cep);
void siw_cep_put(struct siw_cep *cep);
int siw_cm_queue_work(struct siw_cep *cep, enum siw_work_type type);

int siw_cm_init(void);
void siw_cm_exit(void);

/*
 * TCP socket interface
 */
#define sk_to_qp(sk) (((struct siw_cep *)((sk)->sk_user_data))->qp)
#define sk_to_cep(sk) ((struct siw_cep *)((sk)->sk_user_data))

#endif