summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/ntb/ntb_transport.c79
1 files changed, 44 insertions, 35 deletions
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
index e9666bd7ef41..2823087a1338 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -60,7 +60,7 @@
#define NTB_TRANSPORT_VERSION 1
-static int transport_mtu = 0x401E;
+static unsigned int transport_mtu = 0x401E;
module_param(transport_mtu, uint, 0644);
MODULE_PARM_DESC(transport_mtu, "Maximum size of NTB transport packets");
@@ -94,6 +94,7 @@ struct ntb_transport_qp {
void *tx_mw_begin;
void *tx_mw_end;
void *tx_offset;
+ unsigned int tx_max_frame;
void (*rx_handler) (struct ntb_transport_qp *qp, void *qp_data,
void *data, int len);
@@ -105,6 +106,7 @@ struct ntb_transport_qp {
void *rx_buff_begin;
void *rx_buff_end;
void *rx_offset;
+ unsigned int rx_max_frame;
void (*event_handler) (void *data, int status);
struct delayed_work link_work;
@@ -458,28 +460,29 @@ static void ntb_transport_setup_qp_mw(struct ntb_transport *nt,
unsigned int qp_num)
{
struct ntb_transport_qp *qp = &nt->qps[qp_num];
- unsigned int size, num_qps_mw;
+ unsigned int rx_size, num_qps_mw;
u8 mw_num = QP_TO_MW(qp_num);
+ void *offset;
WARN_ON(nt->mw[mw_num].virt_addr == 0);
- if (nt->max_qps % NTB_NUM_MW && !mw_num)
- num_qps_mw = nt->max_qps / NTB_NUM_MW +
- (nt->max_qps % NTB_NUM_MW - mw_num);
+ if (nt->max_qps % NTB_NUM_MW && mw_num < nt->max_qps % NTB_NUM_MW)
+ num_qps_mw = nt->max_qps / NTB_NUM_MW + 1;
else
num_qps_mw = nt->max_qps / NTB_NUM_MW;
- size = nt->mw[mw_num].size / num_qps_mw;
-
+ rx_size = nt->mw[mw_num].size / num_qps_mw;
qp->rx_buff_begin = nt->mw[mw_num].virt_addr +
- (qp_num / NTB_NUM_MW * size);
- qp->rx_buff_end = qp->rx_buff_begin + size;
+ (qp_num / NTB_NUM_MW * rx_size);
+ qp->rx_buff_end = qp->rx_buff_begin + rx_size;
qp->rx_offset = qp->rx_buff_begin;
+ qp->rx_max_frame = min(transport_mtu, rx_size);
- qp->tx_mw_begin = ntb_get_mw_vbase(nt->ndev, mw_num) +
- (qp_num / NTB_NUM_MW * size);
- qp->tx_mw_end = qp->tx_mw_begin + size;
- qp->tx_offset = qp->tx_mw_begin;
+ /* setup the hdr offsets with 0's */
+ for (offset = qp->rx_buff_begin + qp->rx_max_frame -
+ sizeof(struct ntb_payload_header);
+ offset < qp->rx_buff_end; offset += qp->rx_max_frame)
+ memset(offset, 0, sizeof(struct ntb_payload_header));
qp->rx_pkts = 0;
qp->tx_pkts = 0;
@@ -489,7 +492,6 @@ static int ntb_set_mw(struct ntb_transport *nt, int num_mw, unsigned int size)
{
struct ntb_transport_mw *mw = &nt->mw[num_mw];
struct pci_dev *pdev = ntb_query_pdev(nt->ndev);
- void *offset;
/* Alloc memory for receiving data. Must be 4k aligned */
mw->size = ALIGN(size, 4096);
@@ -502,12 +504,6 @@ static int ntb_set_mw(struct ntb_transport *nt, int num_mw, unsigned int size)
return -ENOMEM;
}
- /* setup the hdr offsets with 0's */
- for (offset = mw->virt_addr + transport_mtu -
- sizeof(struct ntb_payload_header);
- offset < mw->virt_addr + size; offset += transport_mtu)
- memset(offset, 0, sizeof(struct ntb_payload_header));
-
/* Notify HW the memory location of the receive buffer */
ntb_set_mw_addr(nt->ndev, num_mw, mw->dma_addr);
@@ -737,6 +733,8 @@ static void ntb_transport_init_queue(struct ntb_transport *nt,
unsigned int qp_num)
{
struct ntb_transport_qp *qp;
+ unsigned int num_qps_mw, tx_size;
+ u8 mw_num = QP_TO_MW(qp_num);
qp = &nt->qps[qp_num];
qp->qp_num = qp_num;
@@ -746,6 +744,18 @@ static void ntb_transport_init_queue(struct ntb_transport *nt,
qp->client_ready = NTB_LINK_DOWN;
qp->event_handler = NULL;
+ if (nt->max_qps % NTB_NUM_MW && mw_num < nt->max_qps % NTB_NUM_MW)
+ num_qps_mw = nt->max_qps / NTB_NUM_MW + 1;
+ else
+ num_qps_mw = nt->max_qps / NTB_NUM_MW;
+
+ tx_size = ntb_get_mw_size(qp->ndev, mw_num) / num_qps_mw;
+ qp->tx_mw_begin = ntb_get_mw_vbase(nt->ndev, mw_num) +
+ (qp_num / NTB_NUM_MW * tx_size);
+ qp->tx_mw_end = qp->tx_mw_begin + tx_size;
+ qp->tx_offset = qp->tx_mw_begin;
+ qp->tx_max_frame = min(transport_mtu, tx_size);
+
if (nt->debugfs_dir) {
char debugfs_name[4];
@@ -873,9 +883,9 @@ static void ntb_rx_copy_task(struct ntb_transport_qp *qp,
struct ntb_payload_header *hdr;
BUG_ON(offset < qp->rx_buff_begin ||
- offset + transport_mtu >= qp->rx_buff_end);
+ offset + qp->rx_max_frame >= qp->rx_buff_end);
- hdr = offset + transport_mtu - sizeof(struct ntb_payload_header);
+ hdr = offset + qp->rx_max_frame - sizeof(struct ntb_payload_header);
entry->len = hdr->len;
memcpy(entry->buf, offset, entry->len);
@@ -898,7 +908,7 @@ static int ntb_process_rxc(struct ntb_transport_qp *qp)
entry = ntb_list_rm(&qp->ntb_rx_pend_q_lock, &qp->rx_pend_q);
if (!entry) {
- hdr = offset + transport_mtu -
+ hdr = offset + qp->rx_max_frame -
sizeof(struct ntb_payload_header);
dev_dbg(&ntb_query_pdev(qp->ndev)->dev,
"no buffer - HDR ver %llu, len %d, flags %x\n",
@@ -908,7 +918,7 @@ static int ntb_process_rxc(struct ntb_transport_qp *qp)
}
offset = qp->rx_offset;
- hdr = offset + transport_mtu - sizeof(struct ntb_payload_header);
+ hdr = offset + qp->rx_max_frame - sizeof(struct ntb_payload_header);
if (!(hdr->flags & DESC_DONE_FLAG)) {
ntb_list_add(&qp->ntb_rx_pend_q_lock, &entry->entry,
@@ -966,8 +976,8 @@ static int ntb_process_rxc(struct ntb_transport_qp *qp)
qp->rx_pkts++;
out:
- qp->rx_offset += transport_mtu;
- if (qp->rx_offset + transport_mtu >= qp->rx_buff_end)
+ qp->rx_offset += qp->rx_max_frame;
+ if (qp->rx_offset + qp->rx_max_frame >= qp->rx_buff_end)
qp->rx_offset = qp->rx_buff_begin;
return 0;
@@ -1000,11 +1010,11 @@ static void ntb_tx_copy_task(struct ntb_transport_qp *qp,
struct ntb_payload_header *hdr;
BUG_ON(offset < qp->tx_mw_begin ||
- offset + transport_mtu >= qp->tx_mw_end);
+ offset + qp->tx_max_frame >= qp->tx_mw_end);
memcpy_toio(offset, entry->buf, entry->len);
- hdr = offset + transport_mtu - sizeof(struct ntb_payload_header);
+ hdr = offset + qp->tx_max_frame - sizeof(struct ntb_payload_header);
hdr->len = entry->len;
hdr->ver = qp->tx_pkts;
@@ -1036,7 +1046,7 @@ static int ntb_process_tx(struct ntb_transport_qp *qp,
void *offset;
offset = qp->tx_offset;
- hdr = offset + transport_mtu - sizeof(struct ntb_payload_header);
+ hdr = offset + qp->tx_max_frame - sizeof(struct ntb_payload_header);
dev_dbg(&ntb_query_pdev(qp->ndev)->dev, "%lld - offset %p, tx %p, entry len %d flags %x buff %p\n",
qp->tx_pkts, offset, qp->tx_offset, entry->len, entry->flags,
@@ -1046,7 +1056,7 @@ static int ntb_process_tx(struct ntb_transport_qp *qp,
return -EAGAIN;
}
- if (entry->len > transport_mtu - sizeof(struct ntb_payload_header)) {
+ if (entry->len > qp->tx_max_frame - sizeof(struct ntb_payload_header)) {
if (qp->tx_handler)
qp->tx_handler(qp->cb_data, qp, NULL, -EIO);
@@ -1057,8 +1067,8 @@ static int ntb_process_tx(struct ntb_transport_qp *qp,
ntb_tx_copy_task(qp, entry, offset);
- qp->tx_offset += transport_mtu;
- if (qp->tx_offset + transport_mtu >= qp->tx_mw_end)
+ qp->tx_offset += qp->tx_max_frame;
+ if (qp->tx_offset + qp->tx_max_frame >= qp->tx_mw_end)
qp->tx_offset = qp->tx_mw_begin;
qp->tx_pkts++;
@@ -1425,9 +1435,8 @@ EXPORT_SYMBOL_GPL(ntb_transport_qp_num);
*
* RETURNS: the max payload size of a qp
*/
-unsigned int
-ntb_transport_max_size(__attribute__((unused)) struct ntb_transport_qp *qp)
+unsigned int ntb_transport_max_size(struct ntb_transport_qp *qp)
{
- return transport_mtu - sizeof(struct ntb_payload_header);
+ return qp->tx_max_frame - sizeof(struct ntb_payload_header);
}
EXPORT_SYMBOL_GPL(ntb_transport_max_size);