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:
Akshay Pandit 2020-10-12 17:31:06 +05:30 • committed by Gerrit - the friendly Code Review server
commit fe26c474b7
7 changed files with 3791 additions and 0 deletions

View file

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

View file

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

View file

@ -0,0 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_VETH_IPA) += veth_emac_mgt.o veth_ipa.o

View 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;
}

View 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_ */

File diff suppressed because it is too large Load diff

View 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 : &params->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_ */