mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-14 08:36:12 -04:00
msm: veth_ipa: Add VETH IPA driver
Add VETH IPA driver for msmnile gvmr. Change-Id: I602d2d56d7213923ade51a47c965149e4969fac9 Acked-by: Sarosh Hasan <sarohasa@codeaurora.org> Signed-off-by: Akshay Pandit <pandit@codeaurora.org>
This commit is contained in:
parent
08db65b8bf
commit
fe26c474b7
7 changed files with 3791 additions and 0 deletions
|
|
@ -96,6 +96,14 @@ config IPA_WDI_UNIFIED_API
|
|||
The IPA WDI unified API supports all WDI versions through a unified
|
||||
interface.
|
||||
|
||||
config VETH_IPA
|
||||
tristate "VETH_IPA Network Interface Driver Support"
|
||||
help
|
||||
Enables EMAC Ethernet Front end driver.
|
||||
Register net device and configure VETH0 iface. This driver will
|
||||
configure EMAC IPA offload channels with help of a backend driver
|
||||
running on GVM Host.
|
||||
|
||||
config USB_BAM
|
||||
tristate "USB BAM Driver"
|
||||
depends on SPS && USB_GADGET
|
||||
|
|
|
|||
|
|
@ -14,3 +14,4 @@ obj-$(CONFIG_MSM_11AD) += msm_11ad/
|
|||
obj-$(CONFIG_EP_PCIE) += ep_pcie/
|
||||
obj-$(CONFIG_MSM_MHI_DEV) += mhi_dev/
|
||||
obj-$(CONFIG_IPA_ETH) += ethernet/
|
||||
obj-$(CONFIG_VETH_IPA) += veth_ipa/
|
||||
|
|
|
|||
3
drivers/platform/msm/veth_ipa/Makefile
Normal file
3
drivers/platform/msm/veth_ipa/Makefile
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
obj-$(CONFIG_VETH_IPA) += veth_emac_mgt.o veth_ipa.o
|
||||
891
drivers/platform/msm/veth_ipa/veth_emac_mgt.c
Normal file
891
drivers/platform/msm/veth_ipa/veth_emac_mgt.c
Normal file
|
|
@ -0,0 +1,891 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/ipa_uc_offload.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/msm_ipa.h>
|
||||
#include <linux/habmm.h>
|
||||
#include <linux/habmmid.h>
|
||||
#include "veth_emac_mgt.h"
|
||||
#include "veth_ipa.h"
|
||||
|
||||
#define NO_FLAGS 0x0
|
||||
|
||||
/** veth_alloc_emac_export_mem() - Called when allocating the
|
||||
* exported memory to the BE driver.
|
||||
* @veth_emac_mem: Consists of all the export memory and
|
||||
* physical addresses of the exported memory
|
||||
* @pdata : Consists of other net device information
|
||||
* This API is mainly used to allocate the required memory
|
||||
* for the BE driver on the QNX host side
|
||||
*/
|
||||
int veth_alloc_emac_export_mem(
|
||||
struct veth_emac_export_mem *veth_emac_mem, struct veth_ipa_dev *pdata)
|
||||
{
|
||||
phys_addr_t tx_desc_mem_paddr;
|
||||
phys_addr_t rx_desc_mem_paddr;
|
||||
phys_addr_t tx_buf_mem_paddr;
|
||||
phys_addr_t rx_buf_mem_paddr;
|
||||
phys_addr_t tx_buf_pool_paddr;
|
||||
phys_addr_t rx_buf_pool_paddr;
|
||||
|
||||
int i = 0;
|
||||
|
||||
VETH_IPA_DEBUG("%s - begin %p, %p\n", __func__, pdata, veth_emac_mem);
|
||||
/* Allocate TX DESC */
|
||||
veth_emac_mem->tx_desc_mem_va = dma_alloc_coherent(&pdata->pdev->dev,
|
||||
sizeof(struct s_TX_NORMAL_DESC) * VETH_TX_DESC_CNT,
|
||||
&tx_desc_mem_paddr,
|
||||
GFP_KERNEL | GFP_DMA);
|
||||
|
||||
if (!veth_emac_mem->tx_desc_mem_va) {
|
||||
VETH_IPA_DEBUG("%s: No memory\n", __func__);
|
||||
goto free_tx_desc_mem_va;
|
||||
//return -ENOMEM;
|
||||
}
|
||||
|
||||
veth_emac_mem->tx_desc_mem_paddr = tx_desc_mem_paddr;
|
||||
|
||||
VETH_IPA_DEBUG("%s: TX desc base mem allocated %p\n",
|
||||
__func__, veth_emac_mem->tx_desc_mem_va);
|
||||
VETH_IPA_DEBUG("%s: physical addr: tx desc mem 0x%x\n",
|
||||
__func__, veth_emac_mem->tx_desc_mem_paddr);
|
||||
|
||||
for (i = 0; i < VETH_TX_DESC_CNT; i++) {
|
||||
veth_emac_mem->tx_desc_ring_base[i] =
|
||||
veth_emac_mem->tx_desc_mem_paddr +
|
||||
(i * sizeof(struct s_TX_NORMAL_DESC));
|
||||
VETH_IPA_DEBUG(
|
||||
"%s: veth_emac_mem->tx_desc_ring_base [i] 0x%x\n",
|
||||
__func__, i, veth_emac_mem->tx_desc_ring_base[i]);
|
||||
}
|
||||
//Allocate RX DESC
|
||||
veth_emac_mem->rx_desc_mem_va = dma_alloc_coherent(&pdata->pdev->dev,
|
||||
sizeof(struct s_RX_NORMAL_DESC) * VETH_RX_DESC_CNT,
|
||||
&rx_desc_mem_paddr,
|
||||
GFP_KERNEL | GFP_DMA);
|
||||
|
||||
if (!veth_emac_mem->rx_desc_mem_va) {
|
||||
VETH_IPA_DEBUG("%s: No memory\n", __func__);
|
||||
goto free_rx_desc_mem_va;
|
||||
}
|
||||
|
||||
VETH_IPA_DEBUG("%s: RX desc mem allocated %p\n",
|
||||
__func__, veth_emac_mem->rx_desc_mem_va);
|
||||
veth_emac_mem->rx_desc_mem_paddr = rx_desc_mem_paddr;
|
||||
|
||||
for (i = 0; i < VETH_RX_DESC_CNT; i++) {
|
||||
veth_emac_mem->rx_desc_ring_base[i] =
|
||||
veth_emac_mem->rx_desc_mem_paddr +
|
||||
(i * sizeof(struct s_RX_NORMAL_DESC));
|
||||
VETH_IPA_DEBUG(
|
||||
"%s: veth_emac_mem->rx_desc_ring_base [i] 0x%x\n",
|
||||
__func__, i, veth_emac_mem->rx_desc_ring_base[i]);
|
||||
}
|
||||
|
||||
VETH_IPA_DEBUG("%s: physical addr: rx desc mem 0x%x\n",
|
||||
__func__, veth_emac_mem->rx_desc_mem_paddr);
|
||||
|
||||
//Allocate TX Buffers
|
||||
veth_emac_mem->tx_buf_mem_va = dma_alloc_coherent(&pdata->pdev->dev,
|
||||
VETH_ETH_FRAME_LEN_IPA * VETH_TX_DESC_CNT,
|
||||
&tx_buf_mem_paddr,
|
||||
GFP_KERNEL | GFP_DMA);
|
||||
|
||||
if (!veth_emac_mem->tx_buf_mem_va) {
|
||||
VETH_IPA_DEBUG("%s: No memory\n", __func__);
|
||||
goto free_tx_buf_mem_va;
|
||||
}
|
||||
|
||||
veth_emac_mem->tx_buf_mem_paddr = tx_buf_mem_paddr;
|
||||
|
||||
VETH_IPA_DEBUG("%s: TX buf mem allocated %p\n",
|
||||
__func__, veth_emac_mem->tx_buf_mem_va);
|
||||
VETH_IPA_DEBUG("%s: physical addr: tx buf mem 0x%x\n",
|
||||
__func__, veth_emac_mem->tx_buf_mem_paddr);
|
||||
|
||||
/*transport minimum 4k*/
|
||||
veth_emac_mem->tx_buff_pool_base_va = dma_alloc_coherent(&pdata->pdev->dev,
|
||||
sizeof(uint32_t) * (VETH_TX_DESC_CNT * 4),
|
||||
&tx_buf_pool_paddr,
|
||||
GFP_KERNEL | GFP_DMA);
|
||||
|
||||
if (!veth_emac_mem->tx_buff_pool_base_va) {
|
||||
VETH_IPA_DEBUG("%s: No memory for rx_buf_mem_va\n", __func__);
|
||||
goto free_tx_buff_pool_base;
|
||||
}
|
||||
|
||||
veth_emac_mem->tx_buff_pool_base_pa = tx_buf_pool_paddr;
|
||||
|
||||
//Allocate RX buffers
|
||||
veth_emac_mem->rx_buf_mem_va = dma_alloc_coherent(&pdata->pdev->dev,
|
||||
VETH_ETH_FRAME_LEN_IPA * VETH_RX_DESC_CNT,
|
||||
&rx_buf_mem_paddr,
|
||||
GFP_KERNEL | GFP_DMA);
|
||||
|
||||
|
||||
if (!veth_emac_mem->rx_buf_mem_va) {
|
||||
VETH_IPA_DEBUG("%s: No memory for rx_buf_mem_va\n", __func__);
|
||||
goto free_rx_buf_mem_va;
|
||||
}
|
||||
|
||||
veth_emac_mem->rx_buf_mem_paddr = rx_buf_mem_paddr;
|
||||
|
||||
VETH_IPA_DEBUG("%s: RX buf mem allocated %p\n",
|
||||
__func__, veth_emac_mem->rx_buf_mem_va);
|
||||
VETH_IPA_DEBUG("%s: physical addr: rx_buf_mem_addr 0x%x\n",
|
||||
__func__, veth_emac_mem->rx_buf_mem_paddr);
|
||||
|
||||
veth_emac_mem->rx_buff_pool_base_va = dma_alloc_coherent(&pdata->pdev->dev,
|
||||
sizeof(uint32_t) * VETH_RX_DESC_CNT*4,
|
||||
&rx_buf_pool_paddr,
|
||||
GFP_KERNEL | GFP_DMA | __GFP_ZERO);
|
||||
|
||||
if (!veth_emac_mem->rx_buff_pool_base_va) {
|
||||
VETH_IPA_DEBUG("%s: No memory for rx_buf_mem_va\n", __func__);
|
||||
goto free_rx_buff_pool_base;
|
||||
}
|
||||
veth_emac_mem->rx_buff_pool_base_pa = rx_buf_pool_paddr;
|
||||
return 0;
|
||||
|
||||
|
||||
|
||||
free_rx_buff_pool_base:
|
||||
dma_free_coherent(&pdata->pdev->dev,
|
||||
VETH_ETH_FRAME_LEN_IPA * VETH_RX_DESC_CNT,
|
||||
veth_emac_mem->rx_buff_pool_base_va,
|
||||
rx_buf_pool_paddr);
|
||||
free_rx_buf_mem_va:
|
||||
dma_free_coherent(&pdata->pdev->dev,
|
||||
VETH_ETH_FRAME_LEN_IPA * VETH_RX_DESC_CNT,
|
||||
veth_emac_mem->rx_buf_mem_va,
|
||||
rx_buf_mem_paddr);
|
||||
free_tx_buff_pool_base:
|
||||
dma_free_coherent(&pdata->pdev->dev,
|
||||
sizeof(uint32_t) * VETH_TX_DESC_CNT,
|
||||
veth_emac_mem->tx_buff_pool_base_va,
|
||||
tx_buf_pool_paddr);
|
||||
free_tx_buf_mem_va:
|
||||
dma_free_coherent(&pdata->pdev->dev,
|
||||
VETH_ETH_FRAME_LEN_IPA * VETH_TX_DESC_CNT,
|
||||
veth_emac_mem->tx_buf_mem_va,
|
||||
tx_buf_mem_paddr);
|
||||
free_rx_desc_mem_va:
|
||||
dma_free_coherent(&pdata->pdev->dev,
|
||||
sizeof(struct s_RX_NORMAL_DESC) * VETH_RX_DESC_CNT,
|
||||
veth_emac_mem->rx_desc_mem_va,
|
||||
rx_desc_mem_paddr);
|
||||
|
||||
free_tx_desc_mem_va:
|
||||
dma_free_coherent(&pdata->pdev->dev,
|
||||
sizeof(struct s_TX_NORMAL_DESC) * VETH_TX_DESC_CNT,
|
||||
veth_emac_mem->tx_desc_mem_va,
|
||||
tx_desc_mem_paddr);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/** veth_dealloc_emac_export_mem() - Called when deallocating
|
||||
* the exported memory to the BE driver.
|
||||
* @veth_emac_mem: Consists of all the export memory and
|
||||
* physical addresses of the exported memory
|
||||
* @pdata : Consists of other net device information
|
||||
*
|
||||
* This API is mainly used to free the memory from DDR space
|
||||
* during DOWN, CARRIER_DOWN, LPM or unmount event
|
||||
*/
|
||||
int veth_alloc_emac_dealloc_mem(
|
||||
struct veth_emac_export_mem *veth_emac_mem, struct veth_ipa_dev *pdata)
|
||||
{
|
||||
/*1. Send stop offload to the BE
|
||||
*2. Receive from BE
|
||||
*4. Free the memory
|
||||
*5. Close the HAB socket ?
|
||||
*/
|
||||
|
||||
if (veth_emac_mem->rx_buf_mem_va) {
|
||||
VETH_IPA_DEBUG("%s: Freeing RX buf mem", __func__);
|
||||
dma_free_coherent(&pdata->pdev->dev,
|
||||
VETH_ETH_FRAME_LEN_IPA * VETH_RX_DESC_CNT,
|
||||
veth_emac_mem->rx_buf_mem_va,
|
||||
veth_emac_mem->rx_buf_mem_paddr);
|
||||
} else {
|
||||
VETH_IPA_ERROR("%s: RX buf not available", __func__);
|
||||
}
|
||||
|
||||
if (veth_emac_mem->tx_buf_mem_va) {
|
||||
VETH_IPA_DEBUG("%s: Freeing TX buf mem", __func__);
|
||||
dma_free_coherent(&pdata->pdev->dev,
|
||||
VETH_ETH_FRAME_LEN_IPA * VETH_TX_DESC_CNT,
|
||||
veth_emac_mem->tx_buf_mem_va,
|
||||
veth_emac_mem->tx_buf_mem_paddr);
|
||||
} else {
|
||||
VETH_IPA_ERROR("%s: TX buf not available", __func__);
|
||||
}
|
||||
|
||||
if (veth_emac_mem->rx_desc_mem_va) {
|
||||
VETH_IPA_DEBUG("%s: Freeing RX desc mem", __func__);
|
||||
dma_free_coherent(&pdata->pdev->dev,
|
||||
sizeof(struct s_TX_NORMAL_DESC) * VETH_TX_DESC_CNT,
|
||||
veth_emac_mem->rx_desc_mem_va,
|
||||
veth_emac_mem->rx_desc_mem_paddr);
|
||||
} else {
|
||||
VETH_IPA_ERROR("%s: RX desc mem not available", __func__);
|
||||
}
|
||||
|
||||
if (veth_emac_mem->tx_desc_mem_va) {
|
||||
VETH_IPA_DEBUG("%s: Freeing TX desc mem", __func__);
|
||||
dma_free_coherent(&pdata->pdev->dev,
|
||||
sizeof(struct s_RX_NORMAL_DESC) * VETH_RX_DESC_CNT,
|
||||
veth_emac_mem->tx_desc_mem_va,
|
||||
veth_emac_mem->tx_desc_mem_paddr);
|
||||
} else {
|
||||
VETH_IPA_ERROR("%s: TX desc mem not available", __func__);
|
||||
}
|
||||
|
||||
if (veth_emac_mem->rx_buff_pool_base_va) {
|
||||
VETH_IPA_DEBUG("%s: Freeing RX buff pool mem", __func__);
|
||||
dma_free_coherent(&pdata->pdev->dev,
|
||||
sizeof(uint32_t) * VETH_RX_DESC_CNT,
|
||||
veth_emac_mem->rx_buff_pool_base_va,
|
||||
veth_emac_mem->rx_buff_pool_base_pa);
|
||||
} else {
|
||||
VETH_IPA_ERROR("%s: RX buff pool base not available", __func__);
|
||||
}
|
||||
|
||||
if (veth_emac_mem->tx_buff_pool_base_va) {
|
||||
VETH_IPA_DEBUG("%s: Freeing TX buff pool mem", __func__);
|
||||
dma_free_coherent(&pdata->pdev->dev,
|
||||
sizeof(uint32_t) * VETH_TX_DESC_CNT,
|
||||
veth_emac_mem->tx_buff_pool_base_va,
|
||||
veth_emac_mem->tx_buff_pool_base_pa);
|
||||
} else {
|
||||
VETH_IPA_ERROR("%s: TX buff pool base not available", __func__);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** veth_emac_ipa_hab_init() - This is called in the initial
|
||||
* HAB init state where the BE and FE driver establish HAB
|
||||
* communixation
|
||||
* @mmid: This provides the physical channel used for HAB
|
||||
* communication
|
||||
*
|
||||
*/
|
||||
int veth_emac_ipa_hab_init(int mmid)
|
||||
{
|
||||
uint32_t timeout_ms = 0;
|
||||
int ret = 0;
|
||||
int vc_id = 0;
|
||||
char *pdata_send;
|
||||
uint32_t *pdata_recv;
|
||||
uint32_t veth_hab_pdata_size = 32;
|
||||
|
||||
VETH_IPA_INFO("%s: Enter HAB init\n", __func__);
|
||||
pdata_send = kmalloc(veth_hab_pdata_size, GFP_KERNEL);
|
||||
if (!pdata_send) {
|
||||
VETH_IPA_ERROR("%s: failed to alloc pdata_send\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pdata_recv = kmalloc(veth_hab_pdata_size, GFP_KERNEL);
|
||||
if (!pdata_recv) {
|
||||
kfree(pdata_send);
|
||||
VETH_IPA_ERROR("%s: failed to alloc pdata_recv\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
VETH_IPA_INFO("%s: Opening hab socket\n", __func__);
|
||||
ret = habmm_socket_open(&vc_id, mmid, timeout_ms, 0);
|
||||
|
||||
if (ret) {
|
||||
VETH_IPA_ERROR("%s: hab open failed %d returned\n",
|
||||
__func__, ret);
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
VETH_IPA_INFO("%s: vc_id = %d\n", __func__, vc_id);
|
||||
|
||||
/*Send the INIT*/
|
||||
memset(pdata_send, 1, veth_hab_pdata_size);
|
||||
VETH_IPA_INFO("%s: Sending INIT\n", __func__);
|
||||
ret = habmm_socket_send(vc_id, pdata_send, veth_hab_pdata_size, 0);
|
||||
|
||||
if (ret) {
|
||||
VETH_IPA_ERROR("%s: Send failed %d returned\n", __func__, ret);
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*Receive ACK*/
|
||||
memset(pdata_recv, 1, veth_hab_pdata_size);
|
||||
VETH_IPA_INFO("%s: Receiving ACK\n", __func__);
|
||||
ret = habmm_socket_recv(vc_id, &pdata_recv, &veth_hab_pdata_size, 0, 0);
|
||||
|
||||
if (ret) {
|
||||
VETH_IPA_ERROR("%s: receive failed! ret %d, recv size %d\n",
|
||||
__func__, ret, veth_hab_pdata_size);
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*Send INITACK*/
|
||||
memset(pdata_send, 1, veth_hab_pdata_size);
|
||||
VETH_IPA_INFO("%s: INIT ACK\n", __func__);
|
||||
ret = habmm_socket_send(vc_id, pdata_send, veth_hab_pdata_size, 0);
|
||||
|
||||
if (ret) {
|
||||
VETH_IPA_ERROR("%s: Send failed %d returned\n",
|
||||
__func__, ret);
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
return vc_id;
|
||||
err:
|
||||
kfree(pdata_send);
|
||||
kfree(pdata_recv);
|
||||
if (vc_id > 0)
|
||||
habmm_socket_close(vc_id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/** veth_emac_ipa_hab_export_tx_desc() - This API is called
|
||||
* for exporting the TX desc memory to BE driver in QNX host
|
||||
* @vcid: The virtual channel ID between BE and FE driver
|
||||
*
|
||||
* @veth_emac_mem - Contains the virtual and physical addresses
|
||||
* of the exported memory
|
||||
*/
|
||||
static int veth_emac_ipa_hab_export_tx_desc(
|
||||
int vc_id, struct veth_emac_export_mem *veth_emac_mem,
|
||||
struct veth_ipa_dev *pdata)
|
||||
{
|
||||
int ret = 0;
|
||||
/*export the memory*/
|
||||
VETH_IPA_DEBUG("%s: Export TX desc memory TO VC_ID %d\n",
|
||||
__func__, vc_id);
|
||||
VETH_IPA_DEBUG("%s: veth_emac_mem->tx_desc_mem_va %p\n",
|
||||
__func__, veth_emac_mem->tx_desc_mem_va);
|
||||
VETH_IPA_DEBUG("%s: size %d\n",
|
||||
__func__, sizeof(struct s_TX_NORMAL_DESC) * VETH_TX_DESC_CNT);
|
||||
ret = habmm_export(vc_id,
|
||||
veth_emac_mem->tx_desc_mem_va,
|
||||
sizeof(struct s_TX_NORMAL_DESC) * VETH_TX_DESC_CNT,
|
||||
&veth_emac_mem->exp_id.tx_desc_exp_id, 0);
|
||||
|
||||
if (ret) {
|
||||
VETH_IPA_ERROR("%s: Export failed %d returned, export id %d\n",
|
||||
__func__, ret, veth_emac_mem->exp_id.tx_desc_exp_id);
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
VETH_IPA_DEBUG("%s: Export memory location %p\n",
|
||||
__func__, veth_emac_mem->tx_desc_mem_va);
|
||||
|
||||
return ret;
|
||||
err:
|
||||
veth_alloc_emac_dealloc_mem(veth_emac_mem, pdata);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** veth_emac_ipa_hab_export_rx_desc() - This API is called for
|
||||
* exporting the RX desc memory to BE driver in QNX host
|
||||
* @vcid: The virtual channel ID between BE and FE driver
|
||||
*
|
||||
* @veth_emac_mem - Contains the virtual and physical addresses
|
||||
* of the exported memory
|
||||
*/
|
||||
static int veth_emac_ipa_hab_export_rx_desc(
|
||||
int vc_id, struct veth_emac_export_mem *veth_emac_mem,
|
||||
struct veth_ipa_dev *pdata)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
VETH_IPA_DEBUG("%s: Export RX desc memory TO VC_ID %d\n",
|
||||
__func__, vc_id);
|
||||
ret = habmm_export(vc_id,
|
||||
veth_emac_mem->rx_desc_mem_va,
|
||||
sizeof(struct s_RX_NORMAL_DESC) * VETH_RX_DESC_CNT,
|
||||
&veth_emac_mem->exp_id.rx_desc_exp_id,
|
||||
0);
|
||||
|
||||
if (ret) {
|
||||
VETH_IPA_ERROR("%s: Export failed %d returned, export id %d\n",
|
||||
__func__, ret, veth_emac_mem->exp_id.rx_desc_exp_id);
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
VETH_IPA_DEBUG("%s: Export RX desc memory location %p\n",
|
||||
__func__, veth_emac_mem->rx_desc_mem_va);
|
||||
return ret;
|
||||
|
||||
err:
|
||||
veth_alloc_emac_dealloc_mem(veth_emac_mem, pdata);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/** veth_emac_ipa_hab_export_tx_buf() - This API is called for
|
||||
* exporting the TX buf memory to BE driver in QNX host
|
||||
* @vcid: The virtual channel ID between BE and FE driver
|
||||
*
|
||||
* @veth_emac_mem - Contains the virtual and physical addresses
|
||||
* of the exported memory
|
||||
*/
|
||||
static int veth_emac_ipa_hab_export_tx_buf(
|
||||
int vc_id, struct veth_emac_export_mem *veth_emac_mem,
|
||||
struct veth_ipa_dev *pdata)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
VETH_IPA_DEBUG("%s: Export TX buf memory TO VC_ID %d\n",
|
||||
__func__, vc_id);
|
||||
ret = habmm_export(vc_id,
|
||||
veth_emac_mem->tx_buf_mem_va,
|
||||
VETH_ETH_FRAME_LEN_IPA * VETH_RX_DESC_CNT,
|
||||
&veth_emac_mem->exp_id.tx_buff_exp_id,
|
||||
0);
|
||||
|
||||
if (ret) {
|
||||
VETH_IPA_ERROR("%s: Export failed %d returned, export id %d\n",
|
||||
__func__, ret, veth_emac_mem->exp_id.tx_buff_exp_id);
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
VETH_IPA_DEBUG("%s: Export TX buf memory location %p\n",
|
||||
__func__, veth_emac_mem->tx_buf_mem_va);
|
||||
|
||||
return ret;
|
||||
|
||||
err:
|
||||
veth_alloc_emac_dealloc_mem(veth_emac_mem, pdata);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** veth_emac_ipa_hab_export_tx_desc() - This API is called
|
||||
* for exporting the RX buf memory to BE driver in QNX host
|
||||
* @vcid: The virtual channel ID between BE and FE driver
|
||||
*
|
||||
* @veth_emac_mem - Contains the virtual and physical addresses
|
||||
* of the exported memory
|
||||
*/
|
||||
static int veth_emac_ipa_hab_export_rx_buf(
|
||||
int vc_id, struct veth_emac_export_mem *veth_emac_mem,
|
||||
struct veth_ipa_dev *pdata)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
VETH_IPA_DEBUG("%s: Export RX buf memory TO VC_ID %d\n",
|
||||
__func__, vc_id);
|
||||
ret = habmm_export(vc_id,
|
||||
veth_emac_mem->rx_buf_mem_va,
|
||||
VETH_ETH_FRAME_LEN_IPA * VETH_RX_DESC_CNT,
|
||||
&veth_emac_mem->exp_id.rx_buff_exp_id,
|
||||
0);
|
||||
|
||||
if (ret) {
|
||||
VETH_IPA_ERROR("%s: Export failed %d returned, export id %d\n",
|
||||
__func__, ret, veth_emac_mem->exp_id.rx_buff_exp_id);
|
||||
ret = -1
|
||||
;
|
||||
goto err;
|
||||
}
|
||||
|
||||
VETH_IPA_DEBUG("%s: Export RX buf memory location %p\n",
|
||||
__func__, veth_emac_mem->rx_buf_mem_va);
|
||||
return ret;
|
||||
|
||||
err:
|
||||
veth_alloc_emac_dealloc_mem(veth_emac_mem, pdata);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** emac_ipa_hab_export_tx_buf_pool() - This API is called
|
||||
* for exporting the TX buf pool memory to BE driver in QNX host
|
||||
* @vcid: The virtual channel ID between BE and FE driver
|
||||
*
|
||||
* @veth_emac_mem - Contains the virtual and physical addresses
|
||||
* of the exported memory
|
||||
*/
|
||||
int emac_ipa_hab_export_tx_buf_pool(
|
||||
int vc_id, struct veth_emac_export_mem *veth_emac_mem,
|
||||
struct veth_ipa_dev *pdata)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
VETH_IPA_DEBUG("%s: Export TX buf pool memory TO VC_ID %d\n",
|
||||
__func__, vc_id);
|
||||
|
||||
ret = habmm_export(
|
||||
vc_id,
|
||||
veth_emac_mem->tx_buff_pool_base_va,
|
||||
sizeof(uint32_t) * VETH_TX_DESC_CNT * 4,
|
||||
&veth_emac_mem->exp_id.tx_buf_pool_exp_id,
|
||||
0);
|
||||
|
||||
if (ret) {
|
||||
VETH_IPA_ERROR("%s: Export failed %d returned, export id %d\n",
|
||||
__func__,
|
||||
ret,
|
||||
veth_emac_mem->exp_id.tx_buf_pool_exp_id);
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
pr_info("%s: Export TX buf pool memory location %p %d\n",
|
||||
__func__,
|
||||
veth_emac_mem->tx_buff_pool_base_va,
|
||||
veth_emac_mem->exp_id.tx_buf_pool_exp_id);
|
||||
return ret;
|
||||
|
||||
err:
|
||||
veth_alloc_emac_dealloc_mem(veth_emac_mem, pdata);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/** emac_ipa_hab_export_tx_buf_pool() - This API is called
|
||||
* for exporting the TX buf pool memory to BE driver in QNX host
|
||||
* @vcid: The virtual channel ID between BE and FE driver
|
||||
*
|
||||
* @veth_emac_mem - Contains the virtual and physical addresses
|
||||
* of the exported memory
|
||||
*/
|
||||
int emac_ipa_hab_export_rx_buf_pool(
|
||||
int vc_id, struct veth_emac_export_mem *veth_emac_mem,
|
||||
struct veth_ipa_dev *pdata)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
VETH_IPA_DEBUG("%s: Export RX buf pool memory TO VC_ID %d\n",
|
||||
__func__, vc_id);
|
||||
|
||||
ret = habmm_export(
|
||||
vc_id,
|
||||
veth_emac_mem->rx_buff_pool_base_va,
|
||||
sizeof(uint32_t) * (VETH_RX_DESC_CNT * 4),
|
||||
&veth_emac_mem->exp_id.rx_buf_pool_exp_id,
|
||||
0);
|
||||
|
||||
if (ret) {
|
||||
VETH_IPA_ERROR("%s: Export failed %d returned, export id %d\n",
|
||||
__func__,
|
||||
ret,
|
||||
veth_emac_mem->exp_id.rx_buf_pool_exp_id);
|
||||
ret = -1
|
||||
;
|
||||
goto err;
|
||||
}
|
||||
|
||||
pr_info("%s: Export RX buf pool memory location %p , %d\n",
|
||||
__func__,
|
||||
veth_emac_mem->rx_buff_pool_base_va,
|
||||
veth_emac_mem->exp_id.rx_buf_pool_exp_id);
|
||||
return ret;
|
||||
|
||||
err:
|
||||
veth_alloc_emac_dealloc_mem(veth_emac_mem, pdata);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** veth_emac_ipa_send_exp_id() - This API is used to send the
|
||||
* export IDs of all the exported memory to the BE driver in
|
||||
* QNX host
|
||||
* @vcid: The virtual channel ID between BE and FE driver
|
||||
*
|
||||
* @veth_emac_mem - Contains the virtual and physical addresses
|
||||
* of the exported memory
|
||||
*/
|
||||
int veth_emac_ipa_send_exp_id(
|
||||
int vc_id, struct veth_emac_export_mem *veth_emac_mem)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = habmm_socket_send(vc_id,
|
||||
&veth_emac_mem->exp_id,
|
||||
sizeof(veth_emac_mem->exp_id),
|
||||
NO_FLAGS);
|
||||
VETH_IPA_INFO("Sent export ids to the backend driver");
|
||||
VETH_IPA_INFO("TX Descriptor export id sent %x",
|
||||
veth_emac_mem->exp_id.tx_desc_exp_id);
|
||||
if (ret) {
|
||||
VETH_IPA_ERROR("%s: Send failed %d returned\n",
|
||||
__func__,
|
||||
ret);
|
||||
ret = -1;
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int veth_emac_init(struct veth_emac_export_mem *veth_emac_mem,
|
||||
struct veth_ipa_dev *pdata, bool smmu_s2_enb)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = veth_emac_ipa_hab_export_tx_desc(veth_emac_mem->vc_id,
|
||||
veth_emac_mem,
|
||||
pdata);
|
||||
|
||||
if (ret < 0) {
|
||||
VETH_IPA_ERROR(
|
||||
"HAB export of TX desc mem failed, returning error");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = veth_emac_ipa_hab_export_rx_desc(veth_emac_mem->vc_id,
|
||||
veth_emac_mem,
|
||||
pdata);
|
||||
|
||||
if (ret < 0) {
|
||||
VETH_IPA_ERROR(
|
||||
"HAB export of RX desc mem failed, returning error");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = veth_emac_ipa_hab_export_tx_buf(veth_emac_mem->vc_id,
|
||||
veth_emac_mem,
|
||||
pdata);
|
||||
|
||||
if (ret < 0) {
|
||||
VETH_IPA_ERROR(
|
||||
"HAB export of TX buf mem failed, returning error");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = veth_emac_ipa_hab_export_rx_buf(veth_emac_mem->vc_id,
|
||||
veth_emac_mem,
|
||||
pdata);
|
||||
|
||||
if (ret < 0) {
|
||||
VETH_IPA_ERROR(
|
||||
"HAB export of RX buf mem failed, returning error");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = emac_ipa_hab_export_tx_buf_pool(veth_emac_mem->vc_id,
|
||||
veth_emac_mem,
|
||||
pdata);
|
||||
|
||||
if (ret < 0) {
|
||||
VETH_IPA_ERROR(
|
||||
"HAB export of TX buff pool mem failed, returning error");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = emac_ipa_hab_export_rx_buf_pool(veth_emac_mem->vc_id,
|
||||
veth_emac_mem,
|
||||
pdata);
|
||||
|
||||
if (ret < 0) {
|
||||
VETH_IPA_ERROR(
|
||||
"HAB export of RX buff pool mem failed, returning error");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = veth_emac_ipa_send_exp_id(veth_emac_mem->vc_id,
|
||||
veth_emac_mem);
|
||||
|
||||
if (ret < 0) {
|
||||
VETH_IPA_ERROR(
|
||||
"Sending exp id failed, returning error");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
VETH_IPA_INFO("%s: Memory export complete\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** veth_emac_ipa_setup_complete() - This API is used to send
|
||||
* the SETUP complete event to the BE driver. It is triggered
|
||||
* when the memory export and the IPA set up is complete. It
|
||||
* informs the BE that the set up is complete at the FE
|
||||
*
|
||||
* @veth_emac_mem - Contains the virtual and physical addresses
|
||||
* of the exported memory
|
||||
*
|
||||
* @pdata - Contains the network device information
|
||||
*/
|
||||
int veth_emac_ipa_setup_complete(struct veth_emac_export_mem *veth_emac_mem,
|
||||
struct veth_ipa_dev *pdata)
|
||||
{
|
||||
|
||||
int ret = 0;
|
||||
|
||||
veth_emac_mem->exp_id.event_id = VETH_IPA_SETUP_COMPLETE;
|
||||
VETH_IPA_DEBUG("%s: Send TX buf memory %d\n", __func__);
|
||||
|
||||
ret = habmm_socket_send(veth_emac_mem->vc_id,
|
||||
&veth_emac_mem->exp_id,
|
||||
sizeof(veth_emac_mem->exp_id),
|
||||
NO_FLAGS);
|
||||
if (ret) {
|
||||
VETH_IPA_ERROR("%s: Send failed %d returned\n",
|
||||
__func__, ret);
|
||||
ret = -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** veth_emac_start_offload() - This API is used to send the
|
||||
* START_OFFLOAD event to the BE driver. It is triggered when
|
||||
* the IPA setup, memory export and emac side set up is
|
||||
* complete. We turn on the net carrier and the start queue
|
||||
*
|
||||
* @veth_emac_mem - Contains the virtual and physical addresses
|
||||
* of the exported memory
|
||||
*
|
||||
* @pdata - Contains the network device information
|
||||
*/
|
||||
int veth_emac_start_offload(struct veth_emac_export_mem *veth_emac_mem,
|
||||
struct veth_ipa_dev *pdata)
|
||||
{
|
||||
|
||||
int ret = 0;
|
||||
|
||||
veth_emac_mem->exp_id.event_id = VETH_IPA_START_OFFLOAD;
|
||||
VETH_IPA_DEBUG("%s: Send TX buf memory %d\n", __func__);
|
||||
ret = habmm_socket_send(veth_emac_mem->vc_id,
|
||||
&veth_emac_mem->exp_id,
|
||||
sizeof(veth_emac_mem->exp_id),
|
||||
NO_FLAGS);
|
||||
if (ret) {
|
||||
VETH_IPA_ERROR("%s: Send failed %d returned\n",
|
||||
__func__, ret);
|
||||
ret = -1;
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** veth_emac_stop_offload() - This API is used to send the STOP
|
||||
* event to the BE driver. This event is triggered after the
|
||||
* clean up at the FE driver an we instruct the BE driver to
|
||||
* clean up the memory and start the clean up process
|
||||
*
|
||||
* @veth_emac_mem - Contains the virtual and physical addresses
|
||||
* of the exported memory
|
||||
*
|
||||
* @pdata - Contains the network device information
|
||||
*/
|
||||
int veth_emac_stop_offload(struct veth_emac_export_mem *veth_emac_mem,
|
||||
struct veth_ipa_dev *pdata)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
veth_emac_mem->exp_id.event_id = VETH_IPA_STOP_OFFLOAD;
|
||||
VETH_IPA_DEBUG("%s: Send TX buf memory %d\n", __func__);
|
||||
ret = habmm_socket_send(veth_emac_mem->vc_id,
|
||||
&veth_emac_mem->exp_id,
|
||||
sizeof(veth_emac_mem->exp_id),
|
||||
NO_FLAGS);
|
||||
if (ret) {
|
||||
VETH_IPA_ERROR("%s: Send failed %d returned\n",
|
||||
__func__, ret);
|
||||
ret = -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** veth_emac_setup_be() - This API is used to send
|
||||
* the SETUP_OFFLOAD event to the BE driver. It is triggered
|
||||
* to notify the BE driver to set up the memory in the BE
|
||||
* driver before starting the offload
|
||||
*
|
||||
* @veth_emac_mem - Contains the virtual and physical addresses
|
||||
* of the exported memory
|
||||
*
|
||||
* @pdata - Contains the network device information
|
||||
*/
|
||||
int veth_emac_setup_be(struct veth_emac_export_mem *veth_emac_mem,
|
||||
struct veth_ipa_dev *pdata)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
veth_emac_mem->exp_id.event_id = VETH_IPA_SETUP_OFFLOAD;
|
||||
VETH_IPA_DEBUG("%s: Send TX buf memory %d\n", __func__);
|
||||
ret = habmm_socket_send(veth_emac_mem->vc_id,
|
||||
&veth_emac_mem->exp_id,
|
||||
sizeof(veth_emac_mem->exp_id),
|
||||
NO_FLAGS);
|
||||
if (ret) {
|
||||
VETH_IPA_ERROR("%s: Send failed %d returned\n",
|
||||
__func__, ret);
|
||||
ret = -1;
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** veth_emac_open_notify() - This API is used to send the
|
||||
* OPEN_NOTIFY event to the BE driver. This event is sent to
|
||||
* notify the BE driver that veth_ipa_open is called when the
|
||||
* ifconfig up command is triggered on VETH0 iface
|
||||
*
|
||||
* @veth_emac_mem - Contains the virtual and physical addresses
|
||||
* of the exported memory
|
||||
*
|
||||
* @pdata - Contains the network device information
|
||||
*/
|
||||
int veth_emac_open_notify(struct veth_emac_export_mem *veth_emac_mem,
|
||||
struct veth_ipa_dev *pdata)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
veth_emac_mem->exp_id.event_id = VETH_IPA_OPEN_EV;
|
||||
VETH_IPA_DEBUG("%s: Send TX buf memory %d\n", __func__);
|
||||
|
||||
ret = habmm_socket_send(veth_emac_mem->vc_id,
|
||||
&veth_emac_mem->exp_id,
|
||||
sizeof(veth_emac_mem->exp_id),
|
||||
NO_FLAGS);
|
||||
if (ret) {
|
||||
VETH_IPA_ERROR("%s: Send failed %d returned\n",
|
||||
__func__, ret);
|
||||
ret = -1;
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
57
drivers/platform/msm/veth_ipa/veth_emac_mgt.h
Normal file
57
drivers/platform/msm/veth_ipa/veth_emac_mgt.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _VETH_EMAC_MGT_H_
|
||||
#define _VETH_EMAC_MGT_H_
|
||||
|
||||
|
||||
#include "veth_ipa.h"
|
||||
|
||||
#define MM_DATA_NETWORK_1_VM_HAB_MINOR_ID 10
|
||||
|
||||
|
||||
int veth_emac_init(struct veth_emac_export_mem *veth_emac_mem,
|
||||
struct veth_ipa_dev *pdata,
|
||||
bool smmu_s2_enb);
|
||||
|
||||
int veth_alloc_emac_export_mem(struct veth_emac_export_mem *veth_emac_mem,
|
||||
struct veth_ipa_dev *pdata);
|
||||
|
||||
int veth_emac_start_offload(struct veth_emac_export_mem *veth_emac_mem,
|
||||
struct veth_ipa_dev *pdata);
|
||||
|
||||
int veth_emac_setup_be(struct veth_emac_export_mem *veth_emac_mem,
|
||||
struct veth_ipa_dev *pdata);
|
||||
|
||||
int veth_emac_ipa_hab_init(int mmid);
|
||||
int veth_alloc_emac_dealloc_mem(struct veth_emac_export_mem *veth_emac_mem,
|
||||
struct veth_ipa_dev *pdata);
|
||||
int veth_emac_stop_offload(struct veth_emac_export_mem *veth_emac_mem,
|
||||
struct veth_ipa_dev *pdata);
|
||||
int veth_emac_open_notify(struct veth_emac_export_mem *veth_emac_mem,
|
||||
struct veth_ipa_dev *pdata);
|
||||
int veth_emac_ipa_setup_complete(struct veth_emac_export_mem *veth_emac_mem,
|
||||
struct veth_ipa_dev *pdata);
|
||||
int emac_ipa_hab_export_tx_buf_pool(int vc_id,
|
||||
struct veth_emac_export_mem *veth_emac_mem,
|
||||
struct veth_ipa_dev *pdata);
|
||||
int emac_ipa_hab_export_rx_buf_pool(int vc_id,
|
||||
struct veth_emac_export_mem *veth_emac_mem,
|
||||
struct veth_ipa_dev *pdata);
|
||||
int veth_emac_ipa_send_exp_id(int vc_id,
|
||||
struct veth_emac_export_mem *veth_emac_mem);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* _VETH_EMAC_MGT_H_ */
|
||||
2364
drivers/platform/msm/veth_ipa/veth_ipa.c
Normal file
2364
drivers/platform/msm/veth_ipa/veth_ipa.c
Normal file
File diff suppressed because it is too large
Load diff
467
drivers/platform/msm/veth_ipa/veth_ipa.h
Normal file
467
drivers/platform/msm/veth_ipa/veth_ipa.h
Normal file
|
|
@ -0,0 +1,467 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only
|
||||
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
/* This file contain content copied from Synopsis driver,
|
||||
* provided under the license below
|
||||
*/
|
||||
/* =========================================================================
|
||||
* The Synopsys DWC ETHER QOS Software Driver and documentation (hereinafter
|
||||
* "Software") is an unsupported work of Synopsys, Inc. unless
|
||||
* otherwise expressly agreed to in writing between Synopsys and you.
|
||||
*
|
||||
* The Software IS NOT an item of Licensed Software or Licensed Product under
|
||||
* any End User Software License Agreement or Agreement for Licensed Product
|
||||
* with Synopsys or any supplement thereto. Permission is hereby granted,
|
||||
* free of charge, to any person obtaining a copy of this software annotated
|
||||
* with this license and the Software, to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject
|
||||
* to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
* =========================================================================
|
||||
*/
|
||||
|
||||
#ifndef _VETH_IPA_H_
|
||||
#define _VETH_IPA_H_
|
||||
|
||||
#include <linux/ipa.h>
|
||||
#include <linux/ipa_uc_offload.h>
|
||||
#include <linux/ipc_logging.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/ip.h>
|
||||
|
||||
|
||||
|
||||
/* Feature enable disable flags*/
|
||||
#define VETH_ENABLE_VLAN_TAG
|
||||
#define VETH_MIN_VLAN_ID 1
|
||||
#define VETH_MAX_VLAN_ID 4094
|
||||
|
||||
#define DRIVER_NAME "veth_ipa"
|
||||
#define IPA_VETH_IPC_LOGGING(buf, fmt, args...) \
|
||||
do { \
|
||||
if (buf) \
|
||||
ipc_log_string((buf), fmt, __func__, __LINE__, \
|
||||
## args); \
|
||||
} while (0)
|
||||
|
||||
static void *ipa_veth_logbuf;
|
||||
|
||||
#define VETH_IPA_DEBUG(fmt, args...) \
|
||||
do { \
|
||||
pr_debug(DRIVER_NAME " %s:%d "\
|
||||
fmt, __func__, __LINE__, ## args);\
|
||||
if (ipa_veth_logbuf) { \
|
||||
IPA_VETH_IPC_LOGGING(ipa_veth_logbuf, \
|
||||
DRIVER_NAME " %s:%d " fmt, ## args); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define VETH_IPA_DEBUG_XMIT(fmt, args...) \
|
||||
pr_debug(DRIVER_NAME " %s:%d " fmt, __func__, __LINE__, ## args)
|
||||
|
||||
#define VETH_IPA_INFO(fmt, args...) \
|
||||
do { \
|
||||
pr_info(DRIVER_NAME "@%s@%d@ctx:%s: "\
|
||||
fmt, __func__, __LINE__, current->comm, ## args);\
|
||||
if (ipa_veth_logbuf) { \
|
||||
IPA_VETH_IPC_LOGGING(ipa_veth_logbuf, \
|
||||
DRIVER_NAME " %s:%d " fmt, ## args); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define VETH_IPA_ERROR(fmt, args...) \
|
||||
do { \
|
||||
pr_err(DRIVER_NAME "@%s@%d@ctx:%s: "\
|
||||
fmt, __func__, __LINE__, current->comm, ## args);\
|
||||
if (ipa_veth_logbuf) { \
|
||||
IPA_VETH_IPC_LOGGING(ipa_veth_logbuf, \
|
||||
DRIVER_NAME " %s:%d " fmt, ## args); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define NULL_CHECK(ptr) \
|
||||
do { \
|
||||
if (!(ptr)) { \
|
||||
VETH_IPA_ERROR("null pointer #ptr\n"); \
|
||||
ret = -EINVAL; \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define VETH_IPA_LOG_ENTRY() VETH_IPA_DEBUG("begin\n")
|
||||
#define VETH_IPA_LOG_EXIT() VETH_IPA_DEBUG("end\n")
|
||||
#define VETH_RX_DESC_CNT 256 /*la uses 128*/
|
||||
#define VETH_TX_DESC_CNT 256 /*la uses 128*/
|
||||
/*IPA can support 2KB max pkt length*/
|
||||
|
||||
#define VETH_ETH_FRAME_LEN_IPA (1<<12)
|
||||
#define VETH_IPA_LOCK() mutex_lock(&pdata->prv_ipa.ipa_lock)
|
||||
#define VETH_IPA_UNLOCK() mutex_unlock(&pdata->prv_ipa.ipa_lock)
|
||||
|
||||
enum IPA_OFFLOAD_EVENT {
|
||||
EV_INVALID = 0,
|
||||
EV_DEV_OPEN,
|
||||
EV_DEV_CLOSE,
|
||||
EV_IPA_READY,
|
||||
EV_IPA_UC_READY,
|
||||
EV_IPA_EMAC_INIT,
|
||||
EV_IPA_EMAC_SETUP,
|
||||
EV_PHY_LINK_UP,
|
||||
EV_EMAC_DEINIT,
|
||||
EV_EMAC_UP,
|
||||
EV_START_OFFLOAD,
|
||||
};
|
||||
|
||||
struct s_RX_NORMAL_DESC {
|
||||
unsigned int RDES0;
|
||||
unsigned int RDES1;
|
||||
unsigned int RDES2;
|
||||
unsigned int RDES3;
|
||||
};
|
||||
|
||||
|
||||
struct s_TX_NORMAL_DESC {
|
||||
unsigned int TDES0;
|
||||
unsigned int TDES1;
|
||||
unsigned int TDES2;
|
||||
unsigned int TDES3;
|
||||
};
|
||||
|
||||
|
||||
struct veth_emac_exp {
|
||||
uint32_t tx_desc_exp_id;
|
||||
uint32_t rx_desc_exp_id;
|
||||
uint32_t tx_buff_exp_id;
|
||||
uint32_t rx_buff_exp_id;
|
||||
uint32_t rx_buf_pool_exp_id;
|
||||
uint32_t tx_buf_pool_exp_id;
|
||||
int event_id;
|
||||
};
|
||||
|
||||
struct veth_emac_export_mem {
|
||||
/* IPAs - this is not a virtual address*/
|
||||
void *tx_desc_mem_va;
|
||||
phys_addr_t tx_desc_mem_paddr;
|
||||
dma_addr_t tx_desc_mem_iova;
|
||||
phys_addr_t tx_desc_ring_base[VETH_TX_DESC_CNT];
|
||||
|
||||
void *tx_buf_mem_va;
|
||||
dma_addr_t tx_buf_mem_paddr;
|
||||
dma_addr_t tx_buf_mem_iova;
|
||||
|
||||
uint32_t *tx_buff_pool_base_va;
|
||||
dma_addr_t tx_buff_pool_base_iova;
|
||||
dma_addr_t tx_buff_pool_base_pa;
|
||||
|
||||
void *rx_desc_mem_va;
|
||||
phys_addr_t rx_desc_mem_paddr;
|
||||
dma_addr_t rx_desc_mem_iova;
|
||||
phys_addr_t rx_desc_ring_base[VETH_RX_DESC_CNT];
|
||||
|
||||
|
||||
void *rx_buf_mem_va;
|
||||
dma_addr_t rx_buf_mem_paddr;
|
||||
dma_addr_t rx_buf_mem_iova;
|
||||
|
||||
uint32_t *rx_buff_pool_base_va;
|
||||
dma_addr_t rx_buff_pool_base_iova;
|
||||
dma_addr_t rx_buff_pool_base_pa;
|
||||
|
||||
struct veth_emac_exp exp_id;
|
||||
int vc_id;
|
||||
bool link_down;
|
||||
bool init_complete;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* enum veth_ipa_state - specify the current driver internal
|
||||
* state which is guarded by a state machine.
|
||||
*
|
||||
* The driver internal state changes due to its external API usage.
|
||||
* The driver saves its internal state to guard from caller illegal
|
||||
* call sequence.
|
||||
* states:
|
||||
* UNLOADED is the first state which is the default one and is also the state
|
||||
* after the driver gets unloaded(cleanup).
|
||||
* INITIALIZED is the driver state once it finished registering
|
||||
* the network device and all internal data struct were initialized
|
||||
* CONNECTED is the driver state once the EMAC pipes were
|
||||
* connected to IPA UP is the driver state after the interface
|
||||
* mode was set to UP but the
|
||||
* pipes are not connected yet - this state is meta-stable state.
|
||||
* CONNECTED_AND_UP is the driver state when the pipe were connected and
|
||||
* the interface got UP request from the network stack. this is the driver
|
||||
* idle operation state which allows it to transmit/receive data.
|
||||
* INVALID is a state which is not allowed.
|
||||
*/
|
||||
enum veth_ipa_state {
|
||||
VETH_IPA_UNLOADED = 0,
|
||||
VETH_IPA_INITIALIZED,
|
||||
VETH_IPA_CONNECTED,
|
||||
VETH_IPA_UP,
|
||||
VETH_IPA_CONNECTED_AND_UP,
|
||||
VETH_IPA_DOWN,
|
||||
VETH_IPA_INVALID,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* enum VETH_ipa_operation - enumerations used to descibe the API operation
|
||||
*
|
||||
* Those enums are used as input for the driver state machine.
|
||||
*/
|
||||
enum veth_ipa_operation {
|
||||
VETH_IPA_INITIALIZE,
|
||||
VETH_IPA_CONNECT,
|
||||
VETH_IPA_OPEN,
|
||||
VETH_IPA_STOP,
|
||||
VETH_IPA_DISCONNECT,
|
||||
VETH_IPA_CLEANUP,
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* enum veth_ipa_emac_commands - enumerations which are used in
|
||||
*
|
||||
* Those enums are used as input for the driver state machine.
|
||||
*/
|
||||
enum veth_ipa_emac_commands {
|
||||
VETH_IPA_OPEN_EV,
|
||||
VETH_IPA_SETUP_OFFLOAD,
|
||||
VETH_IPA_START_OFFLOAD,
|
||||
VETH_IPA_STOP_OFFLOAD,
|
||||
VETH_IPA_ACK,
|
||||
VETH_IPA_SETUP_COMPLETE,
|
||||
};
|
||||
|
||||
|
||||
#define VETH_IPA_STATE_DEBUG(veth_ipa_ctx) \
|
||||
VETH_IPA_DEBUG("Driver state - %s\n",\
|
||||
veth_ipa_state_string((veth_ipa_ctx)->state))
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* @priv: private data given upon ipa_connect
|
||||
* @evt: event enum, should be IPA_WRITE_DONE
|
||||
* @data: for tx path the data field is the sent socket buffer.
|
||||
*/
|
||||
typedef void (*veth_ipa_callback)(void *priv,
|
||||
enum ipa_dp_evt_type evt,
|
||||
unsigned long data);
|
||||
|
||||
|
||||
struct veth_ipa_client_data {
|
||||
phys_addr_t uc_db_rx_addr;
|
||||
phys_addr_t uc_db_tx_addr;
|
||||
u32 ipa_client_hndl;
|
||||
|
||||
/*State of IPA readiness*/
|
||||
bool ipa_ready;
|
||||
|
||||
/*State of IPA UC readiness*/
|
||||
bool ipa_uc_ready;
|
||||
|
||||
/*State of IPA Offload intf registration with IPA driver*/
|
||||
bool ipa_offload_init;
|
||||
|
||||
/*State of IPA pipes connection*/
|
||||
bool ipa_offload_conn;
|
||||
|
||||
/*EMAC init*/
|
||||
bool emac_init;
|
||||
|
||||
/*Dev state*/
|
||||
struct work_struct ntn_ipa_rdy_work;
|
||||
struct mutex ipa_lock;
|
||||
bool vlan_enable;
|
||||
unsigned short vlan_id;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* struct veth_ipa_params - parameters for ecm_ipa
|
||||
* initialization API
|
||||
*
|
||||
* @device_ready_notify: callback supplied by USB core driver.
|
||||
* This callback shall be called by the Netdev once the device
|
||||
* is ready to receive data from tethered PC.
|
||||
*
|
||||
* @veth_ipa_rx_dp_notify: ecm_ipa will set this callback (out
|
||||
* parameter). this callback shall be supplied for ipa_connect
|
||||
* upon pipe connection (USB->IPA), once IPA driver receive data
|
||||
* packets from USB pipe destined for Apps this callback will be
|
||||
* called.
|
||||
*
|
||||
* @veth_ipa_tx_dp_notify: ecm_ipa will set this callback (out
|
||||
* parameter). this callback shall be supplied for ipa_connect
|
||||
* upon pipe connection (IPA->USB), once IPA driver send packets
|
||||
* destined for USB, IPA BAM will notify for Tx-complete. @priv:
|
||||
* ecm_ipa will set this pointer (out parameter). This pointer
|
||||
* will hold the network device for later interaction with
|
||||
* ecm_ipa APIs
|
||||
*
|
||||
* @host_ethaddr: host Ethernet address in network order
|
||||
*
|
||||
* @device_ethaddr: device Ethernet address in network order
|
||||
*
|
||||
* @skip_ep_cfg: boolean field that determines if
|
||||
* Apps-processor should or should not configure this
|
||||
* end-point.
|
||||
*/
|
||||
|
||||
/**
|
||||
* struct veth_ipa_dev - main driver context parameters
|
||||
* @net: network interface struct implemented by this driver
|
||||
* @directory: debugfs directory for various debuging switches
|
||||
* @eth_ipv4_hdr_hdl: saved handle for ipv4 header-insertion table
|
||||
* @eth_ipv6_hdr_hdl: saved handle for ipv6 header-insertion table
|
||||
* @emac_to_ipa_hdl: save handle for IPA pipe operations
|
||||
* @ipa_to_emac_hdl: save handle for IPA pipe operations
|
||||
* @outstanding_pkts: number of packets sent to IPA without TX complete ACKed
|
||||
* @outstanding_high: number of outstanding packets allowed
|
||||
* @outstanding_low: number of outstanding packets which shall cause
|
||||
* to netdev queue start (after stopped due to outstanding_high reached)
|
||||
* @state: current state of VETH_ipa driver
|
||||
* @device_ready_notify: callback supplied by USB core driver
|
||||
* This callback shall be called by the Netdev once the Netdev internal
|
||||
* state is changed to RNDIS_IPA_CONNECTED_AND_UP
|
||||
* @ipa_to_emac_client: consumer client
|
||||
* @emac_to_ipa_client: producer client
|
||||
* @ipa_rm_resource_name_prod: IPA resource manager producer resource
|
||||
* @ipa_rm_resource_name_cons: IPA resource manager consumer resource
|
||||
* @pm_hdl: handle for IPA PM
|
||||
* @is_vlan_mode: does the driver need to work in VLAN mode?
|
||||
*/
|
||||
struct veth_ipa_dev {
|
||||
/*should be part of private Struct*/
|
||||
struct net_device *net;
|
||||
struct platform_device *pdev;
|
||||
//struct net_device_stats stats;
|
||||
atomic_t outstanding_pkts;
|
||||
struct dentry *directory;
|
||||
u8 outstanding_high;
|
||||
u8 outstanding_low;
|
||||
enum veth_ipa_state state;
|
||||
void (*device_ready_notify)(void);
|
||||
|
||||
#ifdef VETH_PM_ENB
|
||||
u32 pm_hdl;
|
||||
#endif
|
||||
bool is_vlan_mode;
|
||||
|
||||
/* Status of EMAC Device*/
|
||||
bool veth_emac_dev_ready;
|
||||
|
||||
int speed;
|
||||
|
||||
struct veth_ipa_client_data prv_ipa;
|
||||
struct veth_emac_export_mem veth_emac_mem;
|
||||
veth_ipa_callback veth_ipa_rx_dp_notify;
|
||||
veth_ipa_callback veth_ipa_tx_dp_notify;
|
||||
u8 host_ethaddr[ETH_ALEN]; /*not needed for veth driver ?*/
|
||||
unsigned char device_ethaddr[ETH_ALEN];
|
||||
void *private;
|
||||
bool skip_ep_cfg;
|
||||
struct ipa_ntn_setup_info *tx_setup_info;
|
||||
struct ipa_ntn_setup_info *rx_setup_info;
|
||||
};
|
||||
|
||||
/* SMMU related */
|
||||
struct emac_emb_smmu_cb_ctx {
|
||||
bool valid;
|
||||
struct platform_device *pdev_master;
|
||||
struct platform_device *smmu_pdev;
|
||||
struct dma_iommu_mapping *mapping;
|
||||
struct iommu_domain *iommu_domain;
|
||||
u32 va_start;
|
||||
u32 va_size;
|
||||
u32 va_end;
|
||||
int ret;
|
||||
};
|
||||
|
||||
|
||||
/* Maintain Order same on FE*/
|
||||
struct emac_ipa_iovas {
|
||||
/*iova addresses*/
|
||||
void *tx_desc_mem_iova;
|
||||
void *tx_buf_mem_iova;
|
||||
void *tx_buf_pool_base_iova;
|
||||
void *rx_desc_mem_iova;
|
||||
void *rx_buf_mem_iova;
|
||||
void *rx_buf_pool_base_iova;
|
||||
};
|
||||
|
||||
struct emac_hab_mm_message {
|
||||
int event_id;
|
||||
union msg_type {
|
||||
struct emac_ipa_iovas iova;
|
||||
} msg_type;
|
||||
};
|
||||
|
||||
|
||||
#define GET_MEM_PDEV_DEV (emac_emb_smmu_ctx.valid ? \
|
||||
&emac_emb_smmu_ctx.smmu_pdev->dev : ¶ms->pdev->dev)
|
||||
|
||||
#if IS_ENABLED(CONFIG_VETH_IPA)
|
||||
|
||||
int veth_ipa_connect(u32 emac_to_ipa_hdl, u32 ipa_to_emac_hdl, void *priv);
|
||||
|
||||
int veth_ipa_disconnect(void *priv);
|
||||
|
||||
void veth_ipa_cleanup(struct veth_ipa_dev *veth_ipa_ctx);
|
||||
|
||||
#else /* CONFIG_VETH_IPA*/
|
||||
|
||||
static inline int veth_ipa_connect(u32 emac_to_ipa_hdl, u32 ipa_to_emac_hdl,
|
||||
void *priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int veth_ipa_disconnect(void *priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void veth_ipa_cleanup(void *priv)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* CONFIG_VETH_IPA*/
|
||||
|
||||
#endif /* _VETH_IPA_H_ */
|
||||
|
||||
Loading…
Reference in a new issue