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>
227 lines
6.1 KiB
C
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;
|
|
}
|