qcacmn: Add QDF wrapper for nbuf frag ops

Introduce qdf wrapper API for nbuf frag based ops.

Change-Id: I0f4c1cb1aa9fcdd9dc2fc2f5716860eb286a1932
CRs-Fixed: 2733972
This commit is contained in:
Ankit Kumar
2020-07-11 14:12:13 +05:30
committed by snandini
parent d7a0b3f14c
commit 2b9e4ba1cb
7 changed files with 473 additions and 0 deletions

View File

@@ -50,6 +50,7 @@ linux/src/qdf_crypto.o \
linux/src/qdf_module.o \
linux/src/qdf_net_if.o \
linux/src/qdf_nbuf.o \
linux/src/qdf_nbuf_frag.o \
linux/src/qdf_perf.o \
linux/src/qdf_status.o \
linux/src/qdf_threads.o \

View File

@@ -3667,6 +3667,86 @@ static inline void qdf_nbuf_orphan(qdf_nbuf_t buf)
return __qdf_nbuf_orphan(buf);
}
/**
* qdf_nbuf_get_frag_size_by_idx() - Get size of nbuf frag at index idx
* @nbuf: qdf_nbuf_t
* @idx: Frag index for which frag size is requested
*
* Return: Frag size
*/
static inline unsigned int qdf_nbuf_get_frag_size_by_idx(qdf_nbuf_t nbuf,
uint8_t idx)
{
return __qdf_nbuf_get_frag_size_by_idx(nbuf, idx);
}
/**
* qdf_nbuf_get_frag_addr() - Get nbuf frag address at index idx
* @nbuf: qdf_nbuf_t
* @idx: Frag index for which frag address is requested
*
* Return: Frag address
*/
static inline qdf_frag_t qdf_nbuf_get_frag_addr(qdf_nbuf_t nbuf, uint8_t idx)
{
return __qdf_nbuf_get_frag_addr(nbuf, idx);
}
/**
* qdf_nbuf_trim_add_frag_size() - Increase/Decrease frag_size by size
* @nbuf: qdf_nbuf_t
* @idx: Frag index
* @size: Size by which frag_size needs to be increased/decreased
* +Ve means increase, -Ve means decrease
* @truesize: truesize
*/
static inline void qdf_nbuf_trim_add_frag_size(qdf_nbuf_t nbuf, uint8_t idx,
int size, unsigned int truesize)
{
__qdf_nbuf_trim_add_frag_size(nbuf, idx, size, truesize);
}
/**
* qdf_nbuf_move_frag_page_offset() - Move frag page_offset by size
* and adjust length by size.
* @nbuf: qdf_nbuf_t
* @idx: Frag index
* @offset: Frag page offset should be moved by offset.
* +Ve - Move offset forward.
* -Ve - Move offset backward.
*/
static inline QDF_STATUS qdf_nbuf_move_frag_page_offset(qdf_nbuf_t nbuf,
uint8_t idx,
int offset)
{
return __qdf_nbuf_move_frag_page_offset(nbuf, idx, offset);
}
/**
* qdf_nbuf_add_rx_frag() - Add frag to nbuf at index frag_idx
* @buf: Frag pointer needs to be added in nbuf frag
* @nbuf: qdf_nbuf_t where frag will be added
* @offset: Offset in frag to be added to nbuf_frags
* @frag_len: Frag length
* @truesize: truesize
* @take_frag_ref: Whether to take ref for frag or not
* This bool must be set as per below comdition:
* 1. False: If this frag is being added in any nbuf
* for the first time after allocation
* 2. True: If frag is already attached part of any
* nbuf
*
* qdf_nbuf_add_rx_frag takes ref_count based on boolean flag take_frag_ref
*/
static inline void qdf_nbuf_add_rx_frag(qdf_frag_t buf, qdf_nbuf_t nbuf,
int offset, int frag_len,
unsigned int truesize,
bool take_frag_ref)
{
__qdf_nbuf_add_rx_frag(buf, nbuf, offset,
frag_len, truesize, take_frag_ref);
}
#ifdef CONFIG_NBUF_AP_PLATFORM
#include <i_qdf_nbuf_api_w.h>
#else

