aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ntb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ntb')
-rw-r--r--drivers/ntb/ntb_transport.c137
1 files changed, 63 insertions, 74 deletions
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
index 1bed1ba2fe5e..69c58da0fa34 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -78,6 +78,10 @@ struct ntb_queue_entry {
78 unsigned int flags; 78 unsigned int flags;
79}; 79};
80 80
81struct ntb_rx_info {
82 unsigned int entry;
83};
84
81struct ntb_transport_qp { 85struct ntb_transport_qp {
82 struct ntb_transport *transport; 86 struct ntb_transport *transport;
83 struct ntb_device *ndev; 87 struct ntb_device *ndev;
@@ -87,13 +91,16 @@ struct ntb_transport_qp {
87 bool qp_link; 91 bool qp_link;
88 u8 qp_num; /* Only 64 QP's are allowed. 0-63 */ 92 u8 qp_num; /* Only 64 QP's are allowed. 0-63 */
89 93
94 struct ntb_rx_info *rx_info;
95 struct ntb_rx_info *remote_rx_info;
96
90 void (*tx_handler) (struct ntb_transport_qp *qp, void *qp_data, 97 void (*tx_handler) (struct ntb_transport_qp *qp, void *qp_data,
91 void *data, int len); 98 void *data, int len);
92 struct list_head tx_free_q; 99 struct list_head tx_free_q;
93 spinlock_t ntb_tx_free_q_lock; 100 spinlock_t ntb_tx_free_q_lock;
94 void *tx_mw_begin; 101 void *tx_mw;
95 void *tx_mw_end; 102 unsigned int tx_index;
96 void *tx_offset; 103 unsigned int tx_max_entry;
97 unsigned int tx_max_frame; 104 unsigned int tx_max_frame;
98 105
99 void (*rx_handler) (struct ntb_transport_qp *qp, void *qp_data, 106 void (*rx_handler) (struct ntb_transport_qp *qp, void *qp_data,
@@ -103,9 +110,9 @@ struct ntb_transport_qp {
103 struct list_head rx_free_q; 110 struct list_head rx_free_q;
104 spinlock_t ntb_rx_pend_q_lock; 111 spinlock_t ntb_rx_pend_q_lock;
105 spinlock_t ntb_rx_free_q_lock; 112 spinlock_t ntb_rx_free_q_lock;
106 void *rx_buff_begin; 113 void *rx_buff;
107 void *rx_buff_end; 114 unsigned int rx_index;
108 void *rx_offset; 115 unsigned int rx_max_entry;
109 unsigned int rx_max_frame; 116 unsigned int rx_max_frame;
110 117
111 void (*event_handler) (void *data, int status); 118 void (*event_handler) (void *data, int status);
@@ -394,11 +401,11 @@ static ssize_t debugfs_read(struct file *filp, char __user *ubuf, size_t count,
394 out_offset += snprintf(buf + out_offset, out_count - out_offset, 401 out_offset += snprintf(buf + out_offset, out_count - out_offset,
395 "rx_err_ver - \t%llu\n", qp->rx_err_ver); 402 "rx_err_ver - \t%llu\n", qp->rx_err_ver);
396 out_offset += snprintf(buf + out_offset, out_count - out_offset, 403 out_offset += snprintf(buf + out_offset, out_count - out_offset,
397 "rx_buff_begin - %p\n", qp->rx_buff_begin); 404 "rx_buff - \t%p\n", qp->rx_buff);
398 out_offset += snprintf(buf + out_offset, out_count - out_offset, 405 out_offset += snprintf(buf + out_offset, out_count - out_offset,
399 "rx_offset - \t%p\n", qp->rx_offset); 406 "rx_index - \t%u\n", qp->rx_index);
400 out_offset += snprintf(buf + out_offset, out_count - out_offset, 407 out_offset += snprintf(buf + out_offset, out_count - out_offset,
401 "rx_buff_end - \t%p\n", qp->rx_buff_end); 408 "rx_max_entry - \t%u\n", qp->rx_max_entry);
402 409
403 out_offset += snprintf(buf + out_offset, out_count - out_offset, 410 out_offset += snprintf(buf + out_offset, out_count - out_offset,
404 "tx_bytes - \t%llu\n", qp->tx_bytes); 411 "tx_bytes - \t%llu\n", qp->tx_bytes);
@@ -407,11 +414,11 @@ static ssize_t debugfs_read(struct file *filp, char __user *ubuf, size_t count,
407 out_offset += snprintf(buf + out_offset, out_count - out_offset, 414 out_offset += snprintf(buf + out_offset, out_count - out_offset,
408 "tx_ring_full - \t%llu\n", qp->tx_ring_full); 415 "tx_ring_full - \t%llu\n", qp->tx_ring_full);
409 out_offset += snprintf(buf + out_offset, out_count - out_offset, 416 out_offset += snprintf(buf + out_offset, out_count - out_offset,
410 "tx_mw_begin - \t%p\n", qp->tx_mw_begin); 417 "tx_mw - \t%p\n", qp->tx_mw);
411 out_offset += snprintf(buf + out_offset, out_count - out_offset, 418 out_offset += snprintf(buf + out_offset, out_count - out_offset,
412 "tx_offset - \t%p\n", qp->tx_offset); 419 "tx_index - \t%u\n", qp->tx_index);
413 out_offset += snprintf(buf + out_offset, out_count - out_offset, 420 out_offset += snprintf(buf + out_offset, out_count - out_offset,
414 "tx_mw_end - \t%p\n", qp->tx_mw_end); 421 "tx_max_entry - \t%u\n", qp->tx_max_entry);
415 422
416 out_offset += snprintf(buf + out_offset, out_count - out_offset, 423 out_offset += snprintf(buf + out_offset, out_count - out_offset,
417 "\nQP Link %s\n", (qp->qp_link == NTB_LINK_UP) ? 424 "\nQP Link %s\n", (qp->qp_link == NTB_LINK_UP) ?
@@ -465,7 +472,7 @@ static void ntb_transport_setup_qp_mw(struct ntb_transport *nt,
465 struct ntb_transport_qp *qp = &nt->qps[qp_num]; 472 struct ntb_transport_qp *qp = &nt->qps[qp_num];
466 unsigned int rx_size, num_qps_mw; 473 unsigned int rx_size, num_qps_mw;
467 u8 mw_num = QP_TO_MW(qp_num); 474 u8 mw_num = QP_TO_MW(qp_num);
468 void *offset; 475 unsigned int i;
469 476
470 WARN_ON(nt->mw[mw_num].virt_addr == 0); 477 WARN_ON(nt->mw[mw_num].virt_addr == 0);
471 478
@@ -474,18 +481,24 @@ static void ntb_transport_setup_qp_mw(struct ntb_transport *nt,
474 else 481 else
475 num_qps_mw = nt->max_qps / NTB_NUM_MW; 482 num_qps_mw = nt->max_qps / NTB_NUM_MW;
476 483
477 rx_size = nt->mw[mw_num].size / num_qps_mw; 484 rx_size = (unsigned int) nt->mw[mw_num].size / num_qps_mw;
478 qp->rx_buff_begin = nt->mw[mw_num].virt_addr + 485 qp->remote_rx_info = nt->mw[mw_num].virt_addr +
479 (qp_num / NTB_NUM_MW * rx_size); 486 (qp_num / NTB_NUM_MW * rx_size);
480 qp->rx_buff_end = qp->rx_buff_begin + rx_size; 487 rx_size -= sizeof(struct ntb_rx_info);
481 qp->rx_offset = qp->rx_buff_begin; 488
489 qp->rx_buff = qp->remote_rx_info + sizeof(struct ntb_rx_info);
482 qp->rx_max_frame = min(transport_mtu, rx_size); 490 qp->rx_max_frame = min(transport_mtu, rx_size);
491 qp->rx_max_entry = rx_size / qp->rx_max_frame;
492 qp->rx_index = 0;
493
494 qp->remote_rx_info->entry = qp->rx_max_entry;
483 495
484 /* setup the hdr offsets with 0's */ 496 /* setup the hdr offsets with 0's */
485 for (offset = qp->rx_buff_begin + qp->rx_max_frame - 497 for (i = 0; i < qp->rx_max_entry; i++) {
486 sizeof(struct ntb_payload_header); 498 void *offset = qp->rx_buff + qp->rx_max_frame * (i + 1) -
487 offset < qp->rx_buff_end; offset += qp->rx_max_frame) 499 sizeof(struct ntb_payload_header);
488 memset(offset, 0, sizeof(struct ntb_payload_header)); 500 memset(offset, 0, sizeof(struct ntb_payload_header));
501 }
489 502
490 qp->rx_pkts = 0; 503 qp->rx_pkts = 0;
491 qp->tx_pkts = 0; 504 qp->tx_pkts = 0;
@@ -762,12 +775,15 @@ static void ntb_transport_init_queue(struct ntb_transport *nt,
762 else 775 else
763 num_qps_mw = nt->max_qps / NTB_NUM_MW; 776 num_qps_mw = nt->max_qps / NTB_NUM_MW;
764 777
765 tx_size = ntb_get_mw_size(qp->ndev, mw_num) / num_qps_mw; 778 tx_size = (unsigned int) ntb_get_mw_size(qp->ndev, mw_num) / num_qps_mw;
766 qp->tx_mw_begin = ntb_get_mw_vbase(nt->ndev, mw_num) + 779 qp->rx_info = ntb_get_mw_vbase(nt->ndev, mw_num) +
767 (qp_num / NTB_NUM_MW * tx_size); 780 (qp_num / NTB_NUM_MW * tx_size);
768 qp->tx_mw_end = qp->tx_mw_begin + tx_size; 781 tx_size -= sizeof(struct ntb_rx_info);
769 qp->tx_offset = qp->tx_mw_begin; 782
783 qp->tx_mw = qp->rx_info + sizeof(struct ntb_rx_info);
770 qp->tx_max_frame = min(transport_mtu, tx_size); 784 qp->tx_max_frame = min(transport_mtu, tx_size);
785 qp->tx_max_entry = tx_size / qp->tx_max_frame;
786 qp->tx_index = 0;
771 787
772 if (nt->debugfs_dir) { 788 if (nt->debugfs_dir) {
773 char debugfs_name[4]; 789 char debugfs_name[4];
@@ -894,21 +910,8 @@ void ntb_transport_free(void *transport)
894static void ntb_rx_copy_task(struct ntb_transport_qp *qp, 910static void ntb_rx_copy_task(struct ntb_transport_qp *qp,
895 struct ntb_queue_entry *entry, void *offset) 911 struct ntb_queue_entry *entry, void *offset)
896{ 912{
897
898 struct ntb_payload_header *hdr;
899
900 BUG_ON(offset < qp->rx_buff_begin ||
901 offset + qp->rx_max_frame >= qp->rx_buff_end);
902
903 hdr = offset + qp->rx_max_frame - sizeof(struct ntb_payload_header);
904 entry->len = hdr->len;
905
906 memcpy(entry->buf, offset, entry->len); 913 memcpy(entry->buf, offset, entry->len);
907 914
908 /* Ensure that the data is fully copied out before clearing the flag */
909 wmb();
910 hdr->flags = 0;
911
912 if (qp->rx_handler && qp->client_ready == NTB_LINK_UP) 915 if (qp->rx_handler && qp->client_ready == NTB_LINK_UP)
913 qp->rx_handler(qp, qp->cb_data, entry->cb_data, entry->len); 916 qp->rx_handler(qp, qp->cb_data, entry->cb_data, entry->len);
914 917
@@ -921,10 +924,11 @@ static int ntb_process_rxc(struct ntb_transport_qp *qp)
921 struct ntb_queue_entry *entry; 924 struct ntb_queue_entry *entry;
922 void *offset; 925 void *offset;
923 926
927 offset = qp->rx_buff + qp->rx_max_frame * qp->rx_index;
928 hdr = offset + qp->rx_max_frame - sizeof(struct ntb_payload_header);
929
924 entry = ntb_list_rm(&qp->ntb_rx_pend_q_lock, &qp->rx_pend_q); 930 entry = ntb_list_rm(&qp->ntb_rx_pend_q_lock, &qp->rx_pend_q);
925 if (!entry) { 931 if (!entry) {
926 hdr = offset + qp->rx_max_frame -
927 sizeof(struct ntb_payload_header);
928 dev_dbg(&ntb_query_pdev(qp->ndev)->dev, 932 dev_dbg(&ntb_query_pdev(qp->ndev)->dev,
929 "no buffer - HDR ver %llu, len %d, flags %x\n", 933 "no buffer - HDR ver %llu, len %d, flags %x\n",
930 hdr->ver, hdr->len, hdr->flags); 934 hdr->ver, hdr->len, hdr->flags);
@@ -932,9 +936,6 @@ static int ntb_process_rxc(struct ntb_transport_qp *qp)
932 return -ENOMEM; 936 return -ENOMEM;
933 } 937 }
934 938
935 offset = qp->rx_offset;
936 hdr = offset + qp->rx_max_frame - sizeof(struct ntb_payload_header);
937
938 if (!(hdr->flags & DESC_DONE_FLAG)) { 939 if (!(hdr->flags & DESC_DONE_FLAG)) {
939 ntb_list_add(&qp->ntb_rx_pend_q_lock, &entry->entry, 940 ntb_list_add(&qp->ntb_rx_pend_q_lock, &entry->entry,
940 &qp->rx_pend_q); 941 &qp->rx_pend_q);
@@ -957,30 +958,20 @@ static int ntb_process_rxc(struct ntb_transport_qp *qp)
957 958
958 ntb_list_add(&qp->ntb_rx_pend_q_lock, &entry->entry, 959 ntb_list_add(&qp->ntb_rx_pend_q_lock, &entry->entry,
959 &qp->rx_pend_q); 960 &qp->rx_pend_q);
960
961 /* Ensure that the data is fully copied out before clearing the
962 * done flag
963 */
964 wmb();
965 hdr->flags = 0;
966 goto out; 961 goto out;
967 } 962 }
968 963
969 dev_dbg(&ntb_query_pdev(qp->ndev)->dev, 964 dev_dbg(&ntb_query_pdev(qp->ndev)->dev,
970 "rx offset %p, ver %llu - %d payload received, buf size %d\n", 965 "rx offset %u, ver %llu - %d payload received, buf size %d\n",
971 qp->rx_offset, hdr->ver, hdr->len, entry->len); 966 qp->rx_index, hdr->ver, hdr->len, entry->len);
972 967
973 if (hdr->len <= entry->len) 968 if (hdr->len <= entry->len) {
969 entry->len = hdr->len;
974 ntb_rx_copy_task(qp, entry, offset); 970 ntb_rx_copy_task(qp, entry, offset);
975 else { 971 } else {
976 ntb_list_add(&qp->ntb_rx_pend_q_lock, &entry->entry, 972 ntb_list_add(&qp->ntb_rx_pend_q_lock, &entry->entry,
977 &qp->rx_pend_q); 973 &qp->rx_pend_q);
978 974
979 /* Ensure that the data is fully copied out before clearing the
980 * done flag
981 */
982 wmb();
983 hdr->flags = 0;
984 qp->rx_err_oflow++; 975 qp->rx_err_oflow++;
985 dev_dbg(&ntb_query_pdev(qp->ndev)->dev, 976 dev_dbg(&ntb_query_pdev(qp->ndev)->dev,
986 "RX overflow! Wanted %d got %d\n", 977 "RX overflow! Wanted %d got %d\n",
@@ -991,9 +982,13 @@ static int ntb_process_rxc(struct ntb_transport_qp *qp)
991 qp->rx_pkts++; 982 qp->rx_pkts++;
992 983
993out: 984out:
994 qp->rx_offset += qp->rx_max_frame; 985 /* Ensure that the data is fully copied out before clearing the flag */
995 if (qp->rx_offset + qp->rx_max_frame >= qp->rx_buff_end) 986 wmb();
996 qp->rx_offset = qp->rx_buff_begin; 987 hdr->flags = 0;
988 qp->rx_info->entry = qp->rx_index;
989
990 qp->rx_index++;
991 qp->rx_index %= qp->rx_max_entry;
997 992
998 return 0; 993 return 0;
999} 994}
@@ -1024,9 +1019,6 @@ static void ntb_tx_copy_task(struct ntb_transport_qp *qp,
1024{ 1019{
1025 struct ntb_payload_header *hdr; 1020 struct ntb_payload_header *hdr;
1026 1021
1027 BUG_ON(offset < qp->tx_mw_begin ||
1028 offset + qp->tx_max_frame >= qp->tx_mw_end);
1029
1030 memcpy_toio(offset, entry->buf, entry->len); 1022 memcpy_toio(offset, entry->buf, entry->len);
1031 1023
1032 hdr = offset + qp->tx_max_frame - sizeof(struct ntb_payload_header); 1024 hdr = offset + qp->tx_max_frame - sizeof(struct ntb_payload_header);
@@ -1057,16 +1049,14 @@ static void ntb_tx_copy_task(struct ntb_transport_qp *qp,
1057static int ntb_process_tx(struct ntb_transport_qp *qp, 1049static int ntb_process_tx(struct ntb_transport_qp *qp,
1058 struct ntb_queue_entry *entry) 1050 struct ntb_queue_entry *entry)
1059{ 1051{
1060 struct ntb_payload_header *hdr;
1061 void *offset; 1052 void *offset;
1062 1053
1063 offset = qp->tx_offset; 1054 offset = qp->tx_mw + qp->tx_max_frame * qp->tx_index;
1064 hdr = offset + qp->tx_max_frame - sizeof(struct ntb_payload_header);
1065 1055
1066 dev_dbg(&ntb_query_pdev(qp->ndev)->dev, "%lld - offset %p, tx %p, entry len %d flags %x buff %p\n", 1056 dev_dbg(&ntb_query_pdev(qp->ndev)->dev, "%lld - offset %p, tx %u, entry len %d flags %x buff %p\n",
1067 qp->tx_pkts, offset, qp->tx_offset, entry->len, entry->flags, 1057 qp->tx_pkts, offset, qp->tx_index, entry->len, entry->flags,
1068 entry->buf); 1058 entry->buf);
1069 if (hdr->flags) { 1059 if (qp->tx_index == qp->remote_rx_info->entry) {
1070 qp->tx_ring_full++; 1060 qp->tx_ring_full++;
1071 return -EAGAIN; 1061 return -EAGAIN;
1072 } 1062 }
@@ -1082,9 +1072,8 @@ static int ntb_process_tx(struct ntb_transport_qp *qp,
1082 1072
1083 ntb_tx_copy_task(qp, entry, offset); 1073 ntb_tx_copy_task(qp, entry, offset);
1084 1074
1085 qp->tx_offset += qp->tx_max_frame; 1075 qp->tx_index++;
1086 if (qp->tx_offset + qp->tx_max_frame >= qp->tx_mw_end) 1076 qp->tx_index %= qp->tx_max_entry;
1087 qp->tx_offset = qp->tx_mw_begin;
1088 1077
1089 qp->tx_pkts++; 1078 qp->tx_pkts++;
1090 1079