| /******************************************************************************* |
| Copyright (C) Marvell International Ltd. and its affiliates |
| |
| This software file (the "File") is owned and distributed by Marvell |
| International Ltd. and/or its affiliates ("Marvell") under the following |
| alternative licensing terms. Once you have made an election to distribute the |
| File under one of the following license alternatives, please (i) delete this |
| introductory statement regarding license alternatives, (ii) delete the two |
| license alternatives that you have not elected to use and (iii) preserve the |
| Marvell copyright notice above. |
| |
| |
| ******************************************************************************** |
| Marvell GPL License Option |
| |
| If you received this File from Marvell, you may opt to use, redistribute and/or |
| modify this File in accordance with the terms and conditions of the General |
| Public License Version 2, June 1991 (the "GPL License"), a copy of which is |
| available along with the File in the license.txt file or by writing to the Free |
| Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or |
| on the worldwide web at http://www.gnu.org/licenses/gpl.txt. |
| |
| THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED |
| WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY |
| DISCLAIMED. The GPL License provides additional details about this warranty |
| disclaimer. |
| *******************************************************************************/ |
| #include <linux/module.h> |
| #include <linux/kernel.h> |
| #include <linux/types.h> |
| #include <linux/capability.h> |
| #include <linux/kernel.h> |
| #include <linux/platform_device.h> |
| |
| #include "gbe/mvNeta.h" |
| #include "bm/mvBm.h" |
| |
| #include "net_dev/mv_netdev.h" |
| |
| static MV_BM_POOL hwfBmPool[MV_BM_POOLS]; |
| |
| |
| static int mv_eth_hwf_pool_add(MV_BM_POOL *pBmPool, int bufNum) |
| { |
| int i; |
| void *pVirt; |
| MV_ULONG physAddr; |
| |
| /* Check total number of buffers doesn't exceed capacity */ |
| if ((bufNum < 0) || |
| ((bufNum + pBmPool->bufNum) > (pBmPool->capacity))) { |
| |
| mvOsPrintf("%s: to many %d buffers for BM pool #%d: capacity=%d, buf_num=%d\n", |
| __func__, bufNum, pBmPool->pool, pBmPool->capacity, pBmPool->bufNum); |
| return 0; |
| } |
| /* Allocate buffers for the pool */ |
| for (i = 0; i < bufNum; i++) { |
| |
| pVirt = mvOsIoCachedMalloc(NULL, pBmPool->bufSize, &physAddr, NULL); |
| if (pVirt == NULL) { |
| mvOsPrintf("%s: Warning! Not all buffers of %d bytes allocated\n", |
| __func__, pBmPool->bufSize); |
| break; |
| } |
| mvBmPoolPut(pBmPool->pool, (MV_ULONG) physAddr); |
| } |
| pBmPool->bufNum += i; |
| |
| mvOsPrintf("BM pool #%d for HWF: bufSize=%4d - %4d of %4d buffers added\n", |
| pBmPool->pool, pBmPool->bufSize, i, bufNum); |
| |
| return i; |
| } |
| |
| /******************************************************************************* |
| * mv_eth_hwf_bm_create - create BM pools used by the port for HWF only |
| * |
| * INPUT: |
| * int port - port number |
| * |
| * RETURN: MV_STATUS |
| * MV_OK - Success, Others - Failure |
| * |
| *******************************************************************************/ |
| MV_STATUS mv_eth_hwf_bm_create(int port, int mtuPktSize) |
| { |
| static bool isFirst = true; |
| MV_BM_POOL *pBmPool; |
| int long_pool, short_pool; |
| int long_buf_size, short_buf_size; |
| |
| /* Check validity of the parameters */ |
| if (mvNetaPortCheck(port)) |
| return MV_FAIL; |
| |
| /* For the first time - clean hwfBmPool array */ |
| if (isFirst == true) { |
| memset(&hwfBmPool, 0, sizeof(hwfBmPool)); |
| isFirst = false; |
| } |
| |
| long_pool = mv_eth_bm_config_long_pool_get(port); |
| /* Check validity of the parameters */ |
| if (mvNetaMaxCheck(long_pool, MV_BM_POOLS)) |
| return MV_FAIL; |
| |
| /* For HWF Packet offset in the packet is 8 bytes */ |
| long_buf_size = mv_eth_bm_config_pkt_size_get(long_pool); |
| if (long_buf_size == 0) |
| long_buf_size = mtuPktSize + 8; |
| |
| /* Check validity of the parameters */ |
| if (long_buf_size < (mtuPktSize + 8)) |
| return MV_FAIL; |
| |
| /* Create long pool */ |
| pBmPool = &hwfBmPool[long_pool]; |
| if (pBmPool->pVirt == NULL) { |
| /* Allocate new pool */ |
| pBmPool->pVirt = mv_eth_bm_pool_create(long_pool, MV_BM_POOL_CAP_MAX, &pBmPool->physAddr); |
| if (pBmPool->pVirt == NULL) { |
| mvOsPrintf("%s: Can't allocate %d bytes for Long pool #%d of port #%d\n", |
| __func__, MV_BM_POOL_CAP_MAX * sizeof(MV_U32), long_pool, port); |
| return MV_OUT_OF_CPU_MEM; |
| } |
| pBmPool->pool = long_pool; |
| pBmPool->capacity = MV_BM_POOL_CAP_MAX; |
| pBmPool->bufSize = long_buf_size; |
| } else { |
| /* Share pool with other port - check buffer size */ |
| if (long_buf_size > pBmPool->bufSize) { |
| /* The BM pool doesn't match the mtuPktSize */ |
| mvOsPrintf("%s: longBufSize=%d is too match for the pool #%d (%d bytes)\n", |
| __func__, long_buf_size, pBmPool->pool, pBmPool->bufSize); |
| return MV_FAIL; |
| } |
| } |
| /* Set long pool buffer size */ |
| mvNetaBmPoolBufSizeSet(port, long_pool, long_buf_size); |
| |
| mv_eth_hwf_pool_add(pBmPool, mv_eth_bm_config_long_buf_num_get(port)); |
| |
| /* Create short pool */ |
| short_pool = mv_eth_bm_config_short_pool_get(port); |
| short_buf_size = mv_eth_bm_config_pkt_size_get(short_pool); |
| if (short_pool != long_pool) { |
| pBmPool = &hwfBmPool[short_pool]; |
| if (pBmPool->pVirt == NULL) { |
| /* Allocate new pool */ |
| pBmPool->pVirt = mv_eth_bm_pool_create(short_pool, MV_BM_POOL_CAP_MAX, &pBmPool->physAddr); |
| if (pBmPool->pVirt == NULL) { |
| mvOsPrintf("%s: Can't allocate %d bytes for Short pool #%d of port #%d\n", |
| __func__, MV_BM_POOL_CAP_MAX * sizeof(MV_U32), short_pool, port); |
| return MV_OUT_OF_CPU_MEM; |
| } |
| pBmPool->pool = short_pool; |
| pBmPool->capacity = MV_BM_POOL_CAP_MAX; |
| pBmPool->bufSize = short_buf_size; |
| } else { |
| /* Share pool with other port - check buffer size */ |
| if (short_buf_size > pBmPool->bufSize) { |
| /* The BM pool doesn't match the mtuPktSize */ |
| mvOsPrintf("%s: shortBufSize=%d is too match for the pool #%d (%d bytes)\n", |
| __func__, short_buf_size, pBmPool->pool, pBmPool->bufSize); |
| return MV_FAIL; |
| } |
| } |
| /* Set short pool buffer size */ |
| mvNetaBmPoolBufSizeSet(port, short_pool, short_buf_size); |
| |
| /* Add buffers to short pool */ |
| mv_eth_hwf_pool_add(pBmPool, mv_eth_bm_config_short_buf_num_get(port)); |
| } |
| mvNetaHwfBmPoolsSet(port, short_pool, long_pool); |
| return MV_OK; |
| } |
| |
| void mv_hwf_bm_dump(void) |
| { |
| int i; |
| MV_BM_POOL *bmPool; |
| |
| mvOsPrintf("HWF BM Pools configuration\n"); |
| mvOsPrintf("pool: capacity bufSize bufNum virtPtr physAddr\n"); |
| for (i = 0; i < MV_BM_POOLS; i++) { |
| bmPool = &hwfBmPool[i]; |
| if (bmPool->pVirt) |
| mvOsPrintf(" %2d: %4d %4d %4d %p 0x%08x\n", |
| bmPool->pool, bmPool->capacity, bmPool->bufSize, bmPool->bufNum, |
| bmPool->pVirt, (unsigned)bmPool->physAddr); |
| } |
| } |
| |