89
qdf/inc/qdf_nbuf_frag.h Normal file
View File

@@ -0,0 +1,89 @@
/*
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/**
* DOC: qdf_nbuf_frag.h
* This file defines the nbuf frag abstraction.
*/
#ifndef _QDF_NBUF_FRAG_H
#define _QDF_NBUF_FRAG_H
#include <i_qdf_trace.h>
#include <i_qdf_nbuf_frag.h>
/*
* typedef qdf_frag_t - Platform independent frag address abstraction
*/
typedef __qdf_frag_t qdf_frag_t;
/**
* Maximum number of frags an SKB can hold
*/
#define QDF_NBUF_MAX_FRAGS __QDF_NBUF_MAX_FRAGS
/**
* qdf_mem_map_page() - Map Page
* @osdev: qdf_device_t
* @buf: Virtual page address to be mapped
* @dir: qdf_dma_dir_t
* @nbytes: Size of memory to be mapped
* @paddr: Corresponding mapped physical address
*
* Return: QDF_STATUS
*/
static inline QDF_STATUS qdf_mem_map_page(qdf_device_t osdev, qdf_frag_t buf,
qdf_dma_dir_t dir, size_t nbytes,
qdf_dma_addr_t *phy_addr)
{
return __qdf_mem_map_page(osdev, buf, dir, nbytes, phy_addr);
}
/**
* qdf_mem_unmap_page() - Unmap Page
* @osdev: qdf_device_t
* @paddr: Physical memory to be unmapped
* @nbytes: Size of memory to be unmapped
* @dir: qdf_dma_dir_t
*/
static inline void qdf_mem_unmap_page(qdf_device_t osdev, qdf_dma_addr_t paddr,
size_t nbytes, qdf_dma_dir_t dir)
{
__qdf_mem_unmap_page(osdev, paddr, nbytes, dir);
}
/**
* qdf_frag_free() - Free allocated frag memory
* @vaddr: Frag address to be freed.
*/
static inline void qdf_frag_free(qdf_frag_t vaddr)
{
__qdf_frag_free(vaddr);
}
/**
* qdf_frag_alloc() - Allocate frag memory
* @fragsz: Size of frag memory to be allocated
*
* Return: Allcated frag address
*/
static inline qdf_frag_t qdf_frag_alloc(unsigned int fragsz)
{
return __qdf_frag_alloc(fragsz);
}
#endif /* _QDF_NBUF_FRAG_H */

View File

