update mhi devices
This commit is contained in:
parent
d919b7854a
commit
ea0d1cca86
@ -1,103 +1,126 @@
|
||||
Release Notes
|
||||
|
||||
[V1.3.4]
|
||||
Date: 12/8/2022
|
||||
enhancement:
|
||||
1. only allow to enable autosuspend when module is in MHI_EE_AMSS
|
||||
2. show pcie link speed and width when driver probe
|
||||
3. check pcie link status by read pcie vid and pid when driver probe,
|
||||
if pcie link is down, return -EIO
|
||||
4. support RM520 (1eac:1004)
|
||||
5. support qmap command packet
|
||||
fix:
|
||||
1. fix tx queue is wrong stop when do uplink TPUT
|
||||
2. fix after QFirehose, module fail to bootup at very small probability
|
||||
3. mhi uci add mutex lock for concurrent reads/writes
|
||||
|
||||
[V1.3.3]
|
||||
Date: 30/6/2022
|
||||
enhancement:
|
||||
1. remove one un-necessary kmalloc when do qfirehose
|
||||
2. support mhi monitor (like usbmon), usage: cat /sys/kernel/debug/mhi_q/0306_00\:01.00/mhimon
|
||||
3. set ring size of event 0 to 256 (from 1024), required by x6x
|
||||
4. support PCIE local network card mhi_swip0 (chan 46/47), default disabled
|
||||
5. porting IPQ5018 mhi rate controll code from spf11.5
|
||||
6. set pcie rmnet download max qmap packet size to 15KB (same to IPQ MHI Driver)
|
||||
7. support set different mac address for rmnet net card
|
||||
8. when mhi netdev fail to malloc, use delay_work instead work
|
||||
9. optimize code for 'when driver load, modem is still in MHI_EE_PTHRU'
|
||||
fix:
|
||||
1. Fix not synchronize access rp/wp when mhi_queue_xxx and mhi_process_xxx_ring run on different CPU
|
||||
2. set dma mask when driver probe, some SOC like rpi_4 need it
|
||||
|
||||
[V1.3.2]
|
||||
Date: 12/16/2021
|
||||
enhancement:
|
||||
1. support Linux Kernel V5.14
|
||||
2. mhi_netdev_quectel.c do not print log in softirq context
|
||||
|
||||
[V1.3.1]
|
||||
Date: 9/26/2021
|
||||
enhancement:
|
||||
fix:
|
||||
|
||||
[V1.3.0.19]
|
||||
Date: 9/18/2021
|
||||
enhancement:
|
||||
1. support sdx62 (17cb:0308)
|
||||
2. support IPQ5018's NSS
|
||||
3. use 'qsdk/qca/src/data-kernel/drivers/rmnet-nss/rmnet_nss.c' instead myself rmnet_nss.c
|
||||
and pcie_mhi.ko must load after then rmnet_nss.ko
|
||||
4. allow bhi irq is not 0 (for ipq5018)
|
||||
fix:
|
||||
|
||||
[V1.3.0.18]
|
||||
Date: 4/14/2021
|
||||
enhancement:
|
||||
1. support mbim multiple call, usage:
|
||||
# insmod pcie_mhi.ko mhi_mbim_enabeld=1 qmap_mode=4
|
||||
# quectel-mbim-proxy -d /dev/mhi_MBIM &
|
||||
# quectel-CM -n X
|
||||
fix:
|
||||
|
||||
[V1.3.0.17]
|
||||
Date: 3/11/2021
|
||||
enhancement:
|
||||
fix:
|
||||
1. fix CPU loading very high when TPUT test when only one MSI interrupt
|
||||
2. fix error on latest X24 modem
|
||||
|
||||
[V1.3.0.16]
|
||||
Date: 11/18/2020
|
||||
enhancement:
|
||||
fix:
|
||||
1. add ring size to 32, for in-bound chan, if one ring is full, modem will not generate MSI interrupt for all chan
|
||||
|
||||
[V1.3.0.15]
|
||||
Date: 10/30/2020
|
||||
enhancement:
|
||||
1. support multi-modems, named as /dev/mhi_<chan_name>X
|
||||
fix:
|
||||
1. fix compile error on kernel v5.8
|
||||
|
||||
[V1.3.0.14]
|
||||
Date: 10/9/2020
|
||||
enhancement:
|
||||
1. suppport EM120&EM160
|
||||
fix:
|
||||
1. fix compile error on kernel v5.6
|
||||
2. support runtime suspend
|
||||
|
||||
[V1.3.0.13]
|
||||
Date: 9/7/2020
|
||||
enhancement:
|
||||
1. suppport EM120&EM160
|
||||
fix:
|
||||
1. fix error on X55 + PCIE2.0(e.g IPQ4019)
|
||||
2. support runtime suspend
|
||||
|
||||
[V1.3.0.12]
|
||||
Date: 7/7/2020
|
||||
enhancement:
|
||||
1. suppport create only none netcard (enabled by marco MHI_NETDEV_ONE_CARD_MODE),
|
||||
Release Notes
|
||||
[V1.3.7]
|
||||
Date: 27/03/2024
|
||||
enhancement:
|
||||
1. support SDX35's PID/VID
|
||||
2. support IPQ QSDK MHI used with rmnetdata driver
|
||||
|
||||
Release Notes
|
||||
[V1.3.6]
|
||||
Date: 01/08/2023
|
||||
enhancement:
|
||||
1. support Linux Kernel V6.4
|
||||
2. support change mtu
|
||||
fix:
|
||||
1. fix compile error on ipq's spf12.x
|
||||
|
||||
Release Notes
|
||||
[V1.3.5]
|
||||
Date: 25/02/2023
|
||||
enhancement:
|
||||
1. support efuse SDX sleep
|
||||
2. support IPQ9574 SFE
|
||||
fix:
|
||||
1. fix cannot find the node when dialing. Nodes in the /sys/bus/mhi_q/devices directory named hex
|
||||
|
||||
[V1.3.4]
|
||||
Date: 12/8/2022
|
||||
enhancement:
|
||||
1. only allow to enable autosuspend when module is in MHI_EE_AMSS
|
||||
2. show pcie link speed and width when driver probe
|
||||
3. check pcie link status by read pcie vid and pid when driver probe,
|
||||
if pcie link is down, return -EIO
|
||||
4. support RM520 (1eac:1004)
|
||||
5. support qmap command packet
|
||||
fix:
|
||||
1. fix tx queue is wrong stop when do uplink TPUT
|
||||
2. fix after QFirehose, module fail to bootup at very small probability
|
||||
3. mhi uci add mutex lock for concurrent reads/writes
|
||||
|
||||
[V1.3.3]
|
||||
Date: 30/6/2022
|
||||
enhancement:
|
||||
1. remove one un-necessary kmalloc when do qfirehose
|
||||
2. support mhi monitor (like usbmon), usage: cat /sys/kernel/debug/mhi_q/0306_00\:01.00/mhimon
|
||||
3. set ring size of event 0 to 256 (from 1024), required by x6x
|
||||
4. support PCIE local network card mhi_swip0 (chan 46/47), default disabled
|
||||
5. porting IPQ5018 mhi rate controll code from spf11.5
|
||||
6. set pcie rmnet download max qmap packet size to 15KB (same to IPQ MHI Driver)
|
||||
7. support set different mac address for rmnet net card
|
||||
8. when mhi netdev fail to malloc, use delay_work instead work
|
||||
9. optimize code for 'when driver load, modem is still in MHI_EE_PTHRU'
|
||||
fix:
|
||||
1. Fix not synchronize access rp/wp when mhi_queue_xxx and mhi_process_xxx_ring run on different CPU
|
||||
2. set dma mask when driver probe, some SOC like rpi_4 need it
|
||||
|
||||
[V1.3.2]
|
||||
Date: 12/16/2021
|
||||
enhancement:
|
||||
1. support Linux Kernel V5.14
|
||||
2. mhi_netdev_quectel.c do not print log in softirq context
|
||||
|
||||
[V1.3.1]
|
||||
Date: 9/26/2021
|
||||
enhancement:
|
||||
fix:
|
||||
|
||||
[V1.3.0.19]
|
||||
Date: 9/18/2021
|
||||
enhancement:
|
||||
1. support sdx62 (17cb:0308)
|
||||
2. support IPQ5018's NSS
|
||||
3. use 'qsdk/qca/src/data-kernel/drivers/rmnet-nss/rmnet_nss.c' instead myself rmnet_nss.c
|
||||
and pcie_mhi.ko must load after then rmnet_nss.ko
|
||||
4. allow bhi irq is not 0 (for ipq5018)
|
||||
fix:
|
||||
|
||||
[V1.3.0.18]
|
||||
Date: 4/14/2021
|
||||
enhancement:
|
||||
1. support mbim multiple call, usage:
|
||||
# insmod pcie_mhi.ko mhi_mbim_enabeld=1 qmap_mode=4
|
||||
# quectel-mbim-proxy -d /dev/mhi_MBIM &
|
||||
# quectel-CM -n X
|
||||
fix:
|
||||
|
||||
[V1.3.0.17]
|
||||
Date: 3/11/2021
|
||||
enhancement:
|
||||
fix:
|
||||
1. fix CPU loading very high when TPUT test when only one MSI interrupt
|
||||
2. fix error on latest X24 modem
|
||||
|
||||
[V1.3.0.16]
|
||||
Date: 11/18/2020
|
||||
enhancement:
|
||||
fix:
|
||||
1. add ring size to 32, for in-bound chan, if one ring is full, modem will not generate MSI interrupt for all chan
|
||||
|
||||
[V1.3.0.15]
|
||||
Date: 10/30/2020
|
||||
enhancement:
|
||||
1. support multi-modems, named as /dev/mhi_<chan_name>X
|
||||
fix:
|
||||
1. fix compile error on kernel v5.8
|
||||
|
||||
[V1.3.0.14]
|
||||
Date: 10/9/2020
|
||||
enhancement:
|
||||
1. suppport EM120&EM160
|
||||
fix:
|
||||
1. fix compile error on kernel v5.6
|
||||
2. support runtime suspend
|
||||
|
||||
[V1.3.0.13]
|
||||
Date: 9/7/2020
|
||||
enhancement:
|
||||
1. suppport EM120&EM160
|
||||
fix:
|
||||
1. fix error on X55 + PCIE2.0(e.g IPQ4019)
|
||||
2. support runtime suspend
|
||||
|
||||
[V1.3.0.12]
|
||||
Date: 7/7/2020
|
||||
enhancement:
|
||||
1. suppport create only none netcard (enabled by marco MHI_NETDEV_ONE_CARD_MODE),
|
||||
fix:
|
File diff suppressed because it is too large
Load Diff
@ -1,92 +1,92 @@
|
||||
/* Copyright (c) 2018, 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 _MHI_QCOM_
|
||||
#define _MHI_QCOM_
|
||||
|
||||
/* iova cfg bitmask */
|
||||
#define MHI_SMMU_ATTACH BIT(0)
|
||||
#define MHI_SMMU_S1_BYPASS BIT(1)
|
||||
#define MHI_SMMU_FAST BIT(2)
|
||||
#define MHI_SMMU_ATOMIC BIT(3)
|
||||
#define MHI_SMMU_FORCE_COHERENT BIT(4)
|
||||
|
||||
#define MHI_PCIE_VENDOR_ID (0x17cb)
|
||||
#define MHI_PCIE_DEBUG_ID (0xffff)
|
||||
#define MHI_RPM_SUSPEND_TMR_MS (3000)
|
||||
#define MHI_PCI_BAR_NUM (0)
|
||||
|
||||
struct mhi_dev {
|
||||
struct pci_dev *pci_dev;
|
||||
u32 smmu_cfg;
|
||||
int resn;
|
||||
void *arch_info;
|
||||
bool powered_on;
|
||||
bool debug_mode;
|
||||
};
|
||||
|
||||
void mhi_deinit_pci_dev(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_pci_probe(struct pci_dev *pci_dev,
|
||||
const struct pci_device_id *device_id);
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION( 3,10,65 ))
|
||||
static inline int dma_set_mask_and_coherent(struct device *dev, u64 mask)
|
||||
{
|
||||
int rc = dma_set_mask(dev, mask);
|
||||
if (rc == 0)
|
||||
dma_set_coherent_mask(dev, mask);
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int mhi_arch_iommu_init(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
|
||||
mhi_cntrl->dev = &mhi_dev->pci_dev->dev;
|
||||
|
||||
return dma_set_mask_and_coherent(mhi_cntrl->dev, DMA_BIT_MASK(64));
|
||||
}
|
||||
|
||||
static inline void mhi_arch_iommu_deinit(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int mhi_arch_pcie_init(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void mhi_arch_pcie_deinit(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int mhi_arch_platform_init(struct mhi_dev *mhi_dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void mhi_arch_platform_deinit(struct mhi_dev *mhi_dev)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int mhi_arch_link_off(struct mhi_controller *mhi_cntrl,
|
||||
bool graceful)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int mhi_arch_link_on(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* _MHI_QCOM_ */
|
||||
/* Copyright (c) 2018, 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 _MHI_QCOM_
|
||||
#define _MHI_QCOM_
|
||||
|
||||
/* iova cfg bitmask */
|
||||
#define MHI_SMMU_ATTACH BIT(0)
|
||||
#define MHI_SMMU_S1_BYPASS BIT(1)
|
||||
#define MHI_SMMU_FAST BIT(2)
|
||||
#define MHI_SMMU_ATOMIC BIT(3)
|
||||
#define MHI_SMMU_FORCE_COHERENT BIT(4)
|
||||
|
||||
#define MHI_PCIE_VENDOR_ID (0x17cb)
|
||||
#define MHI_PCIE_DEBUG_ID (0xffff)
|
||||
#define MHI_RPM_SUSPEND_TMR_MS (3000)
|
||||
#define MHI_PCI_BAR_NUM (0)
|
||||
|
||||
struct mhi_dev {
|
||||
struct pci_dev *pci_dev;
|
||||
u32 smmu_cfg;
|
||||
int resn;
|
||||
void *arch_info;
|
||||
bool powered_on;
|
||||
bool debug_mode;
|
||||
};
|
||||
|
||||
void mhi_deinit_pci_dev(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_pci_probe(struct pci_dev *pci_dev,
|
||||
const struct pci_device_id *device_id);
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION( 3,10,65 ))
|
||||
static inline int dma_set_mask_and_coherent(struct device *dev, u64 mask)
|
||||
{
|
||||
int rc = dma_set_mask(dev, mask);
|
||||
if (rc == 0)
|
||||
dma_set_coherent_mask(dev, mask);
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int mhi_arch_iommu_init(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
|
||||
mhi_cntrl->dev = &mhi_dev->pci_dev->dev;
|
||||
|
||||
return dma_set_mask_and_coherent(mhi_cntrl->dev, DMA_BIT_MASK(64));
|
||||
}
|
||||
|
||||
static inline void mhi_arch_iommu_deinit(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int mhi_arch_pcie_init(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void mhi_arch_pcie_deinit(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int mhi_arch_platform_init(struct mhi_dev *mhi_dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void mhi_arch_platform_deinit(struct mhi_dev *mhi_dev)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int mhi_arch_link_off(struct mhi_controller *mhi_cntrl,
|
||||
bool graceful)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int mhi_arch_link_on(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* _MHI_QCOM_ */
|
||||
|
@ -1066,9 +1066,11 @@ static struct pci_device_id mhi_pcie_device_id[] = {
|
||||
{PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0305)}, //SDX24
|
||||
{PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0306)}, //SDX55
|
||||
{PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0308)}, //SDX62
|
||||
{PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x011a)}, //SDX35
|
||||
{PCI_DEVICE(0x1eac, 0x1001)}, //EM120
|
||||
{PCI_DEVICE(0x1eac, 0x1002)}, //EM160
|
||||
{PCI_DEVICE(0x1eac, 0x1004)}, //RM520
|
||||
{PCI_DEVICE(0x1eac, 0x100b)}, //RM255
|
||||
{PCI_DEVICE(MHI_PCIE_VENDOR_ID, MHI_PCIE_DEBUG_ID)},
|
||||
{0},
|
||||
};
|
||||
|
@ -4,7 +4,7 @@
|
||||
#ifndef _MHI_H_
|
||||
#define _MHI_H_
|
||||
|
||||
#define PCIE_MHI_DRIVER_VERSION "V1.3.6"
|
||||
#define PCIE_MHI_DRIVER_VERSION "V1.3.7"
|
||||
#define ENABLE_MHI_MON
|
||||
//#define ENABLE_IP_SW0
|
||||
|
||||
|
@ -1642,7 +1642,7 @@ static int of_parse_ev_cfg(struct mhi_controller *mhi_cntrl,
|
||||
root@OpenWrt:/# cat /proc/interrupts | grep mhi
|
||||
root@OpenWrt:/# cat /sys/kernel/debug/mhi_q/mhi_netdev/pcie_mhi_0306_00.01.00_0/rx_int
|
||||
*/
|
||||
if (i == IPA_IN_EVENT_RING)
|
||||
if (i == IPA_IN_EVENT_RING || i == IPA_OUT_EVENT_RING)
|
||||
mhi_event->intmod = 5;
|
||||
|
||||
#ifdef ENABLE_IP_SW0
|
||||
@ -1828,6 +1828,7 @@ static struct chan_cfg_t chan_cfg[] = {
|
||||
};
|
||||
|
||||
extern int mhi_netdev_mbin_enabled(void);
|
||||
extern int mhi_netdev_use_xfer_type_dma(unsigned chan);
|
||||
static int of_parse_ch_cfg(struct mhi_controller *mhi_cntrl,
|
||||
struct device_node *of_node)
|
||||
{
|
||||
@ -1942,7 +1943,9 @@ static int of_parse_ch_cfg(struct mhi_controller *mhi_cntrl,
|
||||
|
||||
if (chan == MHI_CLIENT_IP_HW_0_OUT || chan == MHI_CLIENT_IP_SW_0_OUT)
|
||||
mhi_chan->xfer_type = MHI_XFER_SKB;
|
||||
else if (chan == MHI_CLIENT_IP_HW_0_IN || chan == MHI_CLIENT_IP_SW_0_IN)
|
||||
else if (chan == MHI_CLIENT_IP_HW_0_IN)
|
||||
mhi_chan->xfer_type = mhi_netdev_use_xfer_type_dma(chan) ? MHI_XFER_DMA: MHI_XFER_SKB;
|
||||
else if (chan == MHI_CLIENT_IP_SW_0_IN)
|
||||
mhi_chan->xfer_type = MHI_XFER_SKB; //MHI_XFER_DMA;
|
||||
#ifdef ENABLE_ADPL
|
||||
else if (chan == MHI_CLIENT_ADPL)
|
||||
|
@ -1,362 +1,362 @@
|
||||
#ifndef __SDX20_MHI_H
|
||||
#define __SDX20_MHI_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* MHI control data structures alloted by the host, including
|
||||
* channel context array, event context array, command context and rings */
|
||||
|
||||
/* Channel context state */
|
||||
enum mhi_dev_ch_ctx_state {
|
||||
MHI_DEV_CH_STATE_DISABLED,
|
||||
MHI_DEV_CH_STATE_ENABLED,
|
||||
MHI_DEV_CH_STATE_RUNNING,
|
||||
MHI_DEV_CH_STATE_SUSPENDED,
|
||||
MHI_DEV_CH_STATE_STOP,
|
||||
MHI_DEV_CH_STATE_ERROR,
|
||||
MHI_DEV_CH_STATE_RESERVED,
|
||||
MHI_DEV_CH_STATE_32BIT = 0x7FFFFFFF
|
||||
};
|
||||
|
||||
/* Channel type */
|
||||
enum mhi_dev_ch_ctx_type {
|
||||
MHI_DEV_CH_TYPE_NONE,
|
||||
MHI_DEV_CH_TYPE_OUTBOUND_CHANNEL,
|
||||
MHI_DEV_CH_TYPE_INBOUND_CHANNEL,
|
||||
MHI_DEV_CH_RESERVED
|
||||
};
|
||||
|
||||
/* Channel context type */
|
||||
struct mhi_dev_ch_ctx {
|
||||
enum mhi_dev_ch_ctx_state ch_state;
|
||||
enum mhi_dev_ch_ctx_type ch_type;
|
||||
uint32_t err_indx;
|
||||
uint64_t rbase;
|
||||
uint64_t rlen;
|
||||
uint64_t rp;
|
||||
uint64_t wp;
|
||||
} __packed;
|
||||
|
||||
enum mhi_dev_ring_element_type_id {
|
||||
MHI_DEV_RING_EL_INVALID = 0,
|
||||
MHI_DEV_RING_EL_NOOP = 1,
|
||||
MHI_DEV_RING_EL_TRANSFER = 2,
|
||||
MHI_DEV_RING_EL_RESET = 16,
|
||||
MHI_DEV_RING_EL_STOP = 17,
|
||||
MHI_DEV_RING_EL_START = 18,
|
||||
MHI_DEV_RING_EL_MHI_STATE_CHG = 32,
|
||||
MHI_DEV_RING_EL_CMD_COMPLETION_EVT = 33,
|
||||
MHI_DEV_RING_EL_TRANSFER_COMPLETION_EVENT = 34,
|
||||
MHI_DEV_RING_EL_EE_STATE_CHANGE_NOTIFY = 64,
|
||||
MHI_DEV_RING_EL_UNDEF
|
||||
};
|
||||
|
||||
enum mhi_dev_ring_state {
|
||||
RING_STATE_UINT = 0,
|
||||
RING_STATE_IDLE,
|
||||
RING_STATE_PENDING,
|
||||
};
|
||||
|
||||
enum mhi_dev_ring_type {
|
||||
RING_TYPE_CMD = 0,
|
||||
RING_TYPE_ER,
|
||||
RING_TYPE_CH,
|
||||
RING_TYPE_INVAL
|
||||
};
|
||||
|
||||
/* Event context interrupt moderation */
|
||||
enum mhi_dev_evt_ctx_int_mod_timer {
|
||||
MHI_DEV_EVT_INT_MODERATION_DISABLED
|
||||
};
|
||||
|
||||
/* Event ring type */
|
||||
enum mhi_dev_evt_ctx_event_ring_type {
|
||||
MHI_DEV_EVT_TYPE_DEFAULT,
|
||||
MHI_DEV_EVT_TYPE_VALID,
|
||||
MHI_DEV_EVT_RESERVED
|
||||
};
|
||||
|
||||
/* Event ring context type */
|
||||
struct mhi_dev_ev_ctx {
|
||||
uint32_t res1:16;
|
||||
enum mhi_dev_evt_ctx_int_mod_timer intmodt:16;
|
||||
enum mhi_dev_evt_ctx_event_ring_type ertype;
|
||||
uint32_t msivec;
|
||||
uint64_t rbase;
|
||||
uint64_t rlen;
|
||||
uint64_t rp;
|
||||
uint64_t wp;
|
||||
} __packed;
|
||||
|
||||
/* Command context */
|
||||
struct mhi_dev_cmd_ctx {
|
||||
uint32_t res1;
|
||||
uint32_t res2;
|
||||
uint32_t res3;
|
||||
uint64_t rbase;
|
||||
uint64_t rlen;
|
||||
uint64_t rp;
|
||||
uint64_t wp;
|
||||
} __packed;
|
||||
|
||||
/* generic context */
|
||||
struct mhi_dev_gen_ctx {
|
||||
uint32_t res1;
|
||||
uint32_t res2;
|
||||
uint32_t res3;
|
||||
uint64_t rbase;
|
||||
uint64_t rlen;
|
||||
uint64_t rp;
|
||||
uint64_t wp;
|
||||
} __packed;
|
||||
|
||||
/* Transfer ring element */
|
||||
struct mhi_dev_transfer_ring_element {
|
||||
uint64_t data_buf_ptr;
|
||||
uint32_t len:16;
|
||||
uint32_t res1:16;
|
||||
uint32_t chain:1;
|
||||
uint32_t res2:7;
|
||||
uint32_t ieob:1;
|
||||
uint32_t ieot:1;
|
||||
uint32_t bei:1;
|
||||
uint32_t res3:5;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t res4:8;
|
||||
} __packed;
|
||||
|
||||
/* Command ring element */
|
||||
/* Command ring No op command */
|
||||
struct mhi_dev_cmd_ring_op {
|
||||
uint64_t res1;
|
||||
uint32_t res2;
|
||||
uint32_t res3:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
/* Command ring reset channel command */
|
||||
struct mhi_dev_cmd_ring_reset_channel_cmd {
|
||||
uint64_t res1;
|
||||
uint32_t res2;
|
||||
uint32_t res3:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
/* Command ring stop channel command */
|
||||
struct mhi_dev_cmd_ring_stop_channel_cmd {
|
||||
uint64_t res1;
|
||||
uint32_t res2;
|
||||
uint32_t res3:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
/* Command ring start channel command */
|
||||
struct mhi_dev_cmd_ring_start_channel_cmd {
|
||||
uint64_t res1;
|
||||
uint32_t seqnum;
|
||||
uint32_t reliable:1;
|
||||
uint32_t res2:15;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
enum mhi_dev_cmd_completion_code {
|
||||
MHI_CMD_COMPL_CODE_INVALID = 0,
|
||||
MHI_CMD_COMPL_CODE_SUCCESS = 1,
|
||||
MHI_CMD_COMPL_CODE_EOT = 2,
|
||||
MHI_CMD_COMPL_CODE_OVERFLOW = 3,
|
||||
MHI_CMD_COMPL_CODE_EOB = 4,
|
||||
MHI_CMD_COMPL_CODE_UNDEFINED = 16,
|
||||
MHI_CMD_COMPL_CODE_RING_EL = 17,
|
||||
MHI_CMD_COMPL_CODE_RES
|
||||
};
|
||||
|
||||
/* Event ring elements */
|
||||
/* Transfer completion event */
|
||||
struct mhi_dev_event_ring_transfer_completion {
|
||||
uint64_t ptr;
|
||||
uint32_t len:16;
|
||||
uint32_t res1:8;
|
||||
enum mhi_dev_cmd_completion_code code:8;
|
||||
uint32_t res2:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
/* Command completion event */
|
||||
struct mhi_dev_event_ring_cmd_completion {
|
||||
uint64_t ptr;
|
||||
uint32_t res1:24;
|
||||
enum mhi_dev_cmd_completion_code code:8;
|
||||
uint32_t res2:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t res3:8;
|
||||
} __packed;
|
||||
|
||||
enum mhi_dev_state {
|
||||
MHI_DEV_RESET_STATE = 0,
|
||||
MHI_DEV_READY_STATE,
|
||||
MHI_DEV_M0_STATE,
|
||||
MHI_DEV_M1_STATE,
|
||||
MHI_DEV_M2_STATE,
|
||||
MHI_DEV_M3_STATE,
|
||||
MHI_DEV_MAX_STATE,
|
||||
MHI_DEV_SYSERR_STATE = 0xff
|
||||
};
|
||||
|
||||
/* MHI state change event */
|
||||
struct mhi_dev_event_ring_state_change {
|
||||
uint64_t ptr;
|
||||
uint32_t res1:24;
|
||||
enum mhi_dev_state mhistate:8;
|
||||
uint32_t res2:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t res3:8;
|
||||
} __packed;
|
||||
|
||||
enum mhi_dev_execenv {
|
||||
MHI_DEV_SBL_EE = 1,
|
||||
MHI_DEV_AMSS_EE = 2,
|
||||
MHI_DEV_UNRESERVED
|
||||
};
|
||||
|
||||
/* EE state change event */
|
||||
struct mhi_dev_event_ring_ee_state_change {
|
||||
uint64_t ptr;
|
||||
uint32_t res1:24;
|
||||
enum mhi_dev_execenv execenv:8;
|
||||
uint32_t res2:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t res3:8;
|
||||
} __packed;
|
||||
|
||||
/* Generic cmd to parse common details like type and channel id */
|
||||
struct mhi_dev_ring_generic {
|
||||
uint64_t ptr;
|
||||
uint32_t res1:24;
|
||||
enum mhi_dev_state mhistate:8;
|
||||
uint32_t res2:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
struct mhi_config {
|
||||
uint32_t mhi_reg_len;
|
||||
uint32_t version;
|
||||
uint32_t event_rings;
|
||||
uint32_t channels;
|
||||
uint32_t chdb_offset;
|
||||
uint32_t erdb_offset;
|
||||
};
|
||||
|
||||
#define NUM_CHANNELS 128
|
||||
#define HW_CHANNEL_BASE 100
|
||||
#define HW_CHANNEL_END 107
|
||||
#define MHI_ENV_VALUE 2
|
||||
#define MHI_MASK_ROWS_CH_EV_DB 4
|
||||
#define TRB_MAX_DATA_SIZE 8192
|
||||
#define MHI_CTRL_STATE 25
|
||||
#define IPA_DMA_SYNC 1
|
||||
#define IPA_DMA_ASYNC 0
|
||||
|
||||
/*maximum trasnfer completion events buffer*/
|
||||
#define MAX_TR_EVENTS 50
|
||||
/*maximum event requests */
|
||||
#define MHI_MAX_EVT_REQ 50
|
||||
|
||||
/* Possible ring element types */
|
||||
union mhi_dev_ring_element_type {
|
||||
struct mhi_dev_cmd_ring_op cmd_no_op;
|
||||
struct mhi_dev_cmd_ring_reset_channel_cmd cmd_reset;
|
||||
struct mhi_dev_cmd_ring_stop_channel_cmd cmd_stop;
|
||||
struct mhi_dev_cmd_ring_start_channel_cmd cmd_start;
|
||||
struct mhi_dev_transfer_ring_element cmd_transfer;
|
||||
struct mhi_dev_event_ring_transfer_completion evt_tr_comp;
|
||||
struct mhi_dev_event_ring_cmd_completion evt_cmd_comp;
|
||||
struct mhi_dev_event_ring_state_change evt_state_change;
|
||||
struct mhi_dev_event_ring_ee_state_change evt_ee_state;
|
||||
struct mhi_dev_ring_generic generic;
|
||||
};
|
||||
|
||||
/* Transfer ring element type */
|
||||
union mhi_dev_ring_ctx {
|
||||
struct mhi_dev_cmd_ctx cmd;
|
||||
struct mhi_dev_ev_ctx ev;
|
||||
struct mhi_dev_ch_ctx ch;
|
||||
struct mhi_dev_gen_ctx generic;
|
||||
};
|
||||
|
||||
/* MHI host Control and data address region */
|
||||
struct mhi_host_addr {
|
||||
uint32_t ctrl_base_lsb;
|
||||
uint32_t ctrl_base_msb;
|
||||
uint32_t ctrl_limit_lsb;
|
||||
uint32_t ctrl_limit_msb;
|
||||
uint32_t data_base_lsb;
|
||||
uint32_t data_base_msb;
|
||||
uint32_t data_limit_lsb;
|
||||
uint32_t data_limit_msb;
|
||||
};
|
||||
|
||||
/* MHI physical and virtual address region */
|
||||
struct mhi_meminfo {
|
||||
struct device *dev;
|
||||
uintptr_t pa_aligned;
|
||||
uintptr_t pa_unaligned;
|
||||
uintptr_t va_aligned;
|
||||
uintptr_t va_unaligned;
|
||||
uintptr_t size;
|
||||
};
|
||||
|
||||
struct mhi_addr {
|
||||
uint64_t host_pa;
|
||||
uintptr_t device_pa;
|
||||
uintptr_t device_va;
|
||||
size_t size;
|
||||
dma_addr_t phy_addr;
|
||||
void *virt_addr;
|
||||
bool use_ipa_dma;
|
||||
};
|
||||
|
||||
struct mhi_interrupt_state {
|
||||
uint32_t mask;
|
||||
uint32_t status;
|
||||
};
|
||||
|
||||
enum mhi_dev_channel_state {
|
||||
MHI_DEV_CH_UNINT,
|
||||
MHI_DEV_CH_STARTED,
|
||||
MHI_DEV_CH_PENDING_START,
|
||||
MHI_DEV_CH_PENDING_STOP,
|
||||
MHI_DEV_CH_STOPPED,
|
||||
MHI_DEV_CH_CLOSED,
|
||||
};
|
||||
|
||||
enum mhi_dev_ch_operation {
|
||||
MHI_DEV_OPEN_CH,
|
||||
MHI_DEV_CLOSE_CH,
|
||||
MHI_DEV_READ_CH,
|
||||
MHI_DEV_READ_WR,
|
||||
MHI_DEV_POLL,
|
||||
};
|
||||
|
||||
enum mhi_ctrl_info {
|
||||
MHI_STATE_CONFIGURED = 0,
|
||||
MHI_STATE_CONNECTED = 1,
|
||||
MHI_STATE_DISCONNECTED = 2,
|
||||
MHI_STATE_INVAL,
|
||||
};
|
||||
|
||||
enum mhi_dev_tr_compl_evt_type {
|
||||
SEND_EVENT_BUFFER,
|
||||
SEND_EVENT_RD_OFFSET,
|
||||
};
|
||||
|
||||
enum mhi_dev_transfer_type {
|
||||
MHI_DEV_DMA_SYNC,
|
||||
MHI_DEV_DMA_ASYNC,
|
||||
};
|
||||
#endif /* _SDX20_MHI_H_ */
|
||||
#ifndef __SDX20_MHI_H
|
||||
#define __SDX20_MHI_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* MHI control data structures alloted by the host, including
|
||||
* channel context array, event context array, command context and rings */
|
||||
|
||||
/* Channel context state */
|
||||
enum mhi_dev_ch_ctx_state {
|
||||
MHI_DEV_CH_STATE_DISABLED,
|
||||
MHI_DEV_CH_STATE_ENABLED,
|
||||
MHI_DEV_CH_STATE_RUNNING,
|
||||
MHI_DEV_CH_STATE_SUSPENDED,
|
||||
MHI_DEV_CH_STATE_STOP,
|
||||
MHI_DEV_CH_STATE_ERROR,
|
||||
MHI_DEV_CH_STATE_RESERVED,
|
||||
MHI_DEV_CH_STATE_32BIT = 0x7FFFFFFF
|
||||
};
|
||||
|
||||
/* Channel type */
|
||||
enum mhi_dev_ch_ctx_type {
|
||||
MHI_DEV_CH_TYPE_NONE,
|
||||
MHI_DEV_CH_TYPE_OUTBOUND_CHANNEL,
|
||||
MHI_DEV_CH_TYPE_INBOUND_CHANNEL,
|
||||
MHI_DEV_CH_RESERVED
|
||||
};
|
||||
|
||||
/* Channel context type */
|
||||
struct mhi_dev_ch_ctx {
|
||||
enum mhi_dev_ch_ctx_state ch_state;
|
||||
enum mhi_dev_ch_ctx_type ch_type;
|
||||
uint32_t err_indx;
|
||||
uint64_t rbase;
|
||||
uint64_t rlen;
|
||||
uint64_t rp;
|
||||
uint64_t wp;
|
||||
} __packed;
|
||||
|
||||
enum mhi_dev_ring_element_type_id {
|
||||
MHI_DEV_RING_EL_INVALID = 0,
|
||||
MHI_DEV_RING_EL_NOOP = 1,
|
||||
MHI_DEV_RING_EL_TRANSFER = 2,
|
||||
MHI_DEV_RING_EL_RESET = 16,
|
||||
MHI_DEV_RING_EL_STOP = 17,
|
||||
MHI_DEV_RING_EL_START = 18,
|
||||
MHI_DEV_RING_EL_MHI_STATE_CHG = 32,
|
||||
MHI_DEV_RING_EL_CMD_COMPLETION_EVT = 33,
|
||||
MHI_DEV_RING_EL_TRANSFER_COMPLETION_EVENT = 34,
|
||||
MHI_DEV_RING_EL_EE_STATE_CHANGE_NOTIFY = 64,
|
||||
MHI_DEV_RING_EL_UNDEF
|
||||
};
|
||||
|
||||
enum mhi_dev_ring_state {
|
||||
RING_STATE_UINT = 0,
|
||||
RING_STATE_IDLE,
|
||||
RING_STATE_PENDING,
|
||||
};
|
||||
|
||||
enum mhi_dev_ring_type {
|
||||
RING_TYPE_CMD = 0,
|
||||
RING_TYPE_ER,
|
||||
RING_TYPE_CH,
|
||||
RING_TYPE_INVAL
|
||||
};
|
||||
|
||||
/* Event context interrupt moderation */
|
||||
enum mhi_dev_evt_ctx_int_mod_timer {
|
||||
MHI_DEV_EVT_INT_MODERATION_DISABLED
|
||||
};
|
||||
|
||||
/* Event ring type */
|
||||
enum mhi_dev_evt_ctx_event_ring_type {
|
||||
MHI_DEV_EVT_TYPE_DEFAULT,
|
||||
MHI_DEV_EVT_TYPE_VALID,
|
||||
MHI_DEV_EVT_RESERVED
|
||||
};
|
||||
|
||||
/* Event ring context type */
|
||||
struct mhi_dev_ev_ctx {
|
||||
uint32_t res1:16;
|
||||
enum mhi_dev_evt_ctx_int_mod_timer intmodt:16;
|
||||
enum mhi_dev_evt_ctx_event_ring_type ertype;
|
||||
uint32_t msivec;
|
||||
uint64_t rbase;
|
||||
uint64_t rlen;
|
||||
uint64_t rp;
|
||||
uint64_t wp;
|
||||
} __packed;
|
||||
|
||||
/* Command context */
|
||||
struct mhi_dev_cmd_ctx {
|
||||
uint32_t res1;
|
||||
uint32_t res2;
|
||||
uint32_t res3;
|
||||
uint64_t rbase;
|
||||
uint64_t rlen;
|
||||
uint64_t rp;
|
||||
uint64_t wp;
|
||||
} __packed;
|
||||
|
||||
/* generic context */
|
||||
struct mhi_dev_gen_ctx {
|
||||
uint32_t res1;
|
||||
uint32_t res2;
|
||||
uint32_t res3;
|
||||
uint64_t rbase;
|
||||
uint64_t rlen;
|
||||
uint64_t rp;
|
||||
uint64_t wp;
|
||||
} __packed;
|
||||
|
||||
/* Transfer ring element */
|
||||
struct mhi_dev_transfer_ring_element {
|
||||
uint64_t data_buf_ptr;
|
||||
uint32_t len:16;
|
||||
uint32_t res1:16;
|
||||
uint32_t chain:1;
|
||||
uint32_t res2:7;
|
||||
uint32_t ieob:1;
|
||||
uint32_t ieot:1;
|
||||
uint32_t bei:1;
|
||||
uint32_t res3:5;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t res4:8;
|
||||
} __packed;
|
||||
|
||||
/* Command ring element */
|
||||
/* Command ring No op command */
|
||||
struct mhi_dev_cmd_ring_op {
|
||||
uint64_t res1;
|
||||
uint32_t res2;
|
||||
uint32_t res3:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
/* Command ring reset channel command */
|
||||
struct mhi_dev_cmd_ring_reset_channel_cmd {
|
||||
uint64_t res1;
|
||||
uint32_t res2;
|
||||
uint32_t res3:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
/* Command ring stop channel command */
|
||||
struct mhi_dev_cmd_ring_stop_channel_cmd {
|
||||
uint64_t res1;
|
||||
uint32_t res2;
|
||||
uint32_t res3:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
/* Command ring start channel command */
|
||||
struct mhi_dev_cmd_ring_start_channel_cmd {
|
||||
uint64_t res1;
|
||||
uint32_t seqnum;
|
||||
uint32_t reliable:1;
|
||||
uint32_t res2:15;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
enum mhi_dev_cmd_completion_code {
|
||||
MHI_CMD_COMPL_CODE_INVALID = 0,
|
||||
MHI_CMD_COMPL_CODE_SUCCESS = 1,
|
||||
MHI_CMD_COMPL_CODE_EOT = 2,
|
||||
MHI_CMD_COMPL_CODE_OVERFLOW = 3,
|
||||
MHI_CMD_COMPL_CODE_EOB = 4,
|
||||
MHI_CMD_COMPL_CODE_UNDEFINED = 16,
|
||||
MHI_CMD_COMPL_CODE_RING_EL = 17,
|
||||
MHI_CMD_COMPL_CODE_RES
|
||||
};
|
||||
|
||||
/* Event ring elements */
|
||||
/* Transfer completion event */
|
||||
struct mhi_dev_event_ring_transfer_completion {
|
||||
uint64_t ptr;
|
||||
uint32_t len:16;
|
||||
uint32_t res1:8;
|
||||
enum mhi_dev_cmd_completion_code code:8;
|
||||
uint32_t res2:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
/* Command completion event */
|
||||
struct mhi_dev_event_ring_cmd_completion {
|
||||
uint64_t ptr;
|
||||
uint32_t res1:24;
|
||||
enum mhi_dev_cmd_completion_code code:8;
|
||||
uint32_t res2:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t res3:8;
|
||||
} __packed;
|
||||
|
||||
enum mhi_dev_state {
|
||||
MHI_DEV_RESET_STATE = 0,
|
||||
MHI_DEV_READY_STATE,
|
||||
MHI_DEV_M0_STATE,
|
||||
MHI_DEV_M1_STATE,
|
||||
MHI_DEV_M2_STATE,
|
||||
MHI_DEV_M3_STATE,
|
||||
MHI_DEV_MAX_STATE,
|
||||
MHI_DEV_SYSERR_STATE = 0xff
|
||||
};
|
||||
|
||||
/* MHI state change event */
|
||||
struct mhi_dev_event_ring_state_change {
|
||||
uint64_t ptr;
|
||||
uint32_t res1:24;
|
||||
enum mhi_dev_state mhistate:8;
|
||||
uint32_t res2:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t res3:8;
|
||||
} __packed;
|
||||
|
||||
enum mhi_dev_execenv {
|
||||
MHI_DEV_SBL_EE = 1,
|
||||
MHI_DEV_AMSS_EE = 2,
|
||||
MHI_DEV_UNRESERVED
|
||||
};
|
||||
|
||||
/* EE state change event */
|
||||
struct mhi_dev_event_ring_ee_state_change {
|
||||
uint64_t ptr;
|
||||
uint32_t res1:24;
|
||||
enum mhi_dev_execenv execenv:8;
|
||||
uint32_t res2:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t res3:8;
|
||||
} __packed;
|
||||
|
||||
/* Generic cmd to parse common details like type and channel id */
|
||||
struct mhi_dev_ring_generic {
|
||||
uint64_t ptr;
|
||||
uint32_t res1:24;
|
||||
enum mhi_dev_state mhistate:8;
|
||||
uint32_t res2:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
struct mhi_config {
|
||||
uint32_t mhi_reg_len;
|
||||
uint32_t version;
|
||||
uint32_t event_rings;
|
||||
uint32_t channels;
|
||||
uint32_t chdb_offset;
|
||||
uint32_t erdb_offset;
|
||||
};
|
||||
|
||||
#define NUM_CHANNELS 128
|
||||
#define HW_CHANNEL_BASE 100
|
||||
#define HW_CHANNEL_END 107
|
||||
#define MHI_ENV_VALUE 2
|
||||
#define MHI_MASK_ROWS_CH_EV_DB 4
|
||||
#define TRB_MAX_DATA_SIZE 8192
|
||||
#define MHI_CTRL_STATE 25
|
||||
#define IPA_DMA_SYNC 1
|
||||
#define IPA_DMA_ASYNC 0
|
||||
|
||||
/*maximum trasnfer completion events buffer*/
|
||||
#define MAX_TR_EVENTS 50
|
||||
/*maximum event requests */
|
||||
#define MHI_MAX_EVT_REQ 50
|
||||
|
||||
/* Possible ring element types */
|
||||
union mhi_dev_ring_element_type {
|
||||
struct mhi_dev_cmd_ring_op cmd_no_op;
|
||||
struct mhi_dev_cmd_ring_reset_channel_cmd cmd_reset;
|
||||
struct mhi_dev_cmd_ring_stop_channel_cmd cmd_stop;
|
||||
struct mhi_dev_cmd_ring_start_channel_cmd cmd_start;
|
||||
struct mhi_dev_transfer_ring_element cmd_transfer;
|
||||
struct mhi_dev_event_ring_transfer_completion evt_tr_comp;
|
||||
struct mhi_dev_event_ring_cmd_completion evt_cmd_comp;
|
||||
struct mhi_dev_event_ring_state_change evt_state_change;
|
||||
struct mhi_dev_event_ring_ee_state_change evt_ee_state;
|
||||
struct mhi_dev_ring_generic generic;
|
||||
};
|
||||
|
||||
/* Transfer ring element type */
|
||||
union mhi_dev_ring_ctx {
|
||||
struct mhi_dev_cmd_ctx cmd;
|
||||
struct mhi_dev_ev_ctx ev;
|
||||
struct mhi_dev_ch_ctx ch;
|
||||
struct mhi_dev_gen_ctx generic;
|
||||
};
|
||||
|
||||
/* MHI host Control and data address region */
|
||||
struct mhi_host_addr {
|
||||
uint32_t ctrl_base_lsb;
|
||||
uint32_t ctrl_base_msb;
|
||||
uint32_t ctrl_limit_lsb;
|
||||
uint32_t ctrl_limit_msb;
|
||||
uint32_t data_base_lsb;
|
||||
uint32_t data_base_msb;
|
||||
uint32_t data_limit_lsb;
|
||||
uint32_t data_limit_msb;
|
||||
};
|
||||
|
||||
/* MHI physical and virtual address region */
|
||||
struct mhi_meminfo {
|
||||
struct device *dev;
|
||||
uintptr_t pa_aligned;
|
||||
uintptr_t pa_unaligned;
|
||||
uintptr_t va_aligned;
|
||||
uintptr_t va_unaligned;
|
||||
uintptr_t size;
|
||||
};
|
||||
|
||||
struct mhi_addr {
|
||||
uint64_t host_pa;
|
||||
uintptr_t device_pa;
|
||||
uintptr_t device_va;
|
||||
size_t size;
|
||||
dma_addr_t phy_addr;
|
||||
void *virt_addr;
|
||||
bool use_ipa_dma;
|
||||
};
|
||||
|
||||
struct mhi_interrupt_state {
|
||||
uint32_t mask;
|
||||
uint32_t status;
|
||||
};
|
||||
|
||||
enum mhi_dev_channel_state {
|
||||
MHI_DEV_CH_UNINT,
|
||||
MHI_DEV_CH_STARTED,
|
||||
MHI_DEV_CH_PENDING_START,
|
||||
MHI_DEV_CH_PENDING_STOP,
|
||||
MHI_DEV_CH_STOPPED,
|
||||
MHI_DEV_CH_CLOSED,
|
||||
};
|
||||
|
||||
enum mhi_dev_ch_operation {
|
||||
MHI_DEV_OPEN_CH,
|
||||
MHI_DEV_CLOSE_CH,
|
||||
MHI_DEV_READ_CH,
|
||||
MHI_DEV_READ_WR,
|
||||
MHI_DEV_POLL,
|
||||
};
|
||||
|
||||
enum mhi_ctrl_info {
|
||||
MHI_STATE_CONFIGURED = 0,
|
||||
MHI_STATE_CONNECTED = 1,
|
||||
MHI_STATE_DISCONNECTED = 2,
|
||||
MHI_STATE_INVAL,
|
||||
};
|
||||
|
||||
enum mhi_dev_tr_compl_evt_type {
|
||||
SEND_EVENT_BUFFER,
|
||||
SEND_EVENT_RD_OFFSET,
|
||||
};
|
||||
|
||||
enum mhi_dev_transfer_type {
|
||||
MHI_DEV_DMA_SYNC,
|
||||
MHI_DEV_DMA_ASYNC,
|
||||
};
|
||||
#endif /* _SDX20_MHI_H_ */
|
||||
|
@ -1,426 +1,426 @@
|
||||
#ifndef __SDX20_MHI_H
|
||||
#define __SDX20_MHI_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* MHI control data structures alloted by the host, including
|
||||
* channel context array, event context array, command context and rings */
|
||||
|
||||
/* Channel context state */
|
||||
enum mhi_dev_ch_ctx_state {
|
||||
MHI_DEV_CH_STATE_DISABLED,
|
||||
MHI_DEV_CH_STATE_ENABLED,
|
||||
MHI_DEV_CH_STATE_RUNNING,
|
||||
MHI_DEV_CH_STATE_SUSPENDED,
|
||||
MHI_DEV_CH_STATE_STOP,
|
||||
MHI_DEV_CH_STATE_ERROR,
|
||||
MHI_DEV_CH_STATE_RESERVED,
|
||||
MHI_DEV_CH_STATE_32BIT = 0x7FFFFFFF
|
||||
};
|
||||
|
||||
/* Channel type */
|
||||
enum mhi_dev_ch_ctx_type {
|
||||
MHI_DEV_CH_TYPE_NONE,
|
||||
MHI_DEV_CH_TYPE_OUTBOUND_CHANNEL,
|
||||
MHI_DEV_CH_TYPE_INBOUND_CHANNEL,
|
||||
MHI_DEV_CH_RESERVED
|
||||
};
|
||||
|
||||
/* Channel context type */
|
||||
struct mhi_dev_ch_ctx {
|
||||
enum mhi_dev_ch_ctx_state ch_state;
|
||||
enum mhi_dev_ch_ctx_type ch_type;
|
||||
uint32_t err_indx;
|
||||
uint64_t rbase;
|
||||
uint64_t rlen;
|
||||
uint64_t rp;
|
||||
uint64_t wp;
|
||||
} __packed;
|
||||
|
||||
enum mhi_dev_ring_element_type_id {
|
||||
MHI_DEV_RING_EL_INVALID = 0,
|
||||
MHI_DEV_RING_EL_NOOP = 1,
|
||||
MHI_DEV_RING_EL_TRANSFER = 2,
|
||||
MHI_DEV_RING_EL_RESET = 16,
|
||||
MHI_DEV_RING_EL_STOP = 17,
|
||||
MHI_DEV_RING_EL_START = 18,
|
||||
MHI_DEV_RING_EL_MHI_STATE_CHG = 32,
|
||||
MHI_DEV_RING_EL_CMD_COMPLETION_EVT = 33,
|
||||
MHI_DEV_RING_EL_TRANSFER_COMPLETION_EVENT = 34,
|
||||
MHI_DEV_RING_EL_EE_STATE_CHANGE_NOTIFY = 64,
|
||||
MHI_DEV_RING_EL_UNDEF
|
||||
};
|
||||
|
||||
enum mhi_dev_ring_state {
|
||||
RING_STATE_UINT = 0,
|
||||
RING_STATE_IDLE,
|
||||
RING_STATE_PENDING,
|
||||
};
|
||||
|
||||
enum mhi_dev_ring_type {
|
||||
RING_TYPE_CMD = 0,
|
||||
RING_TYPE_ER,
|
||||
RING_TYPE_CH,
|
||||
RING_TYPE_INVAL
|
||||
};
|
||||
|
||||
/* Event context interrupt moderation */
|
||||
enum mhi_dev_evt_ctx_int_mod_timer {
|
||||
MHI_DEV_EVT_INT_MODERATION_DISABLED
|
||||
};
|
||||
|
||||
/* Event ring type */
|
||||
enum mhi_dev_evt_ctx_event_ring_type {
|
||||
MHI_DEV_EVT_TYPE_DEFAULT,
|
||||
MHI_DEV_EVT_TYPE_VALID,
|
||||
MHI_DEV_EVT_RESERVED
|
||||
};
|
||||
|
||||
/* Event ring context type */
|
||||
struct mhi_dev_ev_ctx {
|
||||
uint32_t res1:16;
|
||||
enum mhi_dev_evt_ctx_int_mod_timer intmodt:16;
|
||||
enum mhi_dev_evt_ctx_event_ring_type ertype;
|
||||
uint32_t msivec;
|
||||
uint64_t rbase;
|
||||
uint64_t rlen;
|
||||
uint64_t rp;
|
||||
uint64_t wp;
|
||||
} __packed;
|
||||
|
||||
/* Command context */
|
||||
struct mhi_dev_cmd_ctx {
|
||||
uint32_t res1;
|
||||
uint32_t res2;
|
||||
uint32_t res3;
|
||||
uint64_t rbase;
|
||||
uint64_t rlen;
|
||||
uint64_t rp;
|
||||
uint64_t wp;
|
||||
} __packed;
|
||||
|
||||
/* generic context */
|
||||
struct mhi_dev_gen_ctx {
|
||||
uint32_t res1;
|
||||
uint32_t res2;
|
||||
uint32_t res3;
|
||||
uint64_t rbase;
|
||||
uint64_t rlen;
|
||||
uint64_t rp;
|
||||
uint64_t wp;
|
||||
} __packed;
|
||||
|
||||
/* Transfer ring element */
|
||||
struct mhi_dev_transfer_ring_element {
|
||||
uint64_t data_buf_ptr;
|
||||
uint32_t len:16;
|
||||
uint32_t res1:16;
|
||||
uint32_t chain:1;
|
||||
uint32_t res2:7;
|
||||
uint32_t ieob:1;
|
||||
uint32_t ieot:1;
|
||||
uint32_t bei:1;
|
||||
uint32_t res3:5;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t res4:8;
|
||||
} __packed;
|
||||
|
||||
/* Command ring element */
|
||||
/* Command ring No op command */
|
||||
struct mhi_dev_cmd_ring_op {
|
||||
uint64_t res1;
|
||||
uint32_t res2;
|
||||
uint32_t res3:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
/* Command ring reset channel command */
|
||||
struct mhi_dev_cmd_ring_reset_channel_cmd {
|
||||
uint64_t res1;
|
||||
uint32_t res2;
|
||||
uint32_t res3:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
/* Command ring stop channel command */
|
||||
struct mhi_dev_cmd_ring_stop_channel_cmd {
|
||||
uint64_t res1;
|
||||
uint32_t res2;
|
||||
uint32_t res3:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
/* Command ring start channel command */
|
||||
struct mhi_dev_cmd_ring_start_channel_cmd {
|
||||
uint64_t res1;
|
||||
uint32_t seqnum;
|
||||
uint32_t reliable:1;
|
||||
uint32_t res2:15;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
enum mhi_dev_cmd_completion_code {
|
||||
MHI_CMD_COMPL_CODE_INVALID = 0,
|
||||
MHI_CMD_COMPL_CODE_SUCCESS = 1,
|
||||
MHI_CMD_COMPL_CODE_EOT = 2,
|
||||
MHI_CMD_COMPL_CODE_OVERFLOW = 3,
|
||||
MHI_CMD_COMPL_CODE_EOB = 4,
|
||||
MHI_CMD_COMPL_CODE_UNDEFINED = 16,
|
||||
MHI_CMD_COMPL_CODE_RING_EL = 17,
|
||||
MHI_CMD_COMPL_CODE_RES
|
||||
};
|
||||
|
||||
/* Event ring elements */
|
||||
/* Transfer completion event */
|
||||
struct mhi_dev_event_ring_transfer_completion {
|
||||
uint64_t ptr;
|
||||
uint32_t len:16;
|
||||
uint32_t res1:8;
|
||||
enum mhi_dev_cmd_completion_code code:8;
|
||||
uint32_t res2:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
/* Command completion event */
|
||||
struct mhi_dev_event_ring_cmd_completion {
|
||||
uint64_t ptr;
|
||||
uint32_t res1:24;
|
||||
enum mhi_dev_cmd_completion_code code:8;
|
||||
uint32_t res2:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t res3:8;
|
||||
} __packed;
|
||||
|
||||
enum mhi_dev_state {
|
||||
MHI_DEV_RESET_STATE = 0,
|
||||
MHI_DEV_READY_STATE,
|
||||
MHI_DEV_M0_STATE,
|
||||
MHI_DEV_M1_STATE,
|
||||
MHI_DEV_M2_STATE,
|
||||
MHI_DEV_M3_STATE,
|
||||
MHI_DEV_MAX_STATE,
|
||||
MHI_DEV_SYSERR_STATE = 0xff
|
||||
};
|
||||
|
||||
/* MHI state change event */
|
||||
struct mhi_dev_event_ring_state_change {
|
||||
uint64_t ptr;
|
||||
uint32_t res1:24;
|
||||
enum mhi_dev_state mhistate:8;
|
||||
uint32_t res2:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t res3:8;
|
||||
} __packed;
|
||||
|
||||
enum mhi_dev_execenv {
|
||||
MHI_DEV_SBL_EE = 1,
|
||||
MHI_DEV_AMSS_EE = 2,
|
||||
MHI_DEV_UNRESERVED
|
||||
};
|
||||
|
||||
/* EE state change event */
|
||||
struct mhi_dev_event_ring_ee_state_change {
|
||||
uint64_t ptr;
|
||||
uint32_t res1:24;
|
||||
enum mhi_dev_execenv execenv:8;
|
||||
uint32_t res2:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t res3:8;
|
||||
} __packed;
|
||||
|
||||
/* Generic cmd to parse common details like type and channel id */
|
||||
struct mhi_dev_ring_generic {
|
||||
uint64_t ptr;
|
||||
uint32_t res1:24;
|
||||
enum mhi_dev_state mhistate:8;
|
||||
uint32_t res2:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
struct mhi_config {
|
||||
uint32_t mhi_reg_len;
|
||||
uint32_t version;
|
||||
uint32_t event_rings;
|
||||
uint32_t channels;
|
||||
uint32_t chdb_offset;
|
||||
uint32_t erdb_offset;
|
||||
};
|
||||
|
||||
#define NUM_CHANNELS 128
|
||||
#define HW_CHANNEL_BASE 100
|
||||
#define HW_CHANNEL_END 107
|
||||
#define MHI_ENV_VALUE 2
|
||||
#define MHI_MASK_ROWS_CH_EV_DB 4
|
||||
#define TRB_MAX_DATA_SIZE 8192
|
||||
#define MHI_CTRL_STATE 25
|
||||
#define IPA_DMA_SYNC 1
|
||||
#define IPA_DMA_ASYNC 0
|
||||
|
||||
/*maximum trasnfer completion events buffer*/
|
||||
#define MAX_TR_EVENTS 50
|
||||
/*maximum event requests */
|
||||
#define MHI_MAX_EVT_REQ 50
|
||||
|
||||
/* Possible ring element types */
|
||||
union mhi_dev_ring_element_type {
|
||||
struct mhi_dev_cmd_ring_op cmd_no_op;
|
||||
struct mhi_dev_cmd_ring_reset_channel_cmd cmd_reset;
|
||||
struct mhi_dev_cmd_ring_stop_channel_cmd cmd_stop;
|
||||
struct mhi_dev_cmd_ring_start_channel_cmd cmd_start;
|
||||
struct mhi_dev_transfer_ring_element tre;
|
||||
struct mhi_dev_event_ring_transfer_completion evt_tr_comp;
|
||||
struct mhi_dev_event_ring_cmd_completion evt_cmd_comp;
|
||||
struct mhi_dev_event_ring_state_change evt_state_change;
|
||||
struct mhi_dev_event_ring_ee_state_change evt_ee_state;
|
||||
struct mhi_dev_ring_generic generic;
|
||||
};
|
||||
|
||||
/* Transfer ring element type */
|
||||
union mhi_dev_ring_ctx {
|
||||
struct mhi_dev_cmd_ctx cmd;
|
||||
struct mhi_dev_ev_ctx ev;
|
||||
struct mhi_dev_ch_ctx ch;
|
||||
struct mhi_dev_gen_ctx generic;
|
||||
};
|
||||
|
||||
/* MHI host Control and data address region */
|
||||
struct mhi_host_addr {
|
||||
uint32_t ctrl_base_lsb;
|
||||
uint32_t ctrl_base_msb;
|
||||
uint32_t ctrl_limit_lsb;
|
||||
uint32_t ctrl_limit_msb;
|
||||
uint32_t data_base_lsb;
|
||||
uint32_t data_base_msb;
|
||||
uint32_t data_limit_lsb;
|
||||
uint32_t data_limit_msb;
|
||||
};
|
||||
|
||||
/* MHI physical and virtual address region */
|
||||
struct mhi_meminfo {
|
||||
struct device *dev;
|
||||
uintptr_t pa_aligned;
|
||||
uintptr_t pa_unaligned;
|
||||
uintptr_t va_aligned;
|
||||
uintptr_t va_unaligned;
|
||||
uintptr_t size;
|
||||
};
|
||||
|
||||
struct mhi_addr {
|
||||
uint64_t host_pa;
|
||||
uintptr_t device_pa;
|
||||
uintptr_t device_va;
|
||||
size_t size;
|
||||
dma_addr_t phy_addr;
|
||||
void *virt_addr;
|
||||
bool use_ipa_dma;
|
||||
};
|
||||
|
||||
struct mhi_interrupt_state {
|
||||
uint32_t mask;
|
||||
uint32_t status;
|
||||
};
|
||||
|
||||
enum mhi_dev_channel_state {
|
||||
MHI_DEV_CH_UNINT,
|
||||
MHI_DEV_CH_STARTED,
|
||||
MHI_DEV_CH_PENDING_START,
|
||||
MHI_DEV_CH_PENDING_STOP,
|
||||
MHI_DEV_CH_STOPPED,
|
||||
MHI_DEV_CH_CLOSED,
|
||||
};
|
||||
|
||||
enum mhi_dev_ch_operation {
|
||||
MHI_DEV_OPEN_CH,
|
||||
MHI_DEV_CLOSE_CH,
|
||||
MHI_DEV_READ_CH,
|
||||
MHI_DEV_READ_WR,
|
||||
MHI_DEV_POLL,
|
||||
};
|
||||
|
||||
enum mhi_ctrl_info {
|
||||
MHI_STATE_CONFIGURED = 0,
|
||||
MHI_STATE_CONNECTED = 1,
|
||||
MHI_STATE_DISCONNECTED = 2,
|
||||
MHI_STATE_INVAL,
|
||||
};
|
||||
|
||||
enum mhi_dev_tr_compl_evt_type {
|
||||
SEND_EVENT_BUFFER,
|
||||
SEND_EVENT_RD_OFFSET,
|
||||
};
|
||||
|
||||
enum mhi_dev_transfer_type {
|
||||
MHI_DEV_DMA_SYNC,
|
||||
MHI_DEV_DMA_ASYNC,
|
||||
};
|
||||
|
||||
#if 0
|
||||
/* SW channel client list */
|
||||
enum mhi_client_channel {
|
||||
MHI_CLIENT_LOOPBACK_OUT = 0,
|
||||
MHI_CLIENT_LOOPBACK_IN = 1,
|
||||
MHI_CLIENT_SAHARA_OUT = 2,
|
||||
MHI_CLIENT_SAHARA_IN = 3,
|
||||
MHI_CLIENT_DIAG_OUT = 4,
|
||||
MHI_CLIENT_DIAG_IN = 5,
|
||||
MHI_CLIENT_SSR_OUT = 6,
|
||||
MHI_CLIENT_SSR_IN = 7,
|
||||
MHI_CLIENT_QDSS_OUT = 8,
|
||||
MHI_CLIENT_QDSS_IN = 9,
|
||||
MHI_CLIENT_EFS_OUT = 10,
|
||||
MHI_CLIENT_EFS_IN = 11,
|
||||
MHI_CLIENT_MBIM_OUT = 12,
|
||||
MHI_CLIENT_MBIM_IN = 13,
|
||||
MHI_CLIENT_QMI_OUT = 14,
|
||||
MHI_CLIENT_QMI_IN = 15,
|
||||
MHI_CLIENT_IP_CTRL_0_OUT = 16,
|
||||
MHI_CLIENT_IP_CTRL_0_IN = 17,
|
||||
MHI_CLIENT_IP_CTRL_1_OUT = 18,
|
||||
MHI_CLIENT_IP_CTRL_1_IN = 19,
|
||||
MHI_CLIENT_DCI_OUT = 20,
|
||||
MHI_CLIENT_DCI_IN = 21,
|
||||
MHI_CLIENT_IP_CTRL_3_OUT = 22,
|
||||
MHI_CLIENT_IP_CTRL_3_IN = 23,
|
||||
MHI_CLIENT_IP_CTRL_4_OUT = 24,
|
||||
MHI_CLIENT_IP_CTRL_4_IN = 25,
|
||||
MHI_CLIENT_IP_CTRL_5_OUT = 26,
|
||||
MHI_CLIENT_IP_CTRL_5_IN = 27,
|
||||
MHI_CLIENT_IP_CTRL_6_OUT = 28,
|
||||
MHI_CLIENT_IP_CTRL_6_IN = 29,
|
||||
MHI_CLIENT_IP_CTRL_7_OUT = 30,
|
||||
MHI_CLIENT_IP_CTRL_7_IN = 31,
|
||||
MHI_CLIENT_DUN_OUT = 32,
|
||||
MHI_CLIENT_DUN_IN = 33,
|
||||
MHI_CLIENT_IP_SW_0_OUT = 34,
|
||||
MHI_CLIENT_IP_SW_0_IN = 35,
|
||||
MHI_CLIENT_IP_SW_1_OUT = 36,
|
||||
MHI_CLIENT_IP_SW_1_IN = 37,
|
||||
MHI_CLIENT_IP_SW_2_OUT = 38,
|
||||
MHI_CLIENT_IP_SW_2_IN = 39,
|
||||
MHI_CLIENT_IP_SW_3_OUT = 40,
|
||||
MHI_CLIENT_IP_SW_3_IN = 41,
|
||||
MHI_CLIENT_CSVT_OUT = 42,
|
||||
MHI_CLIENT_CSVT_IN = 43,
|
||||
MHI_CLIENT_SMCT_OUT = 44,
|
||||
MHI_CLIENT_SMCT_IN = 45,
|
||||
MHI_CLIENT_IP_SW_4_OUT = 46,
|
||||
MHI_CLIENT_IP_SW_4_IN = 47,
|
||||
MHI_MAX_SOFTWARE_CHANNELS = 48,
|
||||
MHI_CLIENT_TEST_OUT = 60,
|
||||
MHI_CLIENT_TEST_IN = 61,
|
||||
MHI_CLIENT_RESERVED_1_LOWER = 62,
|
||||
MHI_CLIENT_RESERVED_1_UPPER = 99,
|
||||
MHI_CLIENT_IP_HW_0_OUT = 100,
|
||||
MHI_CLIENT_IP_HW_0_IN = 101,
|
||||
MHI_CLIENT_RESERVED_2_LOWER = 102,
|
||||
MHI_CLIENT_RESERVED_2_UPPER = 127,
|
||||
MHI_MAX_CHANNELS = 102,
|
||||
};
|
||||
#endif
|
||||
#endif /* _SDX20_MHI_H_ */
|
||||
#ifndef __SDX20_MHI_H
|
||||
#define __SDX20_MHI_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* MHI control data structures alloted by the host, including
|
||||
* channel context array, event context array, command context and rings */
|
||||
|
||||
/* Channel context state */
|
||||
enum mhi_dev_ch_ctx_state {
|
||||
MHI_DEV_CH_STATE_DISABLED,
|
||||
MHI_DEV_CH_STATE_ENABLED,
|
||||
MHI_DEV_CH_STATE_RUNNING,
|
||||
MHI_DEV_CH_STATE_SUSPENDED,
|
||||
MHI_DEV_CH_STATE_STOP,
|
||||
MHI_DEV_CH_STATE_ERROR,
|
||||
MHI_DEV_CH_STATE_RESERVED,
|
||||
MHI_DEV_CH_STATE_32BIT = 0x7FFFFFFF
|
||||
};
|
||||
|
||||
/* Channel type */
|
||||
enum mhi_dev_ch_ctx_type {
|
||||
MHI_DEV_CH_TYPE_NONE,
|
||||
MHI_DEV_CH_TYPE_OUTBOUND_CHANNEL,
|
||||
MHI_DEV_CH_TYPE_INBOUND_CHANNEL,
|
||||
MHI_DEV_CH_RESERVED
|
||||
};
|
||||
|
||||
/* Channel context type */
|
||||
struct mhi_dev_ch_ctx {
|
||||
enum mhi_dev_ch_ctx_state ch_state;
|
||||
enum mhi_dev_ch_ctx_type ch_type;
|
||||
uint32_t err_indx;
|
||||
uint64_t rbase;
|
||||
uint64_t rlen;
|
||||
uint64_t rp;
|
||||
uint64_t wp;
|
||||
} __packed;
|
||||
|
||||
enum mhi_dev_ring_element_type_id {
|
||||
MHI_DEV_RING_EL_INVALID = 0,
|
||||
MHI_DEV_RING_EL_NOOP = 1,
|
||||
MHI_DEV_RING_EL_TRANSFER = 2,
|
||||
MHI_DEV_RING_EL_RESET = 16,
|
||||
MHI_DEV_RING_EL_STOP = 17,
|
||||
MHI_DEV_RING_EL_START = 18,
|
||||
MHI_DEV_RING_EL_MHI_STATE_CHG = 32,
|
||||
MHI_DEV_RING_EL_CMD_COMPLETION_EVT = 33,
|
||||
MHI_DEV_RING_EL_TRANSFER_COMPLETION_EVENT = 34,
|
||||
MHI_DEV_RING_EL_EE_STATE_CHANGE_NOTIFY = 64,
|
||||
MHI_DEV_RING_EL_UNDEF
|
||||
};
|
||||
|
||||
enum mhi_dev_ring_state {
|
||||
RING_STATE_UINT = 0,
|
||||
RING_STATE_IDLE,
|
||||
RING_STATE_PENDING,
|
||||
};
|
||||
|
||||
enum mhi_dev_ring_type {
|
||||
RING_TYPE_CMD = 0,
|
||||
RING_TYPE_ER,
|
||||
RING_TYPE_CH,
|
||||
RING_TYPE_INVAL
|
||||
};
|
||||
|
||||
/* Event context interrupt moderation */
|
||||
enum mhi_dev_evt_ctx_int_mod_timer {
|
||||
MHI_DEV_EVT_INT_MODERATION_DISABLED
|
||||
};
|
||||
|
||||
/* Event ring type */
|
||||
enum mhi_dev_evt_ctx_event_ring_type {
|
||||
MHI_DEV_EVT_TYPE_DEFAULT,
|
||||
MHI_DEV_EVT_TYPE_VALID,
|
||||
MHI_DEV_EVT_RESERVED
|
||||
};
|
||||
|
||||
/* Event ring context type */
|
||||
struct mhi_dev_ev_ctx {
|
||||
uint32_t res1:16;
|
||||
enum mhi_dev_evt_ctx_int_mod_timer intmodt:16;
|
||||
enum mhi_dev_evt_ctx_event_ring_type ertype;
|
||||
uint32_t msivec;
|
||||
uint64_t rbase;
|
||||
uint64_t rlen;
|
||||
uint64_t rp;
|
||||
uint64_t wp;
|
||||
} __packed;
|
||||
|
||||
/* Command context */
|
||||
struct mhi_dev_cmd_ctx {
|
||||
uint32_t res1;
|
||||
uint32_t res2;
|
||||
uint32_t res3;
|
||||
uint64_t rbase;
|
||||
uint64_t rlen;
|
||||
uint64_t rp;
|
||||
uint64_t wp;
|
||||
} __packed;
|
||||
|
||||
/* generic context */
|
||||
struct mhi_dev_gen_ctx {
|
||||
uint32_t res1;
|
||||
uint32_t res2;
|
||||
uint32_t res3;
|
||||
uint64_t rbase;
|
||||
uint64_t rlen;
|
||||
uint64_t rp;
|
||||
uint64_t wp;
|
||||
} __packed;
|
||||
|
||||
/* Transfer ring element */
|
||||
struct mhi_dev_transfer_ring_element {
|
||||
uint64_t data_buf_ptr;
|
||||
uint32_t len:16;
|
||||
uint32_t res1:16;
|
||||
uint32_t chain:1;
|
||||
uint32_t res2:7;
|
||||
uint32_t ieob:1;
|
||||
uint32_t ieot:1;
|
||||
uint32_t bei:1;
|
||||
uint32_t res3:5;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t res4:8;
|
||||
} __packed;
|
||||
|
||||
/* Command ring element */
|
||||
/* Command ring No op command */
|
||||
struct mhi_dev_cmd_ring_op {
|
||||
uint64_t res1;
|
||||
uint32_t res2;
|
||||
uint32_t res3:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
/* Command ring reset channel command */
|
||||
struct mhi_dev_cmd_ring_reset_channel_cmd {
|
||||
uint64_t res1;
|
||||
uint32_t res2;
|
||||
uint32_t res3:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
/* Command ring stop channel command */
|
||||
struct mhi_dev_cmd_ring_stop_channel_cmd {
|
||||
uint64_t res1;
|
||||
uint32_t res2;
|
||||
uint32_t res3:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
/* Command ring start channel command */
|
||||
struct mhi_dev_cmd_ring_start_channel_cmd {
|
||||
uint64_t res1;
|
||||
uint32_t seqnum;
|
||||
uint32_t reliable:1;
|
||||
uint32_t res2:15;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
enum mhi_dev_cmd_completion_code {
|
||||
MHI_CMD_COMPL_CODE_INVALID = 0,
|
||||
MHI_CMD_COMPL_CODE_SUCCESS = 1,
|
||||
MHI_CMD_COMPL_CODE_EOT = 2,
|
||||
MHI_CMD_COMPL_CODE_OVERFLOW = 3,
|
||||
MHI_CMD_COMPL_CODE_EOB = 4,
|
||||
MHI_CMD_COMPL_CODE_UNDEFINED = 16,
|
||||
MHI_CMD_COMPL_CODE_RING_EL = 17,
|
||||
MHI_CMD_COMPL_CODE_RES
|
||||
};
|
||||
|
||||
/* Event ring elements */
|
||||
/* Transfer completion event */
|
||||
struct mhi_dev_event_ring_transfer_completion {
|
||||
uint64_t ptr;
|
||||
uint32_t len:16;
|
||||
uint32_t res1:8;
|
||||
enum mhi_dev_cmd_completion_code code:8;
|
||||
uint32_t res2:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
/* Command completion event */
|
||||
struct mhi_dev_event_ring_cmd_completion {
|
||||
uint64_t ptr;
|
||||
uint32_t res1:24;
|
||||
enum mhi_dev_cmd_completion_code code:8;
|
||||
uint32_t res2:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t res3:8;
|
||||
} __packed;
|
||||
|
||||
enum mhi_dev_state {
|
||||
MHI_DEV_RESET_STATE = 0,
|
||||
MHI_DEV_READY_STATE,
|
||||
MHI_DEV_M0_STATE,
|
||||
MHI_DEV_M1_STATE,
|
||||
MHI_DEV_M2_STATE,
|
||||
MHI_DEV_M3_STATE,
|
||||
MHI_DEV_MAX_STATE,
|
||||
MHI_DEV_SYSERR_STATE = 0xff
|
||||
};
|
||||
|
||||
/* MHI state change event */
|
||||
struct mhi_dev_event_ring_state_change {
|
||||
uint64_t ptr;
|
||||
uint32_t res1:24;
|
||||
enum mhi_dev_state mhistate:8;
|
||||
uint32_t res2:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t res3:8;
|
||||
} __packed;
|
||||
|
||||
enum mhi_dev_execenv {
|
||||
MHI_DEV_SBL_EE = 1,
|
||||
MHI_DEV_AMSS_EE = 2,
|
||||
MHI_DEV_UNRESERVED
|
||||
};
|
||||
|
||||
/* EE state change event */
|
||||
struct mhi_dev_event_ring_ee_state_change {
|
||||
uint64_t ptr;
|
||||
uint32_t res1:24;
|
||||
enum mhi_dev_execenv execenv:8;
|
||||
uint32_t res2:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t res3:8;
|
||||
} __packed;
|
||||
|
||||
/* Generic cmd to parse common details like type and channel id */
|
||||
struct mhi_dev_ring_generic {
|
||||
uint64_t ptr;
|
||||
uint32_t res1:24;
|
||||
enum mhi_dev_state mhistate:8;
|
||||
uint32_t res2:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
struct mhi_config {
|
||||
uint32_t mhi_reg_len;
|
||||
uint32_t version;
|
||||
uint32_t event_rings;
|
||||
uint32_t channels;
|
||||
uint32_t chdb_offset;
|
||||
uint32_t erdb_offset;
|
||||
};
|
||||
|
||||
#define NUM_CHANNELS 128
|
||||
#define HW_CHANNEL_BASE 100
|
||||
#define HW_CHANNEL_END 107
|
||||
#define MHI_ENV_VALUE 2
|
||||
#define MHI_MASK_ROWS_CH_EV_DB 4
|
||||
#define TRB_MAX_DATA_SIZE 8192
|
||||
#define MHI_CTRL_STATE 25
|
||||
#define IPA_DMA_SYNC 1
|
||||
#define IPA_DMA_ASYNC 0
|
||||
|
||||
/*maximum trasnfer completion events buffer*/
|
||||
#define MAX_TR_EVENTS 50
|
||||
/*maximum event requests */
|
||||
#define MHI_MAX_EVT_REQ 50
|
||||
|
||||
/* Possible ring element types */
|
||||
union mhi_dev_ring_element_type {
|
||||
struct mhi_dev_cmd_ring_op cmd_no_op;
|
||||
struct mhi_dev_cmd_ring_reset_channel_cmd cmd_reset;
|
||||
struct mhi_dev_cmd_ring_stop_channel_cmd cmd_stop;
|
||||
struct mhi_dev_cmd_ring_start_channel_cmd cmd_start;
|
||||
struct mhi_dev_transfer_ring_element tre;
|
||||
struct mhi_dev_event_ring_transfer_completion evt_tr_comp;
|
||||
struct mhi_dev_event_ring_cmd_completion evt_cmd_comp;
|
||||
struct mhi_dev_event_ring_state_change evt_state_change;
|
||||
struct mhi_dev_event_ring_ee_state_change evt_ee_state;
|
||||
struct mhi_dev_ring_generic generic;
|
||||
};
|
||||
|
||||
/* Transfer ring element type */
|
||||
union mhi_dev_ring_ctx {
|
||||
struct mhi_dev_cmd_ctx cmd;
|
||||
struct mhi_dev_ev_ctx ev;
|
||||
struct mhi_dev_ch_ctx ch;
|
||||
struct mhi_dev_gen_ctx generic;
|
||||
};
|
||||
|
||||
/* MHI host Control and data address region */
|
||||
struct mhi_host_addr {
|
||||
uint32_t ctrl_base_lsb;
|
||||
uint32_t ctrl_base_msb;
|
||||
uint32_t ctrl_limit_lsb;
|
||||
uint32_t ctrl_limit_msb;
|
||||
uint32_t data_base_lsb;
|
||||
uint32_t data_base_msb;
|
||||
uint32_t data_limit_lsb;
|
||||
uint32_t data_limit_msb;
|
||||
};
|
||||
|
||||
/* MHI physical and virtual address region */
|
||||
struct mhi_meminfo {
|
||||
struct device *dev;
|
||||
uintptr_t pa_aligned;
|
||||
uintptr_t pa_unaligned;
|
||||
uintptr_t va_aligned;
|
||||
uintptr_t va_unaligned;
|
||||
uintptr_t size;
|
||||
};
|
||||
|
||||
struct mhi_addr {
|
||||
uint64_t host_pa;
|
||||
uintptr_t device_pa;
|
||||
uintptr_t device_va;
|
||||
size_t size;
|
||||
dma_addr_t phy_addr;
|
||||
void *virt_addr;
|
||||
bool use_ipa_dma;
|
||||
};
|
||||
|
||||
struct mhi_interrupt_state {
|
||||
uint32_t mask;
|
||||
uint32_t status;
|
||||
};
|
||||
|
||||
enum mhi_dev_channel_state {
|
||||
MHI_DEV_CH_UNINT,
|
||||
MHI_DEV_CH_STARTED,
|
||||
MHI_DEV_CH_PENDING_START,
|
||||
MHI_DEV_CH_PENDING_STOP,
|
||||
MHI_DEV_CH_STOPPED,
|
||||
MHI_DEV_CH_CLOSED,
|
||||
};
|
||||
|
||||
enum mhi_dev_ch_operation {
|
||||
MHI_DEV_OPEN_CH,
|
||||
MHI_DEV_CLOSE_CH,
|
||||
MHI_DEV_READ_CH,
|
||||
MHI_DEV_READ_WR,
|
||||
MHI_DEV_POLL,
|
||||
};
|
||||
|
||||
enum mhi_ctrl_info {
|
||||
MHI_STATE_CONFIGURED = 0,
|
||||
MHI_STATE_CONNECTED = 1,
|
||||
MHI_STATE_DISCONNECTED = 2,
|
||||
MHI_STATE_INVAL,
|
||||
};
|
||||
|
||||
enum mhi_dev_tr_compl_evt_type {
|
||||
SEND_EVENT_BUFFER,
|
||||
SEND_EVENT_RD_OFFSET,
|
||||
};
|
||||
|
||||
enum mhi_dev_transfer_type {
|
||||
MHI_DEV_DMA_SYNC,
|
||||
MHI_DEV_DMA_ASYNC,
|
||||
};
|
||||
|
||||
#if 0
|
||||
/* SW channel client list */
|
||||
enum mhi_client_channel {
|
||||
MHI_CLIENT_LOOPBACK_OUT = 0,
|
||||
MHI_CLIENT_LOOPBACK_IN = 1,
|
||||
MHI_CLIENT_SAHARA_OUT = 2,
|
||||
MHI_CLIENT_SAHARA_IN = 3,
|
||||
MHI_CLIENT_DIAG_OUT = 4,
|
||||
MHI_CLIENT_DIAG_IN = 5,
|
||||
MHI_CLIENT_SSR_OUT = 6,
|
||||
MHI_CLIENT_SSR_IN = 7,
|
||||
MHI_CLIENT_QDSS_OUT = 8,
|
||||
MHI_CLIENT_QDSS_IN = 9,
|
||||
MHI_CLIENT_EFS_OUT = 10,
|
||||
MHI_CLIENT_EFS_IN = 11,
|
||||
MHI_CLIENT_MBIM_OUT = 12,
|
||||
MHI_CLIENT_MBIM_IN = 13,
|
||||
MHI_CLIENT_QMI_OUT = 14,
|
||||
MHI_CLIENT_QMI_IN = 15,
|
||||
MHI_CLIENT_IP_CTRL_0_OUT = 16,
|
||||
MHI_CLIENT_IP_CTRL_0_IN = 17,
|
||||
MHI_CLIENT_IP_CTRL_1_OUT = 18,
|
||||
MHI_CLIENT_IP_CTRL_1_IN = 19,
|
||||
MHI_CLIENT_DCI_OUT = 20,
|
||||
MHI_CLIENT_DCI_IN = 21,
|
||||
MHI_CLIENT_IP_CTRL_3_OUT = 22,
|
||||
MHI_CLIENT_IP_CTRL_3_IN = 23,
|
||||
MHI_CLIENT_IP_CTRL_4_OUT = 24,
|
||||
MHI_CLIENT_IP_CTRL_4_IN = 25,
|
||||
MHI_CLIENT_IP_CTRL_5_OUT = 26,
|
||||
MHI_CLIENT_IP_CTRL_5_IN = 27,
|
||||
MHI_CLIENT_IP_CTRL_6_OUT = 28,
|
||||
MHI_CLIENT_IP_CTRL_6_IN = 29,
|
||||
MHI_CLIENT_IP_CTRL_7_OUT = 30,
|
||||
MHI_CLIENT_IP_CTRL_7_IN = 31,
|
||||
MHI_CLIENT_DUN_OUT = 32,
|
||||
MHI_CLIENT_DUN_IN = 33,
|
||||
MHI_CLIENT_IP_SW_0_OUT = 34,
|
||||
MHI_CLIENT_IP_SW_0_IN = 35,
|
||||
MHI_CLIENT_IP_SW_1_OUT = 36,
|
||||
MHI_CLIENT_IP_SW_1_IN = 37,
|
||||
MHI_CLIENT_IP_SW_2_OUT = 38,
|
||||
MHI_CLIENT_IP_SW_2_IN = 39,
|
||||
MHI_CLIENT_IP_SW_3_OUT = 40,
|
||||
MHI_CLIENT_IP_SW_3_IN = 41,
|
||||
MHI_CLIENT_CSVT_OUT = 42,
|
||||
MHI_CLIENT_CSVT_IN = 43,
|
||||
MHI_CLIENT_SMCT_OUT = 44,
|
||||
MHI_CLIENT_SMCT_IN = 45,
|
||||
MHI_CLIENT_IP_SW_4_OUT = 46,
|
||||
MHI_CLIENT_IP_SW_4_IN = 47,
|
||||
MHI_MAX_SOFTWARE_CHANNELS = 48,
|
||||
MHI_CLIENT_TEST_OUT = 60,
|
||||
MHI_CLIENT_TEST_IN = 61,
|
||||
MHI_CLIENT_RESERVED_1_LOWER = 62,
|
||||
MHI_CLIENT_RESERVED_1_UPPER = 99,
|
||||
MHI_CLIENT_IP_HW_0_OUT = 100,
|
||||
MHI_CLIENT_IP_HW_0_IN = 101,
|
||||
MHI_CLIENT_RESERVED_2_LOWER = 102,
|
||||
MHI_CLIENT_RESERVED_2_UPPER = 127,
|
||||
MHI_MAX_CHANNELS = 102,
|
||||
};
|
||||
#endif
|
||||
#endif /* _SDX20_MHI_H_ */
|
||||
|
@ -45,11 +45,6 @@
|
||||
#define ETH_P_MAP 0xDA1A
|
||||
#endif
|
||||
|
||||
#if (ETH_P_MAP == 0x00F9)
|
||||
#undef ETH_P_MAP
|
||||
#define ETH_P_MAP 0xDA1A
|
||||
#endif
|
||||
|
||||
#ifndef ARPHRD_RAWIP
|
||||
#define ARPHRD_RAWIP ARPHRD_NONE
|
||||
#endif
|
||||
@ -71,7 +66,8 @@ static struct rmnet_nss_cb __read_mostly *nss_cb = NULL;
|
||||
#if defined(CONFIG_PINCTRL_IPQ807x) || defined(CONFIG_PINCTRL_IPQ5018) || defined(CONFIG_PINCTRL_IPQ8074)
|
||||
//#ifdef CONFIG_RMNET_DATA //spf12.x have no macro defined, just for spf11.x
|
||||
#define CONFIG_QCA_NSS_DRV
|
||||
/* define at qsdk/qca/src/linux-4.4/net/rmnet_data/rmnet_data_main.c */ //for spf11.x
|
||||
#define CONFIG_USE_RMNET_DATA_FOR_SKIP_MEMCPY
|
||||
/* define at qca/src/linux-4.4/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c */ //for spf11.x
|
||||
/* define at qsdk/qca/src/datarmnet/core/rmnet_config.c */ //for spf12.x
|
||||
/* set at qsdk/qca/src/data-kernel/drivers/rmnet-nss/rmnet_nss.c */
|
||||
/* need add DEPENDS:= kmod-rmnet-core in feeds/makefile */
|
||||
@ -79,6 +75,17 @@ extern struct rmnet_nss_cb *rmnet_nss_callbacks __rcu __read_mostly;
|
||||
//#endif
|
||||
#endif
|
||||
|
||||
|
||||
int mhi_netdev_use_xfer_type_dma(unsigned chan)
|
||||
{
|
||||
(void)chan;
|
||||
#ifdef CONFIG_USE_RMNET_DATA_FOR_SKIP_MEMCPY
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const unsigned char node_id[ETH_ALEN] = {0x02, 0x50, 0xf4, 0x00, 0x00, 0x00};
|
||||
static const unsigned char default_modem_addr[ETH_ALEN] = {0x02, 0x50, 0xf3, 0x00, 0x00, 0x00};
|
||||
|
||||
@ -295,6 +302,22 @@ enum mhi_net_type {
|
||||
MHI_NET_ETHER
|
||||
};
|
||||
|
||||
#ifdef CONFIG_USE_RMNET_DATA_FOR_SKIP_MEMCPY
|
||||
/* Try not to make this structure bigger than 128 bytes, since this take space
|
||||
* in payload packet.
|
||||
* Example: If MRU = 16K, effective MRU = 16K - sizeof(mhi_netbuf)
|
||||
*/
|
||||
struct mhi_netbuf {
|
||||
struct mhi_buf mhi_buf; /* this must be first element */
|
||||
void (*unmap)(struct device *dev, dma_addr_t addr, size_t size,
|
||||
enum dma_data_direction dir);
|
||||
};
|
||||
|
||||
struct mhi_net_chain {
|
||||
struct sk_buff *head, *tail; /* chained skb */
|
||||
};
|
||||
#endif
|
||||
|
||||
//#define TS_DEBUG
|
||||
struct mhi_netdev {
|
||||
int alias;
|
||||
@ -328,6 +351,14 @@ struct mhi_netdev {
|
||||
struct sk_buff *frag_skb;
|
||||
bool recycle_buf;
|
||||
|
||||
#ifdef CONFIG_USE_RMNET_DATA_FOR_SKIP_MEMCPY
|
||||
u32 order;
|
||||
struct mhi_netbuf **netbuf_pool;
|
||||
int pool_size; /* must be power of 2 */
|
||||
int current_index;
|
||||
struct mhi_net_chain chain;
|
||||
#endif
|
||||
|
||||
#if defined(MHI_NETDEV_STATUS64)
|
||||
struct pcpu_sw_netstats __percpu *stats64;
|
||||
#endif
|
||||
@ -1963,6 +1994,253 @@ static void mhi_netdev_dealloc(struct mhi_netdev *mhi_netdev)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USE_RMNET_DATA_FOR_SKIP_MEMCPY
|
||||
static struct mhi_netbuf *mhi_netdev_alloc(struct device *dev,
|
||||
gfp_t gfp,
|
||||
unsigned int order)
|
||||
{
|
||||
struct page *page;
|
||||
struct mhi_netbuf *netbuf;
|
||||
struct mhi_buf *mhi_buf;
|
||||
void *vaddr;
|
||||
|
||||
page = __dev_alloc_pages(gfp, order);
|
||||
if (!page)
|
||||
return NULL;
|
||||
|
||||
vaddr = page_address(page);
|
||||
|
||||
/* we going to use the end of page to store cached data */
|
||||
netbuf = vaddr + (PAGE_SIZE << order) - sizeof(*netbuf);
|
||||
|
||||
mhi_buf = (struct mhi_buf *)netbuf;
|
||||
mhi_buf->page = page;
|
||||
mhi_buf->buf = vaddr;
|
||||
mhi_buf->len = (void *)netbuf - vaddr;
|
||||
mhi_buf->dma_addr = dma_map_page(dev, page, 0, mhi_buf->len,
|
||||
DMA_FROM_DEVICE);
|
||||
if (dma_mapping_error(dev, mhi_buf->dma_addr)) {
|
||||
__free_pages(mhi_buf->page, order);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return netbuf;
|
||||
}
|
||||
|
||||
static void mhi_netdev_unmap_page(struct device *dev,
|
||||
dma_addr_t dma_addr,
|
||||
size_t len,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
dma_unmap_page(dev, dma_addr, len, dir);
|
||||
}
|
||||
|
||||
static int mhi_netdev_tmp_alloc(struct mhi_netdev *mhi_netdev, int nr_tre)
|
||||
{
|
||||
struct mhi_device *mhi_dev = mhi_netdev->mhi_dev;
|
||||
struct device *dev = mhi_dev->dev.parent;
|
||||
const u32 order = mhi_netdev->order;
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < nr_tre; i++) {
|
||||
struct mhi_buf *mhi_buf;
|
||||
struct mhi_netbuf *netbuf = mhi_netdev_alloc(dev, GFP_ATOMIC,
|
||||
order);
|
||||
if (!netbuf)
|
||||
return -ENOMEM;
|
||||
|
||||
mhi_buf = (struct mhi_buf *)netbuf;
|
||||
netbuf->unmap = mhi_netdev_unmap_page;
|
||||
|
||||
ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE, mhi_buf,
|
||||
mhi_buf->len, MHI_EOT);
|
||||
if (unlikely(ret)) {
|
||||
MSG_ERR("Failed to queue transfer, ret:%d\n", ret);
|
||||
mhi_netdev_unmap_page(dev, mhi_buf->dma_addr,
|
||||
mhi_buf->len, DMA_FROM_DEVICE);
|
||||
__free_pages(mhi_buf->page, order);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mhi_netdev_queue(struct mhi_netdev *mhi_netdev)
|
||||
{
|
||||
struct mhi_device *mhi_dev = mhi_netdev->mhi_dev;
|
||||
struct device *dev = mhi_dev->dev.parent;
|
||||
struct mhi_netbuf *netbuf;
|
||||
struct mhi_buf *mhi_buf;
|
||||
struct mhi_netbuf **netbuf_pool = mhi_netdev->netbuf_pool;
|
||||
int nr_tre = mhi_get_no_free_descriptors(mhi_dev, DMA_FROM_DEVICE);
|
||||
int i, peak, cur_index, ret;
|
||||
const int pool_size = mhi_netdev->pool_size - 1, max_peak = 4;
|
||||
|
||||
MSG_VERB("Enter free_desc:%d\n", nr_tre);
|
||||
|
||||
if (!nr_tre)
|
||||
return;
|
||||
|
||||
/* try going thru reclaim pool first */
|
||||
for (i = 0; i < nr_tre; i++) {
|
||||
/* peak for the next buffer, we going to peak several times,
|
||||
* and we going to give up if buffers are not yet free
|
||||
*/
|
||||
cur_index = mhi_netdev->current_index;
|
||||
netbuf = NULL;
|
||||
for (peak = 0; peak < max_peak; peak++) {
|
||||
struct mhi_netbuf *tmp = netbuf_pool[cur_index];
|
||||
|
||||
mhi_buf = &tmp->mhi_buf;
|
||||
|
||||
cur_index = (cur_index + 1) & pool_size;
|
||||
|
||||
/* page == 1 idle, buffer is free to reclaim */
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION( 5,4,0 ))
|
||||
if (atomic_read(&mhi_buf->page->_count) == 1)
|
||||
#else
|
||||
if (atomic_read(&mhi_buf->page->_refcount) == 1)
|
||||
#endif
|
||||
{
|
||||
netbuf = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* could not find a free buffer */
|
||||
if (!netbuf)
|
||||
break;
|
||||
|
||||
/* increment reference count so when network stack is done
|
||||
* with buffer, the buffer won't be freed
|
||||
*/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION( 5,4,0 ))
|
||||
atomic_inc(&mhi_buf->page->_count);
|
||||
#else
|
||||
atomic_inc(&mhi_buf->page->_refcount);
|
||||
#endif
|
||||
dma_sync_single_for_device(dev, mhi_buf->dma_addr, mhi_buf->len,
|
||||
DMA_FROM_DEVICE);
|
||||
ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE, mhi_buf,
|
||||
mhi_buf->len, MHI_EOT);
|
||||
if (unlikely(ret)) {
|
||||
MSG_ERR("Failed to queue buffer, ret:%d\n", ret);
|
||||
netbuf->unmap(dev, mhi_buf->dma_addr, mhi_buf->len,
|
||||
DMA_FROM_DEVICE);
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION( 5,4,0 ))
|
||||
atomic_dec(&mhi_buf->page->_count);
|
||||
#else
|
||||
atomic_dec(&mhi_buf->page->_refcount);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
mhi_netdev->current_index = cur_index;
|
||||
}
|
||||
|
||||
/* recyling did not work, buffers are still busy allocate temp pkts */
|
||||
if (i < nr_tre)
|
||||
mhi_netdev_tmp_alloc(mhi_netdev, nr_tre - i);
|
||||
}
|
||||
|
||||
/* allocating pool of memory */
|
||||
static int mhi_netdev_alloc_pool(struct mhi_netdev *mhi_netdev)
|
||||
{
|
||||
int i;
|
||||
struct mhi_netbuf *netbuf, **netbuf_pool;
|
||||
struct mhi_buf *mhi_buf;
|
||||
const u32 order = mhi_netdev->order;
|
||||
struct device *dev = mhi_netdev->mhi_dev->dev.parent;
|
||||
|
||||
netbuf_pool = kmalloc_array(mhi_netdev->pool_size, sizeof(*netbuf_pool),
|
||||
GFP_KERNEL);
|
||||
if (!netbuf_pool)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < mhi_netdev->pool_size; i++) {
|
||||
/* allocate paged data */
|
||||
netbuf = mhi_netdev_alloc(dev, GFP_KERNEL, order);
|
||||
if (!netbuf)
|
||||
goto error_alloc_page;
|
||||
|
||||
netbuf->unmap = dma_sync_single_for_cpu;
|
||||
netbuf_pool[i] = netbuf;
|
||||
}
|
||||
|
||||
mhi_netdev->netbuf_pool = netbuf_pool;
|
||||
|
||||
return 0;
|
||||
|
||||
error_alloc_page:
|
||||
for (--i; i >= 0; i--) {
|
||||
netbuf = netbuf_pool[i];
|
||||
mhi_buf = &netbuf->mhi_buf;
|
||||
dma_unmap_page(dev, mhi_buf->dma_addr, mhi_buf->len,
|
||||
DMA_FROM_DEVICE);
|
||||
__free_pages(mhi_buf->page, order);
|
||||
}
|
||||
|
||||
kfree(netbuf_pool);
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void mhi_netdev_free_pool(struct mhi_netdev *mhi_netdev)
|
||||
{
|
||||
int i;
|
||||
struct mhi_netbuf *netbuf, **netbuf_pool = mhi_netdev->netbuf_pool;
|
||||
struct device *dev = mhi_netdev->mhi_dev->dev.parent;
|
||||
struct mhi_buf *mhi_buf;
|
||||
|
||||
for (i = 0; i < mhi_netdev->pool_size; i++) {
|
||||
netbuf = netbuf_pool[i];
|
||||
mhi_buf = &netbuf->mhi_buf;
|
||||
dma_unmap_page(dev, mhi_buf->dma_addr, mhi_buf->len,
|
||||
DMA_FROM_DEVICE);
|
||||
__free_pages(mhi_buf->page, mhi_netdev->order);
|
||||
}
|
||||
|
||||
kfree(mhi_netdev->netbuf_pool);
|
||||
mhi_netdev->netbuf_pool = NULL;
|
||||
}
|
||||
|
||||
static int mhi_netdev_poll(struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct net_device *dev = napi->dev;
|
||||
struct mhi_netdev_priv *mhi_netdev_priv = netdev_priv(dev);
|
||||
struct mhi_netdev *mhi_netdev = mhi_netdev_priv->mhi_netdev;
|
||||
struct mhi_device *mhi_dev = mhi_netdev->mhi_dev;
|
||||
struct mhi_net_chain *chain = &mhi_netdev->chain;
|
||||
int rx_work = 0;
|
||||
|
||||
MSG_VERB("Entered\n");
|
||||
|
||||
rx_work = mhi_poll(mhi_dev, budget);
|
||||
|
||||
/* chained skb, push it to stack */
|
||||
if (chain && chain->head) {
|
||||
netif_receive_skb(chain->head);
|
||||
chain->head = NULL;
|
||||
}
|
||||
|
||||
if (rx_work < 0) {
|
||||
MSG_ERR("Error polling ret:%d\n", rx_work);
|
||||
napi_complete(napi);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* queue new buffers */
|
||||
mhi_netdev_queue(mhi_netdev);
|
||||
|
||||
/* complete work if # of packet processed less than allocated budget */
|
||||
if (rx_work < budget)
|
||||
napi_complete(napi);
|
||||
|
||||
MSG_VERB("polled %d pkts\n", rx_work);
|
||||
|
||||
return rx_work;
|
||||
}
|
||||
#else
|
||||
static int mhi_netdev_poll(struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct net_device *dev = napi->dev;
|
||||
@ -2040,6 +2318,7 @@ static int mhi_netdev_poll(struct napi_struct *napi, int budget)
|
||||
|
||||
return rx_work;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int mhi_netdev_open(struct net_device *ndev)
|
||||
{
|
||||
@ -2268,7 +2547,7 @@ static int qmap_ndo_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||
|
||||
case 0x89F3: //SIOCDEVPRIVATE
|
||||
if (mhi_netdev->use_rmnet_usb) {
|
||||
rc = copy_to_user(ifr->ifr_ifru.ifru_data, &mhi_netdev->rmnet_info, sizeof(RMNET_INFO));
|
||||
rc = copy_to_user(ifr->ifr_ifru.ifru_data, &mhi_netdev->rmnet_info, sizeof(mhi_netdev->rmnet_info));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -2436,6 +2715,34 @@ static int mhi_netdev_enable_iface(struct mhi_netdev *mhi_netdev)
|
||||
mhi_netdev->enabled = true;
|
||||
write_unlock_irq(&mhi_netdev->pm_lock);
|
||||
|
||||
#ifdef CONFIG_USE_RMNET_DATA_FOR_SKIP_MEMCPY
|
||||
/* MRU must be multiplication of page size */
|
||||
mhi_netdev->order = 1;
|
||||
while ((PAGE_SIZE << mhi_netdev->order) < mhi_netdev->mru)
|
||||
mhi_netdev->order += 1;
|
||||
|
||||
/* setup pool size ~2x ring length*/
|
||||
no_tre = mhi_get_no_free_descriptors(mhi_dev, DMA_FROM_DEVICE);
|
||||
mhi_netdev->pool_size = 1 << __ilog2_u32(no_tre);
|
||||
if (no_tre > mhi_netdev->pool_size)
|
||||
mhi_netdev->pool_size <<= 1;
|
||||
mhi_netdev->pool_size <<= 1;
|
||||
|
||||
/* allocate memory pool */
|
||||
ret = mhi_netdev_alloc_pool(mhi_netdev);
|
||||
if (ret) {
|
||||
MSG_ERR("mhi_netdev_alloc_pool Fail!\n");
|
||||
goto error_start;
|
||||
}
|
||||
|
||||
napi_enable(&mhi_netdev->napi);
|
||||
|
||||
/* now we have a pool of buffers allocated, queue to hardware
|
||||
* by triggering a napi_poll
|
||||
*/
|
||||
napi_schedule(&mhi_netdev->napi);
|
||||
error_start:
|
||||
#else
|
||||
/* queue buffer for rx path */
|
||||
no_tre = mhi_get_no_free_descriptors(mhi_dev, DMA_FROM_DEVICE);
|
||||
ret = mhi_netdev_alloc_skb(mhi_netdev, GFP_KERNEL);
|
||||
@ -2443,6 +2750,7 @@ static int mhi_netdev_enable_iface(struct mhi_netdev *mhi_netdev)
|
||||
schedule_delayed_work(&mhi_netdev->alloc_work, msecs_to_jiffies(20));
|
||||
|
||||
napi_enable(&mhi_netdev->napi);
|
||||
#endif
|
||||
|
||||
MSG_LOG("Exited.\n");
|
||||
|
||||
@ -2499,6 +2807,49 @@ static void mhi_netdev_xfer_ul_cb(struct mhi_device *mhi_dev,
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USE_RMNET_DATA_FOR_SKIP_MEMCPY
|
||||
static void mhi_netdev_xfer_dl_cb(struct mhi_device *mhi_dev,
|
||||
struct mhi_result *mhi_result)
|
||||
{
|
||||
struct mhi_netdev *mhi_netdev = mhi_device_get_devdata(mhi_dev);
|
||||
struct mhi_netbuf *netbuf = mhi_result->buf_addr;
|
||||
struct mhi_buf *mhi_buf = &netbuf->mhi_buf;
|
||||
struct sk_buff *skb;
|
||||
struct net_device *ndev = mhi_netdev->ndev;
|
||||
struct device *dev = mhi_dev->dev.parent;
|
||||
struct mhi_net_chain *chain = &mhi_netdev->chain;
|
||||
|
||||
netbuf->unmap(dev, mhi_buf->dma_addr, mhi_buf->len, DMA_FROM_DEVICE);
|
||||
|
||||
/* modem is down, drop the buffer */
|
||||
if (mhi_result->transaction_status == -ENOTCONN) {
|
||||
__free_pages(mhi_buf->page, mhi_netdev->order);
|
||||
return;
|
||||
}
|
||||
|
||||
mhi_netdev_upate_rx_stats(mhi_netdev, 1, mhi_result->bytes_xferd);
|
||||
|
||||
/* we support chaining */
|
||||
skb = alloc_skb(0, GFP_ATOMIC);
|
||||
if (likely(skb)) {
|
||||
skb_add_rx_frag(skb, 0, mhi_buf->page, 0,
|
||||
mhi_result->bytes_xferd, mhi_netdev->mru);
|
||||
|
||||
/* this is first on list */
|
||||
if (!chain->head) {
|
||||
skb->dev = ndev;
|
||||
skb->protocol = htons(ETH_P_MAP);
|
||||
chain->head = skb;
|
||||
} else {
|
||||
skb_shinfo(chain->tail)->frag_list = skb;
|
||||
}
|
||||
|
||||
chain->tail = skb;
|
||||
} else {
|
||||
__free_pages(mhi_buf->page, mhi_netdev->order);
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void mhi_netdev_xfer_dl_cb(struct mhi_device *mhi_dev,
|
||||
struct mhi_result *mhi_result)
|
||||
{
|
||||
@ -2604,6 +2955,7 @@ static void mhi_netdev_xfer_dl_cb(struct mhi_device *mhi_dev,
|
||||
skb_priv->bind_netdev = NULL;
|
||||
skb_queue_tail(&mhi_netdev->qmap_chain, skb);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void mhi_netdev_status_cb(struct mhi_device *mhi_dev, enum MHI_CB mhi_cb)
|
||||
{
|
||||
@ -2810,6 +3162,7 @@ static void mhi_netdev_remove(struct mhi_device *mhi_dev)
|
||||
{
|
||||
struct mhi_netdev *mhi_netdev = mhi_device_get_devdata(mhi_dev);
|
||||
struct sk_buff *skb;
|
||||
unsigned i;
|
||||
|
||||
MSG_LOG("Remove notification received\n");
|
||||
|
||||
@ -2817,27 +3170,19 @@ static void mhi_netdev_remove(struct mhi_device *mhi_dev)
|
||||
mhi_netdev->enabled = false;
|
||||
write_unlock_irq(&mhi_netdev->pm_lock);
|
||||
|
||||
if (mhi_netdev->use_rmnet_usb) {
|
||||
#ifndef MHI_NETDEV_ONE_CARD_MODE
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < mhi_netdev->qmap_mode; i++) {
|
||||
if (mhi_netdev->mpQmapNetDev[i]) {
|
||||
rmnet_vnd_unregister_device(mhi_netdev->mpQmapNetDev[i]);
|
||||
mhi_netdev->mpQmapNetDev[i] = NULL;
|
||||
}
|
||||
for (i = 0; i < mhi_netdev->qmap_mode; i++) {
|
||||
if (mhi_netdev->mpQmapNetDev[i]
|
||||
&& mhi_netdev->mpQmapNetDev[i] != mhi_netdev->ndev) {
|
||||
rmnet_vnd_unregister_device(mhi_netdev->mpQmapNetDev[i]);
|
||||
}
|
||||
|
||||
rtnl_lock();
|
||||
#ifdef ANDROID_gki
|
||||
if (mhi_netdev->ndev && rtnl_dereference(mhi_netdev->ndev->rx_handler))
|
||||
#else
|
||||
if (netdev_is_rx_handler_busy(mhi_netdev->ndev))
|
||||
#endif
|
||||
netdev_rx_handler_unregister(mhi_netdev->ndev);
|
||||
rtnl_unlock();
|
||||
#endif
|
||||
mhi_netdev->mpQmapNetDev[i] = NULL;
|
||||
}
|
||||
|
||||
rtnl_lock();
|
||||
if (mhi_netdev->ndev
|
||||
&& rtnl_dereference(mhi_netdev->ndev->rx_handler) == rmnet_rx_handler)
|
||||
netdev_rx_handler_unregister(mhi_netdev->ndev);
|
||||
rtnl_unlock();
|
||||
|
||||
while ((skb = skb_dequeue (&mhi_netdev->skb_chain)))
|
||||
dev_kfree_skb_any(skb);
|
||||
@ -2857,6 +3202,9 @@ static void mhi_netdev_remove(struct mhi_device *mhi_dev)
|
||||
#endif
|
||||
free_netdev(mhi_netdev->ndev);
|
||||
flush_delayed_work(&mhi_netdev->alloc_work);
|
||||
#ifdef CONFIG_USE_RMNET_DATA_FOR_SKIP_MEMCPY
|
||||
mhi_netdev_free_pool(mhi_netdev);
|
||||
#endif
|
||||
|
||||
if (!IS_ERR_OR_NULL(mhi_netdev->dentry))
|
||||
debugfs_remove_recursive(mhi_netdev->dentry);
|
||||
@ -2867,6 +3215,7 @@ static int mhi_netdev_probe(struct mhi_device *mhi_dev,
|
||||
{
|
||||
int ret;
|
||||
struct mhi_netdev *mhi_netdev;
|
||||
unsigned i;
|
||||
|
||||
mhi_netdev = devm_kzalloc(&mhi_dev->dev, sizeof(*mhi_netdev),
|
||||
GFP_KERNEL);
|
||||
@ -2923,6 +3272,8 @@ static int mhi_netdev_probe(struct mhi_device *mhi_dev,
|
||||
if ((mhi_dev->vendor == 0x17cb && mhi_dev->dev_id == 0x0306)
|
||||
|| (mhi_dev->vendor == 0x17cb && mhi_dev->dev_id == 0x0308)
|
||||
|| (mhi_dev->vendor == 0x1eac && mhi_dev->dev_id == 0x1004)
|
||||
|| (mhi_dev->vendor == 0x17cb && mhi_dev->dev_id == 0x011a)
|
||||
|| (mhi_dev->vendor == 0x1eac && mhi_dev->dev_id == 0x100b)
|
||||
) {
|
||||
mhi_netdev->qmap_version = 9;
|
||||
}
|
||||
@ -2958,14 +3309,23 @@ static int mhi_netdev_probe(struct mhi_device *mhi_dev,
|
||||
mhi_netdev->mpQmapNetDev[0] = mhi_netdev->ndev;
|
||||
netif_carrier_on(mhi_netdev->ndev);
|
||||
}
|
||||
else if (mhi_netdev->use_rmnet_usb) {
|
||||
#ifdef MHI_NETDEV_ONE_CARD_MODE
|
||||
else if (1) {
|
||||
mhi_netdev->mpQmapNetDev[0] = mhi_netdev->ndev;
|
||||
strcpy(mhi_netdev->rmnet_info.ifname[0], mhi_netdev->mpQmapNetDev[0]->name);
|
||||
mhi_netdev->rmnet_info.mux_id[0] = QUECTEL_QMAP_MUX_ID;
|
||||
#else
|
||||
unsigned i;
|
||||
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_USE_RMNET_DATA_FOR_SKIP_MEMCPY
|
||||
else if (1) {
|
||||
BUG_ON(mhi_netdev->net_type != MHI_NET_RMNET);
|
||||
for (i = 0; i < mhi_netdev->qmap_mode; i++) {
|
||||
mhi_netdev->rmnet_info.mux_id[i] = QUECTEL_QMAP_MUX_ID + i;
|
||||
strcpy(mhi_netdev->rmnet_info.ifname[i], "use_rmnet_data");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else if (mhi_netdev->use_rmnet_usb) {
|
||||
for (i = 0; i < mhi_netdev->qmap_mode; i++) {
|
||||
u8 mux_id = QUECTEL_QMAP_MUX_ID+i;
|
||||
mhi_netdev->mpQmapNetDev[i] = rmnet_vnd_register_device(mhi_netdev, i, mux_id);
|
||||
@ -2980,7 +3340,6 @@ static int mhi_netdev_probe(struct mhi_device *mhi_dev,
|
||||
//netdev_rx_handler_register(mhi_netdev->ndev, rmnet_rx_handler, mhi_netdev);
|
||||
netdev_rx_handler_register(mhi_netdev->ndev, rmnet_rx_handler, NULL);
|
||||
rtnl_unlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(CONFIG_IPQ5018_RATE_CONTROL)
|
||||
@ -3032,3 +3391,11 @@ void mhi_device_netdev_exit(void)
|
||||
#endif
|
||||
mhi_driver_unregister(&mhi_netdev_driver);
|
||||
}
|
||||
|
||||
void mhi_netdev_quectel_avoid_unused_function(void) {
|
||||
#ifdef CONFIG_USE_RMNET_DATA_FOR_SKIP_MEMCPY
|
||||
qmap_hex_dump(NULL, NULL, 0);
|
||||
mhi_netdev_ip_type_trans(0);
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user