/* * Driver for Marvell NETA network controller Buffer Manager. * * Copyright (C) 2015 Marvell * * Marcin Wojtas <mw@semihalf.com> * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any * warranty of any kind, whether express or implied.
*/
staticvoid mvneta_bm_pool_enable(struct mvneta_bm *priv, int pool_id)
{
u32 val;
val = mvneta_bm_read(priv, MVNETA_BM_POOL_BASE_REG(pool_id));
val |= MVNETA_BM_POOL_ENABLE_MASK;
mvneta_bm_write(priv, MVNETA_BM_POOL_BASE_REG(pool_id), val);
/* Clear BM cause register */
mvneta_bm_write(priv, MVNETA_BM_INTR_CAUSE_REG, 0);
}
staticvoid mvneta_bm_pool_disable(struct mvneta_bm *priv, int pool_id)
{
u32 val;
val = mvneta_bm_read(priv, MVNETA_BM_POOL_BASE_REG(pool_id));
val &= ~MVNETA_BM_POOL_ENABLE_MASK;
mvneta_bm_write(priv, MVNETA_BM_POOL_BASE_REG(pool_id), val);
}
val = mvneta_bm_read(priv, MVNETA_BM_XBAR_POOL_REG(pool_id));
val &= ~MVNETA_BM_TARGET_ID_MASK(pool_id);
val &= ~MVNETA_BM_XBAR_ATTR_MASK(pool_id);
val |= MVNETA_BM_TARGET_ID_VAL(pool_id, target_id);
val |= MVNETA_BM_XBAR_ATTR_VAL(pool_id, attr);
/* In order to update buf_cookie field of RX descriptor properly, * BM hardware expects buf virtual address to be placed in the * first four bytes of mapped buffer.
*/
*(u32 *)buf = (u32)buf;
phys_addr = dma_map_single(&priv->pdev->dev, buf, bm_pool->buf_size,
DMA_FROM_DEVICE); if (unlikely(dma_mapping_error(&priv->pdev->dev, phys_addr))) return -ENOMEM;
/* Notify the driver that BM pool is being used as specific type and return the * pool pointer on success
*/ struct mvneta_bm_pool *mvneta_bm_pool_use(struct mvneta_bm *priv, u8 pool_id, enum mvneta_bm_type type, u8 port_id, int pkt_size)
{ struct mvneta_bm_pool *new_pool = &priv->bm_pools[pool_id]; int num, err;
if (new_pool->type == MVNETA_BM_LONG &&
new_pool->port_map != 1 << port_id) {
dev_err(&priv->pdev->dev, "long pool cannot be shared by the ports\n"); return NULL;
}
if (new_pool->type == MVNETA_BM_SHORT && new_pool->type != type) {
dev_err(&priv->pdev->dev, "mixing pools' types between the ports is forbidden\n"); return NULL;
}
if (new_pool->pkt_size == 0 || type != MVNETA_BM_SHORT)
new_pool->pkt_size = pkt_size;
/* Allocate buffers in case BM pool hasn't been used yet */ if (new_pool->type == MVNETA_BM_FREE) { struct hwbm_pool *hwbm_pool = &new_pool->hwbm_pool;
/* Create new pool */
err = mvneta_bm_pool_create(priv, new_pool); if (err) {
dev_err(&priv->pdev->dev, "fail to create pool %d\n",
new_pool->id); return NULL;
}
/* Allocate buffers for this pool */
num = hwbm_pool_add(hwbm_pool, hwbm_pool->size); if (num != hwbm_pool->size) {
WARN(1, "pool %d: %d of %d allocated\n",
new_pool->id, num, hwbm_pool->size); return NULL;
}
}
/* Activate BM unit */
mvneta_bm_write(priv, MVNETA_BM_COMMAND_REG, MVNETA_BM_START_MASK);
/* Create all pools with maximum size */ for (i = 0; i < MVNETA_BM_POOLS_NUM; i++) {
bm_pool = &priv->bm_pools[i];
bm_pool->id = i;
bm_pool->type = MVNETA_BM_FREE;
/* Mask BM all interrupts */
mvneta_bm_write(priv, MVNETA_BM_INTR_MASK_REG, 0);
/* Clear BM cause register */
mvneta_bm_write(priv, MVNETA_BM_INTR_CAUSE_REG, 0);
/* Set BM configuration register */
val = mvneta_bm_read(priv, MVNETA_BM_CONFIG_REG);
/* Reduce MaxInBurstSize from 32 BPs to 16 BPs */
val &= ~MVNETA_BM_MAX_IN_BURST_SIZE_MASK;
val |= MVNETA_BM_MAX_IN_BURST_SIZE_16BP;
mvneta_bm_write(priv, MVNETA_BM_CONFIG_REG, val);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.