diff options
author | Shrikrishna Khare <skhare@vmware.com> | 2016-06-16 19:51:55 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-06-17 07:37:04 +0200 |
commit | 3c8b3efc061a745d888869dc3462ac4f7dd582d9 (patch) | |
tree | 1149b4276b76ca224ee99ab78146e643d563bcfb /drivers/net/vmxnet3/vmxnet3_drv.c | |
parent | vmxnet3: introduce generalized command interface to configure the device (diff) | |
download | linux-3c8b3efc061a745d888869dc3462ac4f7dd582d9.tar.xz linux-3c8b3efc061a745d888869dc3462ac4f7dd582d9.zip |
vmxnet3: allow variable length transmit data ring buffer
vmxnet3 driver supports transmit data ring viz. a set of fixed size
buffers used by the driver to copy packet headers. Small packets that
fit these buffers are copied into these buffers entirely.
Currently this buffer size of fixed at 128 bytes. This patch extends
transmit data ring implementation to allow variable length transmit
data ring buffers. The length of the buffer is read from the emulation
during initialization.
Signed-off-by: Sriram Rangarajan <rangarajans@vmware.com>
Signed-off-by: Shrikrishna Khare <skhare@vmware.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/vmxnet3/vmxnet3_drv.c')
-rw-r--r-- | drivers/net/vmxnet3/vmxnet3_drv.c | 55 |
1 files changed, 42 insertions, 13 deletions
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 507c53d4e09c..4e42eb04a198 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -435,8 +435,8 @@ vmxnet3_tq_destroy(struct vmxnet3_tx_queue *tq, tq->tx_ring.base = NULL; } if (tq->data_ring.base) { - dma_free_coherent(&adapter->pdev->dev, tq->data_ring.size * - sizeof(struct Vmxnet3_TxDataDesc), + dma_free_coherent(&adapter->pdev->dev, + tq->data_ring.size * tq->txdata_desc_size, tq->data_ring.base, tq->data_ring.basePA); tq->data_ring.base = NULL; } @@ -478,8 +478,8 @@ vmxnet3_tq_init(struct vmxnet3_tx_queue *tq, tq->tx_ring.next2fill = tq->tx_ring.next2comp = 0; tq->tx_ring.gen = VMXNET3_INIT_GEN; - memset(tq->data_ring.base, 0, tq->data_ring.size * - sizeof(struct Vmxnet3_TxDataDesc)); + memset(tq->data_ring.base, 0, + tq->data_ring.size * tq->txdata_desc_size); /* reset the tx comp ring contents to 0 and reset comp ring states */ memset(tq->comp_ring.base, 0, tq->comp_ring.size * @@ -514,10 +514,10 @@ vmxnet3_tq_create(struct vmxnet3_tx_queue *tq, } tq->data_ring.base = dma_alloc_coherent(&adapter->pdev->dev, - tq->data_ring.size * sizeof(struct Vmxnet3_TxDataDesc), + tq->data_ring.size * tq->txdata_desc_size, &tq->data_ring.basePA, GFP_KERNEL); if (!tq->data_ring.base) { - netdev_err(adapter->netdev, "failed to allocate data ring\n"); + netdev_err(adapter->netdev, "failed to allocate tx data ring\n"); goto err; } @@ -689,7 +689,7 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx, if (ctx->copy_size) { ctx->sop_txd->txd.addr = cpu_to_le64(tq->data_ring.basePA + tq->tx_ring.next2fill * - sizeof(struct Vmxnet3_TxDataDesc)); + tq->txdata_desc_size); ctx->sop_txd->dword[2] = cpu_to_le32(dw2 | ctx->copy_size); ctx->sop_txd->dword[3] = 0; @@ -873,8 +873,9 @@ vmxnet3_parse_hdr(struct sk_buff *skb, struct vmxnet3_tx_queue *tq, ctx->eth_ip_hdr_size = 0; ctx->l4_hdr_size = 0; /* copy as much as allowed */ - ctx->copy_size = min((unsigned int)VMXNET3_HDR_COPY_SIZE - , skb_headlen(skb)); + ctx->copy_size = min_t(unsigned int, + tq->txdata_desc_size, + skb_headlen(skb)); } if (skb->len <= VMXNET3_HDR_COPY_SIZE) @@ -885,7 +886,7 @@ vmxnet3_parse_hdr(struct sk_buff *skb, struct vmxnet3_tx_queue *tq, goto err; } - if (unlikely(ctx->copy_size > VMXNET3_HDR_COPY_SIZE)) { + if (unlikely(ctx->copy_size > tq->txdata_desc_size)) { tq->stats.oversized_hdr++; ctx->copy_size = 0; return 0; @@ -2336,6 +2337,7 @@ vmxnet3_setup_driver_shared(struct vmxnet3_adapter *adapter) tqc->ddPA = cpu_to_le64(tq->buf_info_pa); tqc->txRingSize = cpu_to_le32(tq->tx_ring.size); tqc->dataRingSize = cpu_to_le32(tq->data_ring.size); + tqc->txDataRingDescSize = cpu_to_le32(tq->txdata_desc_size); tqc->compRingSize = cpu_to_le32(tq->comp_ring.size); tqc->ddLen = cpu_to_le32( sizeof(struct vmxnet3_tx_buf_info) * @@ -2689,7 +2691,8 @@ vmxnet3_adjust_rx_ring_size(struct vmxnet3_adapter *adapter) int vmxnet3_create_queues(struct vmxnet3_adapter *adapter, u32 tx_ring_size, - u32 rx_ring_size, u32 rx_ring2_size) + u32 rx_ring_size, u32 rx_ring2_size, + u16 txdata_desc_size) { int err = 0, i; @@ -2698,6 +2701,7 @@ vmxnet3_create_queues(struct vmxnet3_adapter *adapter, u32 tx_ring_size, tq->tx_ring.size = tx_ring_size; tq->data_ring.size = tx_ring_size; tq->comp_ring.size = tx_ring_size; + tq->txdata_desc_size = txdata_desc_size; tq->shared = &adapter->tqd_start[i].ctrl; tq->stopped = true; tq->adapter = adapter; @@ -2754,9 +2758,34 @@ vmxnet3_open(struct net_device *netdev) for (i = 0; i < adapter->num_tx_queues; i++) spin_lock_init(&adapter->tx_queue[i].tx_lock); - err = vmxnet3_create_queues(adapter, adapter->tx_ring_size, + if (VMXNET3_VERSION_GE_3(adapter)) { + unsigned long flags; + u16 txdata_desc_size; + + spin_lock_irqsave(&adapter->cmd_lock, flags); + VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, + VMXNET3_CMD_GET_TXDATA_DESC_SIZE); + txdata_desc_size = VMXNET3_READ_BAR1_REG(adapter, + VMXNET3_REG_CMD); + spin_unlock_irqrestore(&adapter->cmd_lock, flags); + + if ((txdata_desc_size < VMXNET3_TXDATA_DESC_MIN_SIZE) || + (txdata_desc_size > VMXNET3_TXDATA_DESC_MAX_SIZE) || + (txdata_desc_size & VMXNET3_TXDATA_DESC_SIZE_MASK)) { + adapter->txdata_desc_size = + sizeof(struct Vmxnet3_TxDataDesc); + } else { + adapter->txdata_desc_size = txdata_desc_size; + } + } else { + adapter->txdata_desc_size = sizeof(struct Vmxnet3_TxDataDesc); + } + + err = vmxnet3_create_queues(adapter, + adapter->tx_ring_size, adapter->rx_ring_size, - adapter->rx_ring2_size); + adapter->rx_ring2_size, + adapter->txdata_desc_size); if (err) goto queue_err; |