1 // SPDX-License-Identifier: GPL-2.0-only
3 * Intel MIC Platform Software Stack (MPSS)
5 * Copyright(c) 2014 Intel Corporation.
12 void scif_cleanup_ep_qp(struct scif_endpt
*ep
)
14 struct scif_qp
*qp
= ep
->qp_info
.qp
;
16 if (qp
->outbound_q
.rb_base
) {
17 scif_iounmap((void *)qp
->outbound_q
.rb_base
,
18 qp
->outbound_q
.size
, ep
->remote_dev
);
19 qp
->outbound_q
.rb_base
= NULL
;
22 scif_iounmap((void *)qp
->remote_qp
,
23 sizeof(struct scif_qp
), ep
->remote_dev
);
27 scif_unmap_single(qp
->local_qp
, ep
->remote_dev
,
28 sizeof(struct scif_qp
));
32 scif_unmap_single(qp
->local_buf
, ep
->remote_dev
,
38 void scif_teardown_ep(void *endpt
)
40 struct scif_endpt
*ep
= endpt
;
41 struct scif_qp
*qp
= ep
->qp_info
.qp
;
45 scif_cleanup_ep_qp(ep
);
46 spin_unlock(&ep
->lock
);
47 kfree(qp
->inbound_q
.rb_base
);
53 * Enqueue the endpoint to the zombie list for cleanup.
54 * The endpoint should not be accessed once this API returns.
56 void scif_add_epd_to_zombie_list(struct scif_endpt
*ep
, bool eplock_held
)
59 mutex_lock(&scif_info
.eplock
);
61 ep
->state
= SCIFEP_ZOMBIE
;
62 spin_unlock(&ep
->lock
);
63 list_add_tail(&ep
->list
, &scif_info
.zombie
);
64 scif_info
.nr_zombies
++;
66 mutex_unlock(&scif_info
.eplock
);
67 schedule_work(&scif_info
.misc_work
);
70 static struct scif_endpt
*scif_find_listen_ep(u16 port
)
72 struct scif_endpt
*ep
= NULL
;
73 struct list_head
*pos
, *tmpq
;
75 mutex_lock(&scif_info
.eplock
);
76 list_for_each_safe(pos
, tmpq
, &scif_info
.listen
) {
77 ep
= list_entry(pos
, struct scif_endpt
, list
);
78 if (ep
->port
.port
== port
) {
79 mutex_unlock(&scif_info
.eplock
);
83 mutex_unlock(&scif_info
.eplock
);
87 void scif_cleanup_zombie_epd(void)
89 struct list_head
*pos
, *tmpq
;
90 struct scif_endpt
*ep
;
92 mutex_lock(&scif_info
.eplock
);
93 list_for_each_safe(pos
, tmpq
, &scif_info
.zombie
) {
94 ep
= list_entry(pos
, struct scif_endpt
, list
);
95 if (scif_rma_ep_can_uninit(ep
)) {
97 scif_info
.nr_zombies
--;
98 put_iova_domain(&ep
->rma_info
.iovad
);
102 mutex_unlock(&scif_info
.eplock
);
106 * scif_cnctreq() - Respond to SCIF_CNCT_REQ interrupt message
107 * @msg: Interrupt message
109 * This message is initiated by the remote node to request a connection
110 * to the local node. This function looks for an end point in the
111 * listen state on the requested port id.
113 * If it finds a listening port it places the connect request on the
114 * listening end points queue and wakes up any pending accept calls.
116 * If it does not find a listening end point it sends a connection
117 * reject message to the remote node.
119 void scif_cnctreq(struct scif_dev
*scifdev
, struct scifmsg
*msg
)
121 struct scif_endpt
*ep
= NULL
;
122 struct scif_conreq
*conreq
;
124 conreq
= kmalloc(sizeof(*conreq
), GFP_KERNEL
);
126 /* Lack of resources so reject the request. */
129 ep
= scif_find_listen_ep(msg
->dst
.port
);
131 /* Send reject due to no listening ports */
132 goto conreq_sendrej_free
;
134 spin_lock(&ep
->lock
);
136 if (ep
->backlog
<= ep
->conreqcnt
) {
137 /* Send reject due to too many pending requests */
138 spin_unlock(&ep
->lock
);
139 goto conreq_sendrej_free
;
143 list_add_tail(&conreq
->list
, &ep
->conlist
);
145 wake_up_interruptible(&ep
->conwq
);
146 spin_unlock(&ep
->lock
);
152 msg
->uop
= SCIF_CNCT_REJ
;
153 scif_nodeqp_send(&scif_dev
[msg
->src
.node
], msg
);
157 * scif_cnctgnt() - Respond to SCIF_CNCT_GNT interrupt message
158 * @msg: Interrupt message
160 * An accept() on the remote node has occurred and sent this message
161 * to indicate success. Place the end point in the MAPPING state and
162 * save the remote nodes memory information. Then wake up the connect
163 * request so it can finish.
165 void scif_cnctgnt(struct scif_dev
*scifdev
, struct scifmsg
*msg
)
167 struct scif_endpt
*ep
= (struct scif_endpt
*)msg
->payload
[0];
169 spin_lock(&ep
->lock
);
170 if (SCIFEP_CONNECTING
== ep
->state
) {
171 ep
->peer
.node
= msg
->src
.node
;
172 ep
->peer
.port
= msg
->src
.port
;
173 ep
->qp_info
.gnt_pld
= msg
->payload
[1];
174 ep
->remote_ep
= msg
->payload
[2];
175 ep
->state
= SCIFEP_MAPPING
;
179 spin_unlock(&ep
->lock
);
183 * scif_cnctgnt_ack() - Respond to SCIF_CNCT_GNTACK interrupt message
184 * @msg: Interrupt message
186 * The remote connection request has finished mapping the local memory.
187 * Place the connection in the connected state and wake up the pending
190 void scif_cnctgnt_ack(struct scif_dev
*scifdev
, struct scifmsg
*msg
)
192 struct scif_endpt
*ep
= (struct scif_endpt
*)msg
->payload
[0];
194 mutex_lock(&scif_info
.connlock
);
195 spin_lock(&ep
->lock
);
196 /* New ep is now connected with all resources set. */
197 ep
->state
= SCIFEP_CONNECTED
;
198 list_add_tail(&ep
->list
, &scif_info
.connected
);
200 spin_unlock(&ep
->lock
);
201 mutex_unlock(&scif_info
.connlock
);
205 * scif_cnctgnt_nack() - Respond to SCIF_CNCT_GNTNACK interrupt message
206 * @msg: Interrupt message
208 * The remote connection request failed to map the local memory it was sent.
209 * Place the end point in the CLOSING state to indicate it and wake up
210 * the pending accept();
212 void scif_cnctgnt_nack(struct scif_dev
*scifdev
, struct scifmsg
*msg
)
214 struct scif_endpt
*ep
= (struct scif_endpt
*)msg
->payload
[0];
216 spin_lock(&ep
->lock
);
217 ep
->state
= SCIFEP_CLOSING
;
219 spin_unlock(&ep
->lock
);
223 * scif_cnctrej() - Respond to SCIF_CNCT_REJ interrupt message
224 * @msg: Interrupt message
226 * The remote end has rejected the connection request. Set the end
227 * point back to the bound state and wake up the pending connect().
229 void scif_cnctrej(struct scif_dev
*scifdev
, struct scifmsg
*msg
)
231 struct scif_endpt
*ep
= (struct scif_endpt
*)msg
->payload
[0];
233 spin_lock(&ep
->lock
);
234 if (SCIFEP_CONNECTING
== ep
->state
) {
235 ep
->state
= SCIFEP_BOUND
;
238 spin_unlock(&ep
->lock
);
242 * scif_discnct() - Respond to SCIF_DISCNCT interrupt message
243 * @msg: Interrupt message
245 * The remote node has indicated close() has been called on its end
246 * point. Remove the local end point from the connected list, set its
247 * state to disconnected and ensure accesses to the remote node are
250 * When all accesses to the remote end have completed then send a
251 * DISCNT_ACK to indicate it can remove its resources and complete
254 void scif_discnct(struct scif_dev
*scifdev
, struct scifmsg
*msg
)
256 struct scif_endpt
*ep
= NULL
;
257 struct scif_endpt
*tmpep
;
258 struct list_head
*pos
, *tmpq
;
260 mutex_lock(&scif_info
.connlock
);
261 list_for_each_safe(pos
, tmpq
, &scif_info
.connected
) {
262 tmpep
= list_entry(pos
, struct scif_endpt
, list
);
264 * The local ep may have sent a disconnect and and been closed
265 * due to a message response time out. It may have been
266 * allocated again and formed a new connection so we want to
267 * check if the remote ep matches
269 if (((u64
)tmpep
== msg
->payload
[1]) &&
270 ((u64
)tmpep
->remote_ep
== msg
->payload
[0])) {
273 spin_lock(&ep
->lock
);
279 * If the terminated end is not found then this side started closing
280 * before the other side sent the disconnect. If so the ep will no
281 * longer be on the connected list. Regardless the other side
282 * needs to be acked to let it know close is complete.
285 mutex_unlock(&scif_info
.connlock
);
289 ep
->state
= SCIFEP_DISCONNECTED
;
290 list_add_tail(&ep
->list
, &scif_info
.disconnected
);
292 wake_up_interruptible(&ep
->sendwq
);
293 wake_up_interruptible(&ep
->recvwq
);
294 spin_unlock(&ep
->lock
);
295 mutex_unlock(&scif_info
.connlock
);
298 msg
->uop
= SCIF_DISCNT_ACK
;
299 scif_nodeqp_send(&scif_dev
[msg
->src
.node
], msg
);
303 * scif_discnct_ack() - Respond to SCIF_DISCNT_ACK interrupt message
304 * @msg: Interrupt message
306 * Remote side has indicated it has not more references to local resources
308 void scif_discnt_ack(struct scif_dev
*scifdev
, struct scifmsg
*msg
)
310 struct scif_endpt
*ep
= (struct scif_endpt
*)msg
->payload
[0];
312 spin_lock(&ep
->lock
);
313 ep
->state
= SCIFEP_DISCONNECTED
;
314 spin_unlock(&ep
->lock
);
315 complete(&ep
->discon
);
319 * scif_clientsend() - Respond to SCIF_CLIENT_SEND interrupt message
320 * @msg: Interrupt message
322 * Remote side is confirming send or receive interrupt handling is complete.
324 void scif_clientsend(struct scif_dev
*scifdev
, struct scifmsg
*msg
)
326 struct scif_endpt
*ep
= (struct scif_endpt
*)msg
->payload
[0];
328 spin_lock(&ep
->lock
);
329 if (SCIFEP_CONNECTED
== ep
->state
)
330 wake_up_interruptible(&ep
->recvwq
);
331 spin_unlock(&ep
->lock
);
335 * scif_clientrcvd() - Respond to SCIF_CLIENT_RCVD interrupt message
336 * @msg: Interrupt message
338 * Remote side is confirming send or receive interrupt handling is complete.
340 void scif_clientrcvd(struct scif_dev
*scifdev
, struct scifmsg
*msg
)
342 struct scif_endpt
*ep
= (struct scif_endpt
*)msg
->payload
[0];
344 spin_lock(&ep
->lock
);
345 if (SCIFEP_CONNECTED
== ep
->state
)
346 wake_up_interruptible(&ep
->sendwq
);
347 spin_unlock(&ep
->lock
);