diff options
Diffstat (limited to 'net/smc/smc_tx.c')
-rw-r--r-- | net/smc/smc_tx.c | 193 |
1 files changed, 150 insertions, 43 deletions
diff --git a/net/smc/smc_tx.c b/net/smc/smc_tx.c index f82886b7d1d8..142bcb134dd6 100644 --- a/net/smc/smc_tx.c +++ b/net/smc/smc_tx.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "smc.h" | 24 | #include "smc.h" |
25 | #include "smc_wr.h" | 25 | #include "smc_wr.h" |
26 | #include "smc_cdc.h" | 26 | #include "smc_cdc.h" |
27 | #include "smc_ism.h" | ||
27 | #include "smc_tx.h" | 28 | #include "smc_tx.h" |
28 | 29 | ||
29 | #define SMC_TX_WORK_DELAY HZ | 30 | #define SMC_TX_WORK_DELAY HZ |
@@ -250,6 +251,24 @@ out_err: | |||
250 | 251 | ||
251 | /***************************** sndbuf consumer *******************************/ | 252 | /***************************** sndbuf consumer *******************************/ |
252 | 253 | ||
254 | /* sndbuf consumer: actual data transfer of one target chunk with ISM write */ | ||
255 | int smcd_tx_ism_write(struct smc_connection *conn, void *data, size_t len, | ||
256 | u32 offset, int signal) | ||
257 | { | ||
258 | struct smc_ism_position pos; | ||
259 | int rc; | ||
260 | |||
261 | memset(&pos, 0, sizeof(pos)); | ||
262 | pos.token = conn->peer_token; | ||
263 | pos.index = conn->peer_rmbe_idx; | ||
264 | pos.offset = conn->tx_off + offset; | ||
265 | pos.signal = signal; | ||
266 | rc = smc_ism_write(conn->lgr->smcd, &pos, data, len); | ||
267 | if (rc) | ||
268 | conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1; | ||
269 | return rc; | ||
270 | } | ||
271 | |||
253 | /* sndbuf consumer: actual data transfer of one target chunk with RDMA write */ | 272 | /* sndbuf consumer: actual data transfer of one target chunk with RDMA write */ |
254 | static int smc_tx_rdma_write(struct smc_connection *conn, int peer_rmbe_offset, | 273 | static int smc_tx_rdma_write(struct smc_connection *conn, int peer_rmbe_offset, |
255 | int num_sges, struct ib_sge sges[]) | 274 | int num_sges, struct ib_sge sges[]) |
@@ -297,21 +316,104 @@ static inline void smc_tx_advance_cursors(struct smc_connection *conn, | |||
297 | smc_curs_add(conn->sndbuf_desc->len, sent, len); | 316 | smc_curs_add(conn->sndbuf_desc->len, sent, len); |
298 | } | 317 | } |
299 | 318 | ||
319 | /* SMC-R helper for smc_tx_rdma_writes() */ | ||
320 | static int smcr_tx_rdma_writes(struct smc_connection *conn, size_t len, | ||
321 | size_t src_off, size_t src_len, | ||
322 | size_t dst_off, size_t dst_len) | ||
323 | { | ||
324 | dma_addr_t dma_addr = | ||
325 | sg_dma_address(conn->sndbuf_desc->sgt[SMC_SINGLE_LINK].sgl); | ||
326 | struct smc_link *link = &conn->lgr->lnk[SMC_SINGLE_LINK]; | ||
327 | int src_len_sum = src_len, dst_len_sum = dst_len; | ||
328 | struct ib_sge sges[SMC_IB_MAX_SEND_SGE]; | ||
329 | int sent_count = src_off; | ||
330 | int srcchunk, dstchunk; | ||
331 | int num_sges; | ||
332 | int rc; | ||
333 | |||
334 | for (dstchunk = 0; dstchunk < 2; dstchunk++) { | ||
335 | num_sges = 0; | ||
336 | for (srcchunk = 0; srcchunk < 2; srcchunk++) { | ||
337 | sges[srcchunk].addr = dma_addr + src_off; | ||
338 | sges[srcchunk].length = src_len; | ||
339 | sges[srcchunk].lkey = link->roce_pd->local_dma_lkey; | ||
340 | num_sges++; | ||
341 | |||
342 | src_off += src_len; | ||
343 | if (src_off >= conn->sndbuf_desc->len) | ||
344 | src_off -= conn->sndbuf_desc->len; | ||
345 | /* modulo in send ring */ | ||
346 | if (src_len_sum == dst_len) | ||
347 | break; /* either on 1st or 2nd iteration */ | ||
348 | /* prepare next (== 2nd) iteration */ | ||
349 | src_len = dst_len - src_len; /* remainder */ | ||
350 | src_len_sum += src_len; | ||
351 | } | ||
352 | rc = smc_tx_rdma_write(conn, dst_off, num_sges, sges); | ||
353 | if (rc) | ||
354 | return rc; | ||
355 | if (dst_len_sum == len) | ||
356 | break; /* either on 1st or 2nd iteration */ | ||
357 | /* prepare next (== 2nd) iteration */ | ||
358 | dst_off = 0; /* modulo offset in RMBE ring buffer */ | ||
359 | dst_len = len - dst_len; /* remainder */ | ||
360 | dst_len_sum += dst_len; | ||
361 | src_len = min_t(int, dst_len, conn->sndbuf_desc->len - | ||
362 | sent_count); | ||
363 | src_len_sum = src_len; | ||
364 | } | ||
365 | return 0; | ||
366 | } | ||
367 | |||
368 | /* SMC-D helper for smc_tx_rdma_writes() */ | ||
369 | static int smcd_tx_rdma_writes(struct smc_connection *conn, size_t len, | ||
370 | size_t src_off, size_t src_len, | ||
371 | size_t dst_off, size_t dst_len) | ||
372 | { | ||
373 | int src_len_sum = src_len, dst_len_sum = dst_len; | ||
374 | int srcchunk, dstchunk; | ||
375 | int rc; | ||
376 | |||
377 | for (dstchunk = 0; dstchunk < 2; dstchunk++) { | ||
378 | for (srcchunk = 0; srcchunk < 2; srcchunk++) { | ||
379 | void *data = conn->sndbuf_desc->cpu_addr + src_off; | ||
380 | |||
381 | rc = smcd_tx_ism_write(conn, data, src_len, dst_off + | ||
382 | sizeof(struct smcd_cdc_msg), 0); | ||
383 | if (rc) | ||
384 | return rc; | ||
385 | dst_off += src_len; | ||
386 | src_off += src_len; | ||
387 | if (src_off >= conn->sndbuf_desc->len) | ||
388 | src_off -= conn->sndbuf_desc->len; | ||
389 | /* modulo in send ring */ | ||
390 | if (src_len_sum == dst_len) | ||
391 | break; /* either on 1st or 2nd iteration */ | ||
392 | /* prepare next (== 2nd) iteration */ | ||
393 | src_len = dst_len - src_len; /* remainder */ | ||
394 | src_len_sum += src_len; | ||
395 | } | ||
396 | if (dst_len_sum == len) | ||
397 | break; /* either on 1st or 2nd iteration */ | ||
398 | /* prepare next (== 2nd) iteration */ | ||
399 | dst_off = 0; /* modulo offset in RMBE ring buffer */ | ||
400 | dst_len = len - dst_len; /* remainder */ | ||
401 | dst_len_sum += dst_len; | ||
402 | src_len = min_t(int, dst_len, conn->sndbuf_desc->len - src_off); | ||
403 | src_len_sum = src_len; | ||
404 | } | ||
405 | return 0; | ||
406 | } | ||
407 | |||
300 | /* sndbuf consumer: prepare all necessary (src&dst) chunks of data transmit; | 408 | /* sndbuf consumer: prepare all necessary (src&dst) chunks of data transmit; |
301 | * usable snd_wnd as max transmit | 409 | * usable snd_wnd as max transmit |
302 | */ | 410 | */ |
303 | static int smc_tx_rdma_writes(struct smc_connection *conn) | 411 | static int smc_tx_rdma_writes(struct smc_connection *conn) |
304 | { | 412 | { |
305 | size_t src_off, src_len, dst_off, dst_len; /* current chunk values */ | 413 | size_t len, src_len, dst_off, dst_len; /* current chunk values */ |
306 | size_t len, dst_len_sum, src_len_sum, dstchunk, srcchunk; | ||
307 | union smc_host_cursor sent, prep, prod, cons; | 414 | union smc_host_cursor sent, prep, prod, cons; |
308 | struct ib_sge sges[SMC_IB_MAX_SEND_SGE]; | ||
309 | struct smc_link_group *lgr = conn->lgr; | ||
310 | struct smc_cdc_producer_flags *pflags; | 415 | struct smc_cdc_producer_flags *pflags; |
311 | int to_send, rmbespace; | 416 | int to_send, rmbespace; |
312 | struct smc_link *link; | ||
313 | dma_addr_t dma_addr; | ||
314 | int num_sges; | ||
315 | int rc; | 417 | int rc; |
316 | 418 | ||
317 | /* source: sndbuf */ | 419 | /* source: sndbuf */ |
@@ -341,7 +443,6 @@ static int smc_tx_rdma_writes(struct smc_connection *conn) | |||
341 | len = min(to_send, rmbespace); | 443 | len = min(to_send, rmbespace); |
342 | 444 | ||
343 | /* initialize variables for first iteration of subsequent nested loop */ | 445 | /* initialize variables for first iteration of subsequent nested loop */ |
344 | link = &lgr->lnk[SMC_SINGLE_LINK]; | ||
345 | dst_off = prod.count; | 446 | dst_off = prod.count; |
346 | if (prod.wrap == cons.wrap) { | 447 | if (prod.wrap == cons.wrap) { |
347 | /* the filled destination area is unwrapped, | 448 | /* the filled destination area is unwrapped, |
@@ -358,8 +459,6 @@ static int smc_tx_rdma_writes(struct smc_connection *conn) | |||
358 | */ | 459 | */ |
359 | dst_len = len; | 460 | dst_len = len; |
360 | } | 461 | } |
361 | dst_len_sum = dst_len; | ||
362 | src_off = sent.count; | ||
363 | /* dst_len determines the maximum src_len */ | 462 | /* dst_len determines the maximum src_len */ |
364 | if (sent.count + dst_len <= conn->sndbuf_desc->len) { | 463 | if (sent.count + dst_len <= conn->sndbuf_desc->len) { |
365 | /* unwrapped src case: single chunk of entire dst_len */ | 464 | /* unwrapped src case: single chunk of entire dst_len */ |
@@ -368,38 +467,15 @@ static int smc_tx_rdma_writes(struct smc_connection *conn) | |||
368 | /* wrapped src case: 2 chunks of sum dst_len; start with 1st: */ | 467 | /* wrapped src case: 2 chunks of sum dst_len; start with 1st: */ |
369 | src_len = conn->sndbuf_desc->len - sent.count; | 468 | src_len = conn->sndbuf_desc->len - sent.count; |
370 | } | 469 | } |
371 | src_len_sum = src_len; | 470 | |
372 | dma_addr = sg_dma_address(conn->sndbuf_desc->sgt[SMC_SINGLE_LINK].sgl); | 471 | if (conn->lgr->is_smcd) |
373 | for (dstchunk = 0; dstchunk < 2; dstchunk++) { | 472 | rc = smcd_tx_rdma_writes(conn, len, sent.count, src_len, |
374 | num_sges = 0; | 473 | dst_off, dst_len); |
375 | for (srcchunk = 0; srcchunk < 2; srcchunk++) { | 474 | else |
376 | sges[srcchunk].addr = dma_addr + src_off; | 475 | rc = smcr_tx_rdma_writes(conn, len, sent.count, src_len, |
377 | sges[srcchunk].length = src_len; | 476 | dst_off, dst_len); |
378 | sges[srcchunk].lkey = link->roce_pd->local_dma_lkey; | 477 | if (rc) |
379 | num_sges++; | 478 | return rc; |
380 | src_off += src_len; | ||
381 | if (src_off >= conn->sndbuf_desc->len) | ||
382 | src_off -= conn->sndbuf_desc->len; | ||
383 | /* modulo in send ring */ | ||
384 | if (src_len_sum == dst_len) | ||
385 | break; /* either on 1st or 2nd iteration */ | ||
386 | /* prepare next (== 2nd) iteration */ | ||
387 | src_len = dst_len - src_len; /* remainder */ | ||
388 | src_len_sum += src_len; | ||
389 | } | ||
390 | rc = smc_tx_rdma_write(conn, dst_off, num_sges, sges); | ||
391 | if (rc) | ||
392 | return rc; | ||
393 | if (dst_len_sum == len) | ||
394 | break; /* either on 1st or 2nd iteration */ | ||
395 | /* prepare next (== 2nd) iteration */ | ||
396 | dst_off = 0; /* modulo offset in RMBE ring buffer */ | ||
397 | dst_len = len - dst_len; /* remainder */ | ||
398 | dst_len_sum += dst_len; | ||
399 | src_len = min_t(int, | ||
400 | dst_len, conn->sndbuf_desc->len - sent.count); | ||
401 | src_len_sum = src_len; | ||
402 | } | ||
403 | 479 | ||
404 | if (conn->urg_tx_pend && len == to_send) | 480 | if (conn->urg_tx_pend && len == to_send) |
405 | pflags->urg_data_present = 1; | 481 | pflags->urg_data_present = 1; |
@@ -420,7 +496,7 @@ static int smc_tx_rdma_writes(struct smc_connection *conn) | |||
420 | /* Wakeup sndbuf consumers from any context (IRQ or process) | 496 | /* Wakeup sndbuf consumers from any context (IRQ or process) |
421 | * since there is more data to transmit; usable snd_wnd as max transmit | 497 | * since there is more data to transmit; usable snd_wnd as max transmit |
422 | */ | 498 | */ |
423 | int smc_tx_sndbuf_nonempty(struct smc_connection *conn) | 499 | static int smcr_tx_sndbuf_nonempty(struct smc_connection *conn) |
424 | { | 500 | { |
425 | struct smc_cdc_producer_flags *pflags; | 501 | struct smc_cdc_producer_flags *pflags; |
426 | struct smc_cdc_tx_pend *pend; | 502 | struct smc_cdc_tx_pend *pend; |
@@ -467,6 +543,37 @@ out_unlock: | |||
467 | return rc; | 543 | return rc; |
468 | } | 544 | } |
469 | 545 | ||
546 | static int smcd_tx_sndbuf_nonempty(struct smc_connection *conn) | ||
547 | { | ||
548 | struct smc_cdc_producer_flags *pflags = &conn->local_tx_ctrl.prod_flags; | ||
549 | int rc = 0; | ||
550 | |||
551 | spin_lock_bh(&conn->send_lock); | ||
552 | if (!pflags->urg_data_present) | ||
553 | rc = smc_tx_rdma_writes(conn); | ||
554 | if (!rc) | ||
555 | rc = smcd_cdc_msg_send(conn); | ||
556 | |||
557 | if (!rc && pflags->urg_data_present) { | ||
558 | pflags->urg_data_pending = 0; | ||
559 | pflags->urg_data_present = 0; | ||
560 | } | ||
561 | spin_unlock_bh(&conn->send_lock); | ||
562 | return rc; | ||
563 | } | ||
564 | |||
565 | int smc_tx_sndbuf_nonempty(struct smc_connection *conn) | ||
566 | { | ||
567 | int rc; | ||
568 | |||
569 | if (conn->lgr->is_smcd) | ||
570 | rc = smcd_tx_sndbuf_nonempty(conn); | ||
571 | else | ||
572 | rc = smcr_tx_sndbuf_nonempty(conn); | ||
573 | |||
574 | return rc; | ||
575 | } | ||
576 | |||
470 | /* Wakeup sndbuf consumers from process context | 577 | /* Wakeup sndbuf consumers from process context |
471 | * since there is more data to transmit | 578 | * since there is more data to transmit |
472 | */ | 579 | */ |