Sfoglia il codice sorgente

qcacmn: Add QDF wrapper for nbuf frag ops

Introduce qdf wrapper API for nbuf frag based ops.

Change-Id: I0f4c1cb1aa9fcdd9dc2fc2f5716860eb286a1932
CRs-Fixed: 2733972
Ankit Kumar 5 anni fa
parent
commit
2b9e4ba1cb

+ 1 - 0
qdf/Kbuild

@@ -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     \

+ 80 - 0
qdf/inc/qdf_nbuf.h

@@ -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 - 0
qdf/inc/qdf_nbuf_frag.h

@@ -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 */

+ 84 - 0
qdf/linux/src/i_qdf_nbuf.h

@@ -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

+ 83 - 0
qdf/linux/src/i_qdf_nbuf_frag.h

@@ -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 */

+ 68 - 0
qdf/linux/src/qdf_nbuf.c

@@ -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);

+ 68 - 0
qdf/linux/src/qdf_nbuf_frag.c

@@ -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);