luckfox-pico-sdk/sysdrv/drv_ko/wifi/ssv6115/utils/pre_alloc_skb.c
luckfox-eng29 8f34c2760d project:build.sh: Added fastboot support; custom modifications to U-Boot and kernel implemented using patches.
project:cfg:BoardConfig_IPC: Added fastboot BoardConfig file and firmware post-scripts, distinguishing between
the BoardConfigs for Luckfox Pico Pro and Luckfox Pico Max. project:app: Added fastboot_client and rk_smart_door
for quick boot applications; updated rkipc app to adapt to the latest media library. media:samples: Added more
usage examples. media:rockit: Fixed bugs; removed support for retrieving data frames from VPSS. media:isp:
Updated rkaiq library and related tools to support connection to RKISP_Tuner. sysdrv:Makefile: Added support for
compiling drv_ko on Luckfox Pico Ultra W using Ubuntu; added support for custom root filesystem.
sysdrv:tools:board: Updated Buildroot optional mirror sources, updated some software versions, and stored device
tree files and configuration files that undergo multiple modifications for U-Boot and kernel separately.
sysdrv:source:mcu: Used RISC-V MCU SDK with RT-Thread system, mainly for initializing camera AE during quick
boot. sysdrv:source:uboot: Added support for fastboot; added high baud rate DDR bin for serial firmware upgrades.
sysdrv:source:kernel: Upgraded to version 5.10.160; increased NPU frequency for RV1106G3; added support for
fastboot.

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>
2024-10-14 09:47:04 +08:00

227 lines
6.1 KiB
C

