aboutsummaryrefslogtreecommitdiffstats
path: root/net/smc/smc_tx.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/smc/smc_tx.c')
-rw-r--r--net/smc/smc_tx.c193
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 */
255int 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 */
254static int smc_tx_rdma_write(struct smc_connection *conn, int peer_rmbe_offset, 273static 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() */
320static 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() */
369static 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 */
303static int smc_tx_rdma_writes(struct smc_connection *conn) 411static 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 */
423int smc_tx_sndbuf_nonempty(struct smc_connection *conn) 499static 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
546static 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
565int 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 */