aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ntb
diff options
context:
space:
mode:
authorJon Mason <jon.mason@intel.com>2013-01-19 04:02:26 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-01-20 18:45:51 -0500
commit793c20e9c924e6bc91bc9b1c98e2f6b8e1bf2fae (patch)
tree1ac009d91230095b0cc5808ef86e089d6fc7c30b /drivers/ntb
parentd7237e22bbcffc3237a234fdf165fde4c2b0a22d (diff)
NTB: Remove reads across NTB
CPU reads across NTB are slow(er) and can hang the local system if an ECC error is encountered on the remote. To work around the need for a read, have the remote side write its current position in the rx buffer to the local system's buffer and use that to see if there is room when transmitting. Signed-off-by: Jon Mason <jon.mason@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
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