Merge branch 'bcmgenet-next'
Petri Gynther says: ==================== net: bcmgenet: Tx init improvements Four small patches to improve bcmgenet Tx init: 1. bcmgenet_init_tx_ring() cleanup 2. rework Tx queue init 3. precalculate TxCB->bd_addr 4. rename bcmgenet_hw_params->bds_cnt and GENET_DEFAULT_BD_CNT ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
1e0629d3f8
|
@ -54,8 +54,8 @@
|
||||||
/* Default highest priority queue for multi queue support */
|
/* Default highest priority queue for multi queue support */
|
||||||
#define GENET_Q0_PRIORITY 0
|
#define GENET_Q0_PRIORITY 0
|
||||||
|
|
||||||
#define GENET_DEFAULT_BD_CNT \
|
#define GENET_Q16_TX_BD_CNT \
|
||||||
(TOTAL_DESC - priv->hw_params->tx_queues * priv->hw_params->bds_cnt)
|
(TOTAL_DESC - priv->hw_params->tx_queues * priv->hw_params->tx_bds_per_q)
|
||||||
|
|
||||||
#define RX_BUF_LENGTH 2048
|
#define RX_BUF_LENGTH 2048
|
||||||
#define SKB_ALIGNMENT 32
|
#define SKB_ALIGNMENT 32
|
||||||
|
@ -920,7 +920,7 @@ static struct enet_cb *bcmgenet_get_txcb(struct bcmgenet_priv *priv,
|
||||||
|
|
||||||
tx_cb_ptr = ring->cbs;
|
tx_cb_ptr = ring->cbs;
|
||||||
tx_cb_ptr += ring->write_ptr - ring->cb_ptr;
|
tx_cb_ptr += ring->write_ptr - ring->cb_ptr;
|
||||||
tx_cb_ptr->bd_addr = priv->tx_bds + ring->write_ptr * DMA_DESC_SIZE;
|
|
||||||
/* Advancing local write pointer */
|
/* Advancing local write pointer */
|
||||||
if (ring->write_ptr == ring->end_ptr)
|
if (ring->write_ptr == ring->end_ptr)
|
||||||
ring->write_ptr = ring->cb_ptr;
|
ring->write_ptr = ring->cb_ptr;
|
||||||
|
@ -1680,17 +1680,14 @@ static int init_umac(struct bcmgenet_priv *priv)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize all house-keeping variables for a TX ring, along
|
/* Initialize a Tx ring along with corresponding hardware registers */
|
||||||
* with corresponding hardware registers
|
|
||||||
*/
|
|
||||||
static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv,
|
static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv,
|
||||||
unsigned int index, unsigned int size,
|
unsigned int index, unsigned int size,
|
||||||
unsigned int write_ptr, unsigned int end_ptr)
|
unsigned int start_ptr, unsigned int end_ptr)
|
||||||
{
|
{
|
||||||
struct bcmgenet_tx_ring *ring = &priv->tx_rings[index];
|
struct bcmgenet_tx_ring *ring = &priv->tx_rings[index];
|
||||||
u32 words_per_bd = WORDS_PER_BD(priv);
|
u32 words_per_bd = WORDS_PER_BD(priv);
|
||||||
u32 flow_period_val = 0;
|
u32 flow_period_val = 0;
|
||||||
unsigned int first_bd;
|
|
||||||
|
|
||||||
spin_lock_init(&ring->lock);
|
spin_lock_init(&ring->lock);
|
||||||
ring->index = index;
|
ring->index = index;
|
||||||
|
@ -1703,12 +1700,12 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv,
|
||||||
ring->int_enable = bcmgenet_tx_ring_int_enable;
|
ring->int_enable = bcmgenet_tx_ring_int_enable;
|
||||||
ring->int_disable = bcmgenet_tx_ring_int_disable;
|
ring->int_disable = bcmgenet_tx_ring_int_disable;
|
||||||
}
|
}
|
||||||
ring->cbs = priv->tx_cbs + write_ptr;
|
ring->cbs = priv->tx_cbs + start_ptr;
|
||||||
ring->size = size;
|
ring->size = size;
|
||||||
ring->c_index = 0;
|
ring->c_index = 0;
|
||||||
ring->free_bds = size;
|
ring->free_bds = size;
|
||||||
ring->write_ptr = write_ptr;
|
ring->write_ptr = start_ptr;
|
||||||
ring->cb_ptr = write_ptr;
|
ring->cb_ptr = start_ptr;
|
||||||
ring->end_ptr = end_ptr - 1;
|
ring->end_ptr = end_ptr - 1;
|
||||||
ring->prod_index = 0;
|
ring->prod_index = 0;
|
||||||
|
|
||||||
|
@ -1722,19 +1719,16 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv,
|
||||||
/* Disable rate control for now */
|
/* Disable rate control for now */
|
||||||
bcmgenet_tdma_ring_writel(priv, index, flow_period_val,
|
bcmgenet_tdma_ring_writel(priv, index, flow_period_val,
|
||||||
TDMA_FLOW_PERIOD);
|
TDMA_FLOW_PERIOD);
|
||||||
/* Unclassified traffic goes to ring 16 */
|
|
||||||
bcmgenet_tdma_ring_writel(priv, index,
|
bcmgenet_tdma_ring_writel(priv, index,
|
||||||
((size << DMA_RING_SIZE_SHIFT) |
|
((size << DMA_RING_SIZE_SHIFT) |
|
||||||
RX_BUF_LENGTH), DMA_RING_BUF_SIZE);
|
RX_BUF_LENGTH), DMA_RING_BUF_SIZE);
|
||||||
|
|
||||||
first_bd = write_ptr;
|
|
||||||
|
|
||||||
/* Set start and end address, read and write pointers */
|
/* Set start and end address, read and write pointers */
|
||||||
bcmgenet_tdma_ring_writel(priv, index, first_bd * words_per_bd,
|
bcmgenet_tdma_ring_writel(priv, index, start_ptr * words_per_bd,
|
||||||
DMA_START_ADDR);
|
DMA_START_ADDR);
|
||||||
bcmgenet_tdma_ring_writel(priv, index, first_bd * words_per_bd,
|
bcmgenet_tdma_ring_writel(priv, index, start_ptr * words_per_bd,
|
||||||
TDMA_READ_PTR);
|
TDMA_READ_PTR);
|
||||||
bcmgenet_tdma_ring_writel(priv, index, first_bd,
|
bcmgenet_tdma_ring_writel(priv, index, start_ptr * words_per_bd,
|
||||||
TDMA_WRITE_PTR);
|
TDMA_WRITE_PTR);
|
||||||
bcmgenet_tdma_ring_writel(priv, index, end_ptr * words_per_bd - 1,
|
bcmgenet_tdma_ring_writel(priv, index, end_ptr * words_per_bd - 1,
|
||||||
DMA_END_ADDR);
|
DMA_END_ADDR);
|
||||||
|
@ -1782,78 +1776,73 @@ static int bcmgenet_init_rx_ring(struct bcmgenet_priv *priv,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* init multi xmit queues, only available for GENET2+
|
/* Initialize Tx queues
|
||||||
* the queue is partitioned as follows:
|
|
||||||
*
|
*
|
||||||
* queue 0 - 3 is priority based, each one has 32 descriptors,
|
* Queues 0-3 are priority-based, each one has 32 descriptors,
|
||||||
* with queue 0 being the highest priority queue.
|
* with queue 0 being the highest priority queue.
|
||||||
*
|
*
|
||||||
* queue 16 is the default tx queue with GENET_DEFAULT_BD_CNT
|
* Queue 16 is the default Tx queue with
|
||||||
* descriptors: 256 - (number of tx queues * bds per queues) = 128
|
* GENET_Q16_TX_BD_CNT = 256 - 4 * 32 = 128 descriptors.
|
||||||
* descriptors.
|
|
||||||
*
|
*
|
||||||
* The transmit control block pool is then partitioned as following:
|
* The transmit control block pool is then partitioned as follows:
|
||||||
* - tx_cbs[0...127] are for queue 16
|
* - Tx queue 0 uses tx_cbs[0..31]
|
||||||
* - tx_ring_cbs[0] points to tx_cbs[128..159]
|
* - Tx queue 1 uses tx_cbs[32..63]
|
||||||
* - tx_ring_cbs[1] points to tx_cbs[160..191]
|
* - Tx queue 2 uses tx_cbs[64..95]
|
||||||
* - tx_ring_cbs[2] points to tx_cbs[192..223]
|
* - Tx queue 3 uses tx_cbs[96..127]
|
||||||
* - tx_ring_cbs[3] points to tx_cbs[224..255]
|
* - Tx queue 16 uses tx_cbs[128..255]
|
||||||
*/
|
*/
|
||||||
static void bcmgenet_init_multiq(struct net_device *dev)
|
static void bcmgenet_init_tx_queues(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||||
unsigned int i, dma_enable;
|
u32 i, dma_enable;
|
||||||
u32 reg, dma_ctrl, ring_cfg = 0;
|
u32 dma_ctrl, ring_cfg;
|
||||||
u32 dma_priority[3] = {0, 0, 0};
|
u32 dma_priority[3] = {0, 0, 0};
|
||||||
|
|
||||||
if (!netif_is_multiqueue(dev)) {
|
|
||||||
netdev_warn(dev, "called with non multi queue aware HW\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dma_ctrl = bcmgenet_tdma_readl(priv, DMA_CTRL);
|
dma_ctrl = bcmgenet_tdma_readl(priv, DMA_CTRL);
|
||||||
dma_enable = dma_ctrl & DMA_EN;
|
dma_enable = dma_ctrl & DMA_EN;
|
||||||
dma_ctrl &= ~DMA_EN;
|
dma_ctrl &= ~DMA_EN;
|
||||||
bcmgenet_tdma_writel(priv, dma_ctrl, DMA_CTRL);
|
bcmgenet_tdma_writel(priv, dma_ctrl, DMA_CTRL);
|
||||||
|
|
||||||
|
dma_ctrl = 0;
|
||||||
|
ring_cfg = 0;
|
||||||
|
|
||||||
/* Enable strict priority arbiter mode */
|
/* Enable strict priority arbiter mode */
|
||||||
bcmgenet_tdma_writel(priv, DMA_ARBITER_SP, DMA_ARB_CTRL);
|
bcmgenet_tdma_writel(priv, DMA_ARBITER_SP, DMA_ARB_CTRL);
|
||||||
|
|
||||||
|
/* Initialize Tx priority queues */
|
||||||
for (i = 0; i < priv->hw_params->tx_queues; i++) {
|
for (i = 0; i < priv->hw_params->tx_queues; i++) {
|
||||||
/* first 64 tx_cbs are reserved for default tx queue
|
bcmgenet_init_tx_ring(priv, i, priv->hw_params->tx_bds_per_q,
|
||||||
* (ring 16)
|
i * priv->hw_params->tx_bds_per_q,
|
||||||
*/
|
(i + 1) * priv->hw_params->tx_bds_per_q);
|
||||||
bcmgenet_init_tx_ring(priv, i, priv->hw_params->bds_cnt,
|
ring_cfg |= (1 << i);
|
||||||
i * priv->hw_params->bds_cnt,
|
dma_ctrl |= (1 << (i + DMA_RING_BUF_EN_SHIFT));
|
||||||
(i + 1) * priv->hw_params->bds_cnt);
|
|
||||||
|
|
||||||
/* Configure ring as descriptor ring and setup priority */
|
|
||||||
ring_cfg |= 1 << i;
|
|
||||||
dma_ctrl |= 1 << (i + DMA_RING_BUF_EN_SHIFT);
|
|
||||||
|
|
||||||
dma_priority[DMA_PRIO_REG_INDEX(i)] |=
|
dma_priority[DMA_PRIO_REG_INDEX(i)] |=
|
||||||
((GENET_Q0_PRIORITY + i) << DMA_PRIO_REG_SHIFT(i));
|
((GENET_Q0_PRIORITY + i) << DMA_PRIO_REG_SHIFT(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set ring 16 priority and program the hardware registers */
|
/* Initialize Tx default queue 16 */
|
||||||
|
bcmgenet_init_tx_ring(priv, DESC_INDEX, GENET_Q16_TX_BD_CNT,
|
||||||
|
priv->hw_params->tx_queues *
|
||||||
|
priv->hw_params->tx_bds_per_q,
|
||||||
|
TOTAL_DESC);
|
||||||
|
ring_cfg |= (1 << DESC_INDEX);
|
||||||
|
dma_ctrl |= (1 << (DESC_INDEX + DMA_RING_BUF_EN_SHIFT));
|
||||||
dma_priority[DMA_PRIO_REG_INDEX(DESC_INDEX)] |=
|
dma_priority[DMA_PRIO_REG_INDEX(DESC_INDEX)] |=
|
||||||
((GENET_Q0_PRIORITY + priv->hw_params->tx_queues) <<
|
((GENET_Q0_PRIORITY + priv->hw_params->tx_queues) <<
|
||||||
DMA_PRIO_REG_SHIFT(DESC_INDEX));
|
DMA_PRIO_REG_SHIFT(DESC_INDEX));
|
||||||
|
|
||||||
|
/* Set Tx queue priorities */
|
||||||
bcmgenet_tdma_writel(priv, dma_priority[0], DMA_PRIORITY_0);
|
bcmgenet_tdma_writel(priv, dma_priority[0], DMA_PRIORITY_0);
|
||||||
bcmgenet_tdma_writel(priv, dma_priority[1], DMA_PRIORITY_1);
|
bcmgenet_tdma_writel(priv, dma_priority[1], DMA_PRIORITY_1);
|
||||||
bcmgenet_tdma_writel(priv, dma_priority[2], DMA_PRIORITY_2);
|
bcmgenet_tdma_writel(priv, dma_priority[2], DMA_PRIORITY_2);
|
||||||
|
|
||||||
/* Enable rings */
|
/* Enable Tx queues */
|
||||||
reg = bcmgenet_tdma_readl(priv, DMA_RING_CFG);
|
bcmgenet_tdma_writel(priv, ring_cfg, DMA_RING_CFG);
|
||||||
reg |= ring_cfg;
|
|
||||||
bcmgenet_tdma_writel(priv, reg, DMA_RING_CFG);
|
|
||||||
|
|
||||||
/* Configure ring as descriptor ring and re-enable DMA if enabled */
|
/* Enable Tx DMA */
|
||||||
reg = bcmgenet_tdma_readl(priv, DMA_CTRL);
|
|
||||||
reg |= dma_ctrl;
|
|
||||||
if (dma_enable)
|
if (dma_enable)
|
||||||
reg |= DMA_EN;
|
dma_ctrl |= DMA_EN;
|
||||||
bcmgenet_tdma_writel(priv, reg, DMA_CTRL);
|
bcmgenet_tdma_writel(priv, dma_ctrl, DMA_CTRL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bcmgenet_dma_teardown(struct bcmgenet_priv *priv)
|
static int bcmgenet_dma_teardown(struct bcmgenet_priv *priv)
|
||||||
|
@ -1930,6 +1919,8 @@ static void bcmgenet_fini_dma(struct bcmgenet_priv *priv)
|
||||||
static int bcmgenet_init_dma(struct bcmgenet_priv *priv)
|
static int bcmgenet_init_dma(struct bcmgenet_priv *priv)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
unsigned int i;
|
||||||
|
struct enet_cb *cb;
|
||||||
|
|
||||||
netif_dbg(priv, hw, priv->dev, "bcmgenet: init_edma\n");
|
netif_dbg(priv, hw, priv->dev, "bcmgenet: init_edma\n");
|
||||||
|
|
||||||
|
@ -1956,14 +1947,13 @@ static int bcmgenet_init_dma(struct bcmgenet_priv *priv)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* initialize multi xmit queue */
|
for (i = 0; i < priv->num_tx_bds; i++) {
|
||||||
bcmgenet_init_multiq(priv->dev);
|
cb = priv->tx_cbs + i;
|
||||||
|
cb->bd_addr = priv->tx_bds + i * DMA_DESC_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
/* initialize special ring 16 */
|
/* Initialize Tx queues */
|
||||||
bcmgenet_init_tx_ring(priv, DESC_INDEX, GENET_DEFAULT_BD_CNT,
|
bcmgenet_init_tx_queues(priv->dev);
|
||||||
priv->hw_params->tx_queues *
|
|
||||||
priv->hw_params->bds_cnt,
|
|
||||||
TOTAL_DESC);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2437,8 +2427,8 @@ static const struct net_device_ops bcmgenet_netdev_ops = {
|
||||||
static struct bcmgenet_hw_params bcmgenet_hw_params[] = {
|
static struct bcmgenet_hw_params bcmgenet_hw_params[] = {
|
||||||
[GENET_V1] = {
|
[GENET_V1] = {
|
||||||
.tx_queues = 0,
|
.tx_queues = 0,
|
||||||
|
.tx_bds_per_q = 0,
|
||||||
.rx_queues = 0,
|
.rx_queues = 0,
|
||||||
.bds_cnt = 0,
|
|
||||||
.bp_in_en_shift = 16,
|
.bp_in_en_shift = 16,
|
||||||
.bp_in_mask = 0xffff,
|
.bp_in_mask = 0xffff,
|
||||||
.hfb_filter_cnt = 16,
|
.hfb_filter_cnt = 16,
|
||||||
|
@ -2450,8 +2440,8 @@ static struct bcmgenet_hw_params bcmgenet_hw_params[] = {
|
||||||
},
|
},
|
||||||
[GENET_V2] = {
|
[GENET_V2] = {
|
||||||
.tx_queues = 4,
|
.tx_queues = 4,
|
||||||
|
.tx_bds_per_q = 32,
|
||||||
.rx_queues = 4,
|
.rx_queues = 4,
|
||||||
.bds_cnt = 32,
|
|
||||||
.bp_in_en_shift = 16,
|
.bp_in_en_shift = 16,
|
||||||
.bp_in_mask = 0xffff,
|
.bp_in_mask = 0xffff,
|
||||||
.hfb_filter_cnt = 16,
|
.hfb_filter_cnt = 16,
|
||||||
|
@ -2466,8 +2456,8 @@ static struct bcmgenet_hw_params bcmgenet_hw_params[] = {
|
||||||
},
|
},
|
||||||
[GENET_V3] = {
|
[GENET_V3] = {
|
||||||
.tx_queues = 4,
|
.tx_queues = 4,
|
||||||
|
.tx_bds_per_q = 32,
|
||||||
.rx_queues = 4,
|
.rx_queues = 4,
|
||||||
.bds_cnt = 32,
|
|
||||||
.bp_in_en_shift = 17,
|
.bp_in_en_shift = 17,
|
||||||
.bp_in_mask = 0x1ffff,
|
.bp_in_mask = 0x1ffff,
|
||||||
.hfb_filter_cnt = 48,
|
.hfb_filter_cnt = 48,
|
||||||
|
@ -2482,8 +2472,8 @@ static struct bcmgenet_hw_params bcmgenet_hw_params[] = {
|
||||||
},
|
},
|
||||||
[GENET_V4] = {
|
[GENET_V4] = {
|
||||||
.tx_queues = 4,
|
.tx_queues = 4,
|
||||||
|
.tx_bds_per_q = 32,
|
||||||
.rx_queues = 4,
|
.rx_queues = 4,
|
||||||
.bds_cnt = 32,
|
|
||||||
.bp_in_en_shift = 17,
|
.bp_in_en_shift = 17,
|
||||||
.bp_in_mask = 0x1ffff,
|
.bp_in_mask = 0x1ffff,
|
||||||
.hfb_filter_cnt = 48,
|
.hfb_filter_cnt = 48,
|
||||||
|
@ -2583,14 +2573,15 @@ static void bcmgenet_set_hw_params(struct bcmgenet_priv *priv)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pr_debug("Configuration for version: %d\n"
|
pr_debug("Configuration for version: %d\n"
|
||||||
"TXq: %1d, RXq: %1d, BDs: %1d\n"
|
"TXq: %1d, TXqBDs: %1d, RXq: %1d\n"
|
||||||
"BP << en: %2d, BP msk: 0x%05x\n"
|
"BP << en: %2d, BP msk: 0x%05x\n"
|
||||||
"HFB count: %2d, QTAQ msk: 0x%05x\n"
|
"HFB count: %2d, QTAQ msk: 0x%05x\n"
|
||||||
"TBUF: 0x%04x, HFB: 0x%04x, HFBreg: 0x%04x\n"
|
"TBUF: 0x%04x, HFB: 0x%04x, HFBreg: 0x%04x\n"
|
||||||
"RDMA: 0x%05x, TDMA: 0x%05x\n"
|
"RDMA: 0x%05x, TDMA: 0x%05x\n"
|
||||||
"Words/BD: %d\n",
|
"Words/BD: %d\n",
|
||||||
priv->version,
|
priv->version,
|
||||||
params->tx_queues, params->rx_queues, params->bds_cnt,
|
params->tx_queues, params->tx_bds_per_q,
|
||||||
|
params->rx_queues,
|
||||||
params->bp_in_en_shift, params->bp_in_mask,
|
params->bp_in_en_shift, params->bp_in_mask,
|
||||||
params->hfb_filter_cnt, params->qtag_mask,
|
params->hfb_filter_cnt, params->qtag_mask,
|
||||||
params->tbuf_offset, params->hfb_offset,
|
params->tbuf_offset, params->hfb_offset,
|
||||||
|
|
|
@ -503,8 +503,8 @@ enum bcmgenet_version {
|
||||||
*/
|
*/
|
||||||
struct bcmgenet_hw_params {
|
struct bcmgenet_hw_params {
|
||||||
u8 tx_queues;
|
u8 tx_queues;
|
||||||
|
u8 tx_bds_per_q;
|
||||||
u8 rx_queues;
|
u8 rx_queues;
|
||||||
u8 bds_cnt;
|
|
||||||
u8 bp_in_en_shift;
|
u8 bp_in_en_shift;
|
||||||
u32 bp_in_mask;
|
u32 bp_in_mask;
|
||||||
u8 hfb_filter_cnt;
|
u8 hfb_filter_cnt;
|
||||||
|
|
Loading…
Reference in New Issue