#include <linux/version.h>
#include <linux/module.h>
#include <linux/vmalloc.h>
#include <linux/skbuff.h>
#include <linux/pm_runtime.h>
#include "hwif/hwif.h"
#include "hci/ssv_hci.h"
#include "hci/hctrl.h"
#include "pre_alloc_skb.h"
#include "ssv_debug.h"
static bool ssv_is_pre_rx_skb(struct ssv_pre_alloc *pre_alloc, struct sk_buff *skb)
{
int i = 0;
int q_len = pre_alloc->total_pre_rx_skb_q_len;
struct sk_buff **skb_list = pre_alloc->pre_rx_skb_list;
if (q_len > 0) {
for (i = q_len - 1; i >= 0; i--) {
if (skb == *(skb_list + i))
return true;
}
}
return false;
}
struct sk_buff *ssv_pre_rx_skb_alloc(struct ssv_pre_alloc *pre_alloc)
{
struct sk_buff *skb = NULL;
int use_skb_q_len = 0;
if (NULL == pre_alloc) {
SSV_LOG_DBG("%s: Parameter is invalid!\n", __func__);
return NULL;
}
skb = skb_dequeue_tail(&pre_alloc->pre_rx_skb_q);
use_skb_q_len = pre_alloc->total_pre_rx_skb_q_len - skb_queue_len(&pre_alloc->pre_rx_skb_q);
if (use_skb_q_len > pre_alloc->max_running_pre_rx_skb_q_len)
pre_alloc->max_running_pre_rx_skb_q_len = use_skb_q_len;
return skb;
}
int ssv_pre_rx_skb_free(struct ssv_pre_alloc *pre_alloc, struct sk_buff *skb)
{
struct skb_shared_info *s = skb_shinfo(skb);
if ((NULL == pre_alloc) || (NULL == skb)) {
SSV_LOG_DBG("%s: Parameter is invalid!\n", __func__);
return -EINVAL;
}
if (false == ssv_is_pre_rx_skb(pre_alloc, skb))
return -EFAULT;
// reset skb
memset(s, 0, offsetof(struct skb_shared_info, dataref));
atomic_set(&s->dataref, 1);
memset(skb, 0, offsetof(struct sk_buff, tail));
skb_reset_tail_pointer(skb);
// enqueue rxq
skb_queue_tail(&pre_alloc->pre_rx_skb_q, skb);
return 0;
}
int ssv_pre_rx_skb_free_all(struct ssv_pre_alloc *pre_alloc)
{
int i = 0, total_q_len = 0, q_len = 0;
struct sk_buff *skb = NULL;
if (NULL == pre_alloc) {
SSV_LOG_DBG("%s: Parameter is invalid!\n", __func__);
return -EINVAL;
}
q_len = skb_queue_len(&pre_alloc->pre_rx_skb_q);
total_q_len = pre_alloc->total_pre_rx_skb_q_len;
if (total_q_len > q_len) {
for (i = 0; i < q_len; i++)
skb_dequeue(&pre_alloc->pre_rx_skb_q);
for (i = 0; i < total_q_len; i++) {
skb = *(pre_alloc->pre_rx_skb_list + i);
ssv_pre_rx_skb_free(pre_alloc, skb);
}
}
return 0;
}
int ssv_pre_rx_skb_init(struct ssv_pre_alloc *pre_alloc, int rx_threshold)
{
int i = 0;
struct sk_buff *skb = NULL;
SSV_LOG_DBG("%s\n", __func__);
if (NULL == pre_alloc) {
SSV_LOG_DBG("%s: Parameter is invalid!\n", __func__);
return -EINVAL;
}
if (rx_threshold > 0) {
// create a list to record each pre alloc skb
pre_alloc->pre_rx_skb_list = kmalloc(rx_threshold * sizeof(struct sk_buff *), GFP_KERNEL);
if (NULL == pre_alloc->pre_rx_skb_list)
return -ENOMEM;
memset(pre_alloc->pre_rx_skb_list, 0, rx_threshold * sizeof(struct sk_buff *));
skb_queue_head_init(&pre_alloc->pre_rx_skb_q);
pre_alloc->max_running_pre_rx_skb_q_len = 0;
// pre alloc rx skb for hci rx aggr frame
for (i = 0; i < rx_threshold; i++) {
skb = __dev_alloc_skb(MAX_HCI_RX_AGGR_SIZE+PLATFORM_DEF_DMA_ALIGN_SIZE-1, GFP_KERNEL);
if (NULL == skb)
break;
skb_queue_tail(&pre_alloc->pre_rx_skb_q, skb);
*(pre_alloc->pre_rx_skb_list + i) = skb;
}
pre_alloc->total_pre_rx_skb_q_len = skb_queue_len(&pre_alloc->pre_rx_skb_q);
SSV_LOG_DBG("alloc %d rx skb_buff\n", pre_alloc->total_pre_rx_skb_q_len);
if (pre_alloc->total_pre_rx_skb_q_len != rx_threshold) {
BUG_ON(1);
}
}
return 0;
}
int ssv_pre_rx_skb_deinit(struct ssv_pre_alloc *pre_alloc)
{
int i = 0;
struct sk_buff *skb = NULL;
u32 q_len = 0;
SSV_LOG_DBG("%s\n", __func__);
if (NULL == pre_alloc) {
SSV_LOG_DBG("%s: Parameter is invalid!\n", __func__);
return -EINVAL;
}
q_len = pre_alloc->total_pre_rx_skb_q_len;
if (pre_alloc->pre_rx_skb_list) {
for (i = 0; i < q_len; i++) {
skb = *(pre_alloc->pre_rx_skb_list + i);
if (skb != NULL)
dev_kfree_skb_any(skb);
}
kfree(pre_alloc->pre_rx_skb_list);
}
SSV_LOG_DBG("max_running: %u\n", pre_alloc->max_running_pre_rx_skb_q_len);
return 0;
}
struct sk_buff *ssv_pre_tx_skb_alloc(struct ssv_pre_alloc *pre_alloc)
{
struct sk_buff *skb = NULL;
if (NULL == pre_alloc) {
SSV_LOG_DBG("%s: Parameter is invalid!\n", __func__);
return NULL;
}
skb = pre_alloc->pre_tx_skb;
return skb;
}
int ssv_pre_tx_skb_free(struct ssv_pre_alloc *pre_alloc, struct sk_buff *skb)
{
struct skb_shared_info *s = skb_shinfo(skb);
if ((NULL == pre_alloc) || (skb == NULL)) {
SSV_LOG_DBG("%s: Parameter is invalid!\n", __func__);
return -EINVAL;
}
if (skb == pre_alloc->pre_tx_skb) {
// reset skb
memset(s, 0, offsetof(struct skb_shared_info, dataref));
atomic_set(&s->dataref, 1);
memset(skb, 0, offsetof(struct sk_buff, tail));
skb_reset_tail_pointer(skb);
}
return 0;
}
int ssv_pre_tx_skb_init(struct ssv_pre_alloc *pre_alloc)
{
SSV_LOG_DBG("%s\n", __func__);
if (NULL == pre_alloc) {
SSV_LOG_DBG("%s: Parameter is invalid!\n", __func__);
return -EINVAL;
}
pre_alloc->pre_tx_skb = __dev_alloc_skb(HCI_TX_AGGR_SKB_LEN+PLATFORM_DEF_DMA_ALIGN_SIZE-1, GFP_KERNEL);
if (NULL == pre_alloc->pre_tx_skb) {
SSV_LOG_DBG("%s: Pre-alloc tx skb error!\n", __func__);
return -ENOMEM;
}
return 0;
}
int ssv_pre_tx_skb_deinit(struct ssv_pre_alloc *pre_alloc)
{
SSV_LOG_DBG("%s\n", __func__);
if (NULL == pre_alloc) {
SSV_LOG_DBG("%s: Parameter is invalid!\n", __func__);
return -EINVAL;
}
if (NULL != pre_alloc->pre_tx_skb) {
dev_kfree_skb_any(pre_alloc->pre_tx_skb);
pre_alloc->pre_tx_skb = NULL;
}
return 0;
}