@@ -37,6 +37,7 @@
#include <qdf_mem.h>
#include <linux/tcp.h>
#include <qdf_util.h>
#include <qdf_nbuf_frag.h>
/*
* Use socket buffer as the underlying implementation as skbuf .
@@ -2347,6 +2348,89 @@ void __qdf_nbuf_queue_head_unlock(struct sk_buff_head *skb_queue_head)
spin_unlock_bh(&skb_queue_head->lock);
}
/**
* __qdf_nbuf_get_frag_size_by_idx() - Get nbuf frag size at index idx
* @nbuf: qdf_nbuf_t
* @idx: Index for which frag size is requested
*
* Return: Frag size
*/
static inline unsigned int __qdf_nbuf_get_frag_size_by_idx(__qdf_nbuf_t nbuf,
uint8_t idx)
{
unsigned int size = 0;
if (likely(idx < __QDF_NBUF_MAX_FRAGS))
size = skb_frag_size(&skb_shinfo(nbuf)->frags[idx]);
return size;
}
/**
* __qdf_nbuf_get_frag_address() - Get nbuf frag address at index idx
* @nbuf: qdf_nbuf_t
* @idx: Index for which frag address is requested
*
* Return: Frag address in success, else NULL
*/
static inline __qdf_frag_t __qdf_nbuf_get_frag_addr(__qdf_nbuf_t nbuf,
uint8_t idx)
{
__qdf_frag_t frag_addr = NULL;
if (likely(idx < __QDF_NBUF_MAX_FRAGS))
frag_addr = skb_frag_address(&skb_shinfo(nbuf)->frags[idx]);
return frag_addr;
}
/**
* __qdf_nbuf_trim_add_frag_size() - Increase/Decrease frag_size by size
* @nbuf: qdf_nbuf_t
* @idx: Frag index
* @size: Size by which frag_size needs to be increased/decreased
* +Ve means increase, -Ve means decrease
* @truesize: truesize
*/
static inline void __qdf_nbuf_trim_add_frag_size(__qdf_nbuf_t nbuf, uint8_t idx,
int size,
unsigned int truesize)
{
skb_coalesce_rx_frag(nbuf, idx, size, truesize);
}
/**
* __qdf_nbuf_move_frag_page_offset() - Move frag page_offset by size
* and adjust length by size.
* @nbuf: qdf_nbuf_t
* @idx: Frag index
* @offset: Frag page offset should be moved by offset.
* +Ve - Move offset forward.
* -Ve - Move offset backward.
*
* Return: QDF_STATUS
*/
QDF_STATUS __qdf_nbuf_move_frag_page_offset(__qdf_nbuf_t nbuf, uint8_t idx,
int offset);
/**
* __qdf_nbuf_add_rx_frag() - Add frag to nbuf at nr_frag index
* @buf: Frag pointer needs to be added in nbuf frag
* @nbuf: qdf_nbuf_t where frag will be added
* @offset: Offset in frag to be added to nbuf_frags
* @frag_len: Frag length
* @truesize: truesize
* @take_frag_ref: Whether to take ref for frag or not
* This bool must be set as per below comdition:
* 1. False: If this frag is being added in any nbuf
* for the first time after allocation.
* 2. True: If frag is already attached part of any
* nbuf.
*
* It takes ref_count based on boolean flag take_frag_ref
*/
void __qdf_nbuf_add_rx_frag(__qdf_frag_t buf, __qdf_nbuf_t nbuf,
int offset, int frag_len,
unsigned int truesize, bool take_frag_ref);
#ifdef CONFIG_NBUF_AP_PLATFORM
#include <i_qdf_nbuf_w.h>
#else

View File

@@ -0,0 +1,83 @@
/*
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/**
* DOC: i_qdf_nbuf_frag.h
* This file provides OS dependent nbuf frag API's.
*/
#ifndef _I_QDF_NBUF_FRAG_H
#define _I_QDF_NBUF_FRAG_H
#include <qdf_net_types.h>
#include <qdf_mem.h>
/**
* typedef __qdf_frag_t - Abstraction for void * for frag address
*/
typedef void *__qdf_frag_t;
/**
* Maximum number of frags an SKB can hold
*/
#define __QDF_NBUF_MAX_FRAGS MAX_SKB_FRAGS
/**
* __qdf_mem_unmap_page() - Unmap frag memory
* @osdev: qdf_device_t
* @paddr: Address to be unmapped
* @nbytes: Number of bytes to be unmapped
* @dir: qdf_dma_dir_t
*/
void __qdf_mem_unmap_page(qdf_device_t osdev, qdf_dma_addr_t paddr,
size_t nbytes, qdf_dma_dir_t dir);
/**
* __qdf_mem_map_page() - Map frag memory
* @osdev: qdf_device_t
* @buf: Vaddr to be mapped
* @dir: qdf_dma_dir_t
* @nbytes: Number of bytes to be mapped
* @paddr: Mapped physical address
*
* Return: QDF_STATUS
*/
QDF_STATUS __qdf_mem_map_page(qdf_device_t osdev, __qdf_frag_t buf,
qdf_dma_dir_t dir, size_t nbytes,
qdf_dma_addr_t *phy_addr);
/**
* __qdf_frag_free() - Free allocated frag memory
* @vaddr: Frag address to be freed
*/
static inline void __qdf_frag_free(__qdf_frag_t vaddr)
{
skb_free_frag(vaddr);
}
/**
* __qdf_frag_alloc() - Allocate frag Memory
* @fragsz: Size of frag memory to be allocated
*
* Return: Allocated frag addr.
*/
static inline __qdf_frag_t __qdf_frag_alloc(unsigned int fragsz)
{
return netdev_alloc_frag(fragsz);
}
#endif /* _I_QDF_NBUF_FRAG_H */

View File

@@ -4574,3 +4574,71 @@ void __qdf_nbuf_mod_exit(void)
{
}
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
QDF_STATUS __qdf_nbuf_move_frag_page_offset(__qdf_nbuf_t nbuf, uint8_t idx,
int offset)
{
unsigned int frag_offset;
skb_frag_t *frag;
if (qdf_unlikely(idx >= __qdf_nbuf_get_nr_frags(nbuf)))
return QDF_STATUS_E_FAILURE;
frag = &skb_shinfo(nbuf)->frags[idx];
frag_offset = skb_frag_off(frag);
frag_offset += offset;
skb_frag_off_set(frag, frag_offset);
__qdf_nbuf_trim_add_frag_size(nbuf, idx, -(offset), 0);
return QDF_STATUS_SUCCESS;
}
#else
QDF_STATUS __qdf_nbuf_move_frag_page_offset(__qdf_nbuf_t nbuf, uint8_t idx,
int offset)
{
uint16_t frag_offset;
skb_frag_t *frag;
if (qdf_unlikely(idx >= __qdf_nbuf_get_nr_frags(nbuf)))
return QDF_STATUS_E_FAILURE;
frag = &skb_shinfo(nbuf)->frags[idx];
frag_offset = frag->page_offset;
frag_offset += offset;
frag->page_offset = frag_offset;
__qdf_nbuf_trim_add_frag_size(nbuf, idx, -(offset), 0);
return QDF_STATUS_SUCCESS;
}
#endif
qdf_export_symbol(__qdf_nbuf_move_frag_page_offset);
void __qdf_nbuf_add_rx_frag(__qdf_frag_t buf, __qdf_nbuf_t nbuf,
int offset, int frag_len,
unsigned int truesize, bool take_frag_ref)
{
struct page *page;
int frag_offset;
uint8_t nr_frag;
nr_frag = __qdf_nbuf_get_nr_frags(nbuf);
page = virt_to_head_page(buf);
frag_offset = buf - page_address(page);
skb_add_rx_frag(nbuf, nr_frag, page,
(frag_offset + offset),
frag_len, truesize);
if (unlikely(take_frag_ref))
skb_frag_ref(nbuf, nr_frag);
}
qdf_export_symbol(__qdf_nbuf_add_rx_frag);

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/**
* DOC: qdf_nbuf_frag.c
* QCA driver framework(QDF) network nbuf frag management APIs
*/
#include <qdf_module.h>
#include <qdf_nbuf_frag.h>
#if defined(HIF_PCI)
QDF_STATUS __qdf_mem_map_page(qdf_device_t osdev, __qdf_frag_t buf,
qdf_dma_dir_t dir, size_t nbytes,
qdf_dma_addr_t *phy_addr)
{
struct page *page;
unsigned long offset;
page = virt_to_head_page(buf);
offset = buf - page_address(page);
*phy_addr = dma_map_page(osdev->dev, page, offset, nbytes,
__qdf_dma_dir_to_os(dir));
return dma_mapping_error(osdev->dev, *phy_addr) ?
QDF_STATUS_E_FAILURE : QDF_STATUS_SUCCESS;
}
#else
QDF_STATUS __qdf_mem_map_page(qdf_device_t osdev, __qdf_frag_t buf,
qdf_dma_dir_t dir, size_t nbytes,
qdf_dma_addr_t *phy_addr)
{
return QDF_STATUS_SUCCESS;
}
#endif
qdf_export_symbol(__qdf_mem_map_page);
#if defined(HIF_PCI)
void __qdf_mem_unmap_page(qdf_device_t osdev, qdf_dma_addr_t paddr,
size_t nbytes, qdf_dma_dir_t dir)
{
dma_unmap_page(osdev->dev, paddr, nbytes,
__qdf_dma_dir_to_os(dir));
}
#else
void __qdf_mem_unmap_page(qdf_device_t osdev, qdf_dma_addr_t paddr,
size_t nbytes, qdf_dma_dir_t dir)
{
}
#endif
qdf_export_symbol(__qdf_mem_unmap_page);