Merge ab56bd6371 on remote branch

Change-Id: Iddd5cafb74fad368252433aef65b03253f272520
This commit is contained in:
Linux Build Service Account 2020-11-23 06:50:06 -08:00
commit 27a0c35498
22 changed files with 890 additions and 50 deletions

9
config/dataipa_gsi_V1.h Normal file
View file

@ -0,0 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*/
#define CONFIG_GSI 1
#define CONFIG_RMNET_IPA3 1
#define CONFIG_RNDIS_IPA 1
#define CONFIG_IPA_WDI_UNIFIED_API 1

View file

@ -0,0 +1,5 @@
export CONFIG_GSI=m
export CONFIG_IPA_CLIENTS_MANAGER=m
export CONFIG_IPA_WDI_UNIFIED_API=y
export CONFIG_RMNET_IPA3=y
export CONFIG_RNDIS_IPA=m

View file

@ -0,0 +1,5 @@
export CONFIG_GSI=y
export CONFIG_IPA_CLIENTS_MANAGER=y
export CONFIG_IPA_WDI_UNIFIED_API=y
export CONFIG_RMNET_IPA3=y
export CONFIG_RNDIS_IPA=y

View file

@ -26,6 +26,19 @@ include $(srctree)/techpack/dataipa/config/dataipa_GKI.conf
endif
endif
ifeq ($(CONFIG_QTI_QUIN_GVM),y)
LINUXINCLUDE += -include $(srctree)/techpack/dataipa/config/dataipa_gsi_V1.h
ifeq ($(CONFIG_QGKI),y)
include $(srctree)/techpack/dataipa/config/dataipa_gsi_V1_QGKI.conf
ifeq ($(CONFIG_LOCALVERSION), "-qgki-debug")
include $(srctree)/techpack/dataipa/config/dataipa_debug.conf
LINUXINCLUDE += -include $(srctree)/techpack/dataipa/config/dataipa_debug.h
endif
else
include $(srctree)/techpack/dataipa/config/dataipa_gsi_V1_GKI.conf
endif
endif
DATAIPADRVTOP = $(srctree)/techpack/dataipa/drivers/platform/msm
ifneq (,$(filter $(CONFIG_IPA3),y m))

View file

@ -442,6 +442,8 @@
#define GSI_V2_2_GSI_INST_RAM_n_MAXn 4095
#define GSI_V2_5_GSI_INST_RAM_n_MAXn 8191
#define GSI_V2_7_GSI_INST_RAM_n_MAXn 5119
#define GSI_V2_9_GSI_INST_RAM_n_MAXn 6143
#define GSI_V2_11_GSI_INST_RAM_n_MAXn 5119
#define GSI_GSI_INST_RAM_n_INST_BYTE_3_BMSK 0xff000000
#define GSI_GSI_INST_RAM_n_INST_BYTE_3_SHFT 0x18
@ -476,6 +478,11 @@
#define GSI_EE_n_GSI_CH_k_CNTXT_1_R_LENGTH_BMSK 0xffff
#define GSI_EE_n_GSI_CH_k_CNTXT_1_R_LENGTH_SHFT 0x0
#define GSI_V2_9_EE_n_GSI_CH_k_CNTXT_1_OFFS(k, n) \
(GSI_GSI_REG_BASE_OFFS + 0x0000f004 + 0x4000 * (n) + 0x80 * (k))
#define GSI_V2_9_EE_n_GSI_CH_k_CNTXT_1_R_LENGTH_BMSK 0xfffff
#define GSI_V2_9_EE_n_GSI_CH_k_CNTXT_1_R_LENGTH_SHFT 0x0
#define GSI_EE_n_GSI_CH_k_CNTXT_2_OFFS(k, n) \
(GSI_GSI_REG_BASE_OFFS + 0x0001c008 + 0x4000 * (n) + 0x80 * (k))
#define GSI_EE_n_GSI_CH_k_CNTXT_2_R_BASE_ADDR_LSBS_BMSK 0xffffffff
@ -549,6 +556,20 @@
#define GSI_V2_5_EE_n_GSI_CH_k_QOS_WRR_WEIGHT_BMSK 0xf
#define GSI_V2_5_EE_n_GSI_CH_k_QOS_WRR_WEIGHT_SHFT 0x0
#define GSI_V2_9_EE_n_GSI_CH_k_QOS_OFFS(k, n) \
(GSI_GSI_REG_BASE_OFFS + 0x0000f05c + 0x4000 * (n) + 0x80 * (k))
#define GSI_V2_9_EE_n_GSI_CH_k_QOS_DB_IN_BYTES_BMSK 0x1000000
#define GSI_V2_9_EE_n_GSI_CH_k_QOS_DB_IN_BYTES_SHFT 0x18
#define GSI_V2_9_EE_n_GSI_CH_k_QOS_EMPTY_LVL_THRSHOLD_BMSK 0xff0000
#define GSI_V2_9_EE_n_GSI_CH_k_QOS_EMPTY_LVL_THRSHOLD_SHFT 0x10
#define GSI_V2_9_EE_n_GSI_CH_k_QOS_PREFETCH_MODE_BMSK 0x3c00
#define GSI_V2_9_EE_n_GSI_CH_k_QOS_PREFETCH_MODE_SHFT 0xa
#define GSI_V2_9_EE_n_GSI_CH_k_QOS_USE_DB_ENG_BMSK 0x200
#define GSI_V2_9_EE_n_GSI_CH_k_QOS_USE_DB_ENG_SHFT 0x9
#define GSI_V2_9_EE_n_GSI_CH_k_QOS_MAX_PREFETCH_BMSK 0x100
#define GSI_V2_9_EE_n_GSI_CH_k_QOS_MAX_PREFETCH_SHFT 0x8
#define GSI_V2_9_EE_n_GSI_CH_k_QOS_WRR_WEIGHT_BMSK 0xf
#define GSI_V2_9_EE_n_GSI_CH_k_QOS_WRR_WEIGHT_SHFT 0x0
#define GSI_EE_n_GSI_CH_k_SCRATCH_0_OFFS(k, n) \
(GSI_GSI_REG_BASE_OFFS + 0x0001c060 + 0x4000 * (n) + 0x80 * (k))
@ -590,6 +611,11 @@
#define GSI_EE_n_EV_CH_k_CNTXT_1_R_LENGTH_BMSK 0xffff
#define GSI_EE_n_EV_CH_k_CNTXT_1_R_LENGTH_SHFT 0x0
#define GSI_V2_9_EE_n_EV_CH_k_CNTXT_1_OFFS(k, n) \
(GSI_GSI_REG_BASE_OFFS + 0x00010004 + 0x4000 * (n) + 0x80 * (k))
#define GSI_V2_9_EE_n_EV_CH_k_CNTXT_1_R_LENGTH_BMSK 0xfffff
#define GSI_V2_9_EE_n_EV_CH_k_CNTXT_1_R_LENGTH_SHFT 0x0
#define GSI_EE_n_EV_CH_k_CNTXT_2_OFFS(k, n) \
(GSI_GSI_REG_BASE_OFFS + 0x0001d008 + 0x4000 * (n) + 0x80 * (k))
#define GSI_EE_n_EV_CH_k_CNTXT_2_R_BASE_ADDR_LSBS_BMSK 0xffffffff
@ -850,6 +876,110 @@
#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_THREE_N_HALF_KB_FVAL 0x4
#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_FOUR_KB_FVAL 0x5
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_OFFS(n) \
(GSI_GSI_REG_BASE_OFFS + 0x00012040 + 0x4000 * (n))
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_GSI_USE_INTER_EE_BMSK 0x8000
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_GSI_USE_INTER_EE_SHFT 0xf
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_GSI_USE_RD_WR_ENG_BMSK 0x4000
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_GSI_USE_RD_WR_ENG_SHFT 0xE
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_RMSK 0x7fff
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_MAXn 2
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_GSI_SDMA_N_IOVEC_BMSK 0x38000000
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_GSI_SDMA_N_IOVEC_SHFT 0x1b
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_GSI_SDMA_MAX_BURST_BMSK 0x7F80000
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_GSI_SDMA_MAX_BURST_SHFT 0x13
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_GSI_SDMA_N_INT_BMSK 0x70000
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_GSI_SDMA_N_INT_SHFT 0x10
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_GSI_USE_SDMA_BMSK 0x8000
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_GSI_USE_SDMA_SHFT 0xf
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_GSI_CH_FULL_LOGIC_BMSK 0x4000
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_GSI_CH_FULL_LOGIC_SHFT 0xe
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_GSI_CH_PEND_TRANSLATE_BMSK 0x2000
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_GSI_CH_PEND_TRANSLATE_SHFT 0xd
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_GSI_NUM_EV_PER_EE_BMSK 0x1f00
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_GSI_NUM_EV_PER_EE_SHFT 0x8
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_GSI_NUM_CH_PER_EE_BMSK 0xf8
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_GSI_NUM_CH_PER_EE_SHFT 0x3
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_BMSK 0x7
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_SHFT 0x0
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_ONE_KB_FVAL 0x0
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_TWO_KB_FVAL 0x1
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_TWO_N_HALF_KB_FVAL 0x2
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_THREE_KB_FVAL 0x3
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_THREE_N_HALF_KB_FVAL 0x4
#define GSI_V2_7_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_FOUR_KB_FVAL 0x5
#define GSI_V2_9_EE_n_GSI_HW_PARAM_2_OFFS(n) \
(GSI_GSI_REG_BASE_OFFS + 0x00012040 + 0x4000 * (n))
#define GSI_V2_9_EE_n_GSI_HW_PARAM_2_RMSK 0xffffffff
#define GSI_V2_9_EE_n_GSI_HW_PARAM_2_MAXn 2
#define GSI_V2_9_EE_n_GSI_HW_PARAM_2_INI(n) \
in_dword_masked(GSI_V2_9_EE_n_GSI_HW_PARAM_2_OFFS(n), \
GSI_V2_9_EE_n_GSI_HW_PARAM_2_RMSK)
#define GSI_V2_9_EE_n_GSI_HW_PARAM_2_INMI(n, mask) \
in_dword_masked(GSI_V2_9_EE_n_GSI_HW_PARAM_2_OFFS(n), \
mask)
#define GSI_V2_9_EE_n_GSI_HW_PARAM_2_GSI_USE_INTER_EE_BMSK 0x80000000
#define GSI_V2_9_EE_n_GSI_HW_PARAM_2_GSI_USE_INTER_EE_SHFT 0x1f
#define GSI_V2_9_EE_n_GSI_HW_PARAM_2_GSI_USE_RD_WR_ENG_BMSK 0x40000000
#define GSI_V2_9_EE_n_GSI_HW_PARAM_2_GSI_USE_RD_WR_ENG_SHFT 0x1e
#define GSI_V2_9_EE_n_GSI_HW_PARAM_2_GSI_SDMA_N_IOVEC_BMSK 0x38000000
#define GSI_V2_9_EE_n_GSI_HW_PARAM_2_GSI_SDMA_N_IOVEC_SHFT 0x1b
#define GSI_V2_9_EE_n_GSI_HW_PARAM_2_GSI_SDMA_MAX_BURST_BMSK 0x7f80000
#define GSI_V2_9_EE_n_GSI_HW_PARAM_2_GSI_SDMA_MAX_BURST_SHFT 0x13
#define GSI_V2_9_EE_n_GSI_HW_PARAM_2_GSI_SDMA_N_INT_BMSK 0x70000
#define GSI_V2_9_EE_n_GSI_HW_PARAM_2_GSI_SDMA_N_INT_SHFT 0x10
#define GSI_V2_9_EE_n_GSI_HW_PARAM_2_GSI_USE_SDMA_BMSK 0x8000
#define GSI_V2_9_EE_n_GSI_HW_PARAM_2_GSI_USE_SDMA_SHFT 0xf
#define GSI_V2_9_EE_n_GSI_HW_PARAM_2_GSI_CH_FULL_LOGIC_BMSK 0x4000
#define GSI_V2_9_EE_n_GSI_HW_PARAM_2_GSI_CH_FULL_LOGIC_SHFT 0xe
#define GSI_V2_9_EE_n_GSI_HW_PARAM_2_GSI_CH_PEND_TRANSLATE_BMSK 0x2000
#define GSI_V2_9_EE_n_GSI_HW_PARAM_2_GSI_CH_PEND_TRANSLATE_SHFT 0xd
#define GSI_V2_9_EE_n_GSI_HW_PARAM_2_GSI_NUM_EV_PER_EE_BMSK 0x1f00
#define GSI_V2_9_EE_n_GSI_HW_PARAM_2_GSI_NUM_EV_PER_EE_SHFT 0x8
#define GSI_V2_9_EE_n_GSI_HW_PARAM_2_GSI_NUM_CH_PER_EE_BMSK 0xf8
#define GSI_V2_9_EE_n_GSI_HW_PARAM_2_GSI_NUM_CH_PER_EE_SHFT 0x3
#define GSI_V2_9_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_BMSK 0x7
#define GSI_V2_9_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_SHFT 0x0
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_OFFS(n) \
(GSI_GSI_REG_BASE_OFFS + 0x00012040 + 0x4000 * (n))
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_GSI_USE_INTER_EE_BMSK 0x80000000
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_GSI_USE_INTER_EE_SHFT 0x1f
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_GSI_USE_RD_WR_ENG_BMSK 0x40000000
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_GSI_USE_RD_WR_ENG_SHFT 0x1e
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_RMSK 0xffffffff
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_MAXn 2
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_GSI_SDMA_N_IOVEC_BMSK 0x38000000
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_GSI_SDMA_N_IOVEC_SHFT 0x1b
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_GSI_SDMA_MAX_BURST_BMSK 0x7F80000
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_GSI_SDMA_MAX_BURST_SHFT 0x13
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_GSI_SDMA_N_INT_BMSK 0x70000
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_GSI_SDMA_N_INT_SHFT 0x10
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_GSI_USE_SDMA_BMSK 0x8000
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_GSI_USE_SDMA_SHFT 0xf
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_GSI_CH_FULL_LOGIC_BMSK 0x4000
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_GSI_CH_FULL_LOGIC_SHFT 0xe
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_GSI_CH_PEND_TRANSLATE_BMSK 0x2000
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_GSI_CH_PEND_TRANSLATE_SHFT 0xd
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_GSI_NUM_EV_PER_EE_BMSK 0x1f00
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_GSI_NUM_EV_PER_EE_SHFT 0x8
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_GSI_NUM_CH_PER_EE_BMSK 0xf8
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_GSI_NUM_CH_PER_EE_SHFT 0x3
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_BMSK 0x7
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_SHFT 0x0
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_ONE_KB_FVAL 0x0
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_TWO_KB_FVAL 0x1
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_TWO_N_HALF_KB_FVAL 0x2
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_THREE_KB_FVAL 0x3
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_THREE_N_HALF_KB_FVAL 0x4
#define GSI_V2_11_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_FOUR_KB_FVAL 0x5
#define GSI_GSI_IRAM_PTR_MSI_DB_OFFS \
(GSI_GSI_REG_BASE_OFFS + 0x00000414)
#define GSI_GSI_IRAM_PTR_MSI_DB_FULL_RMSK 0xfff
#define GSI_GSI_IRAM_PTR_MSI_DB_FULL_IRAM_PTR_BMSK 0xfff
#define GSI_GSI_IRAM_PTR_MSI_DB_FULL_IRAM_PTR_SHFT 0x0
#define GSI_EE_n_GSI_SW_VERSION_OFFS(n) \
(GSI_GSI_REG_BASE_OFFS + 0x0001f044 + 0x4000 * (n))
#define GSI_EE_n_GSI_SW_VERSION_MAJOR_BMSK 0xf0000000

View file

@ -126,6 +126,8 @@ static int ipa_wdi_cleanup_internal(void)
struct ipa_wdi_intf_info *entry;
struct ipa_wdi_intf_info *next;
ipa3_uc_dereg_rdyCB();
/* clear interface list */
list_for_each_entry_safe(entry, next,
&ipa_wdi_ctx->head_intf_list, link) {
@ -635,6 +637,12 @@ static int ipa_wdi_enable_pipes_internal(void)
if (ipa_ep_idx_tx <= 0 || ipa_ep_idx_rx <= 0)
return -EFAULT;
ret = ipa_pm_activate_sync(ipa_wdi_ctx->ipa_pm_hdl);
if (ret) {
IPA_WDI_ERR("fail to activate ipa pm\n");
return -EFAULT;
}
if (ipa_wdi_ctx->wdi_version == IPA_WDI_3) {
if (ipa3_enable_wdi3_pipes(ipa_ep_idx_tx, ipa_ep_idx_rx)) {
IPA_WDI_ERR("fail to enable wdi pipes\n");
@ -666,12 +674,6 @@ static int ipa_wdi_enable_pipes_internal(void)
}
}
ret = ipa_pm_activate_sync(ipa_wdi_ctx->ipa_pm_hdl);
if (ret) {
IPA_WDI_ERR("fail to activate ipa pm\n");
return -EFAULT;
}
return 0;
}

View file

@ -469,10 +469,6 @@ int ipa3_connect_mhi_pipe(struct ipa_mhi_connect_params_internal *in,
u32 *clnt_hdl);
int ipa3_disconnect_mhi_pipe(u32 clnt_hdl);
bool ipa3_mhi_stop_gsi_channel(enum ipa_client_type client);
int ipa3_qmi_enable_force_clear_datapath_send(
struct ipa_enable_force_clear_datapath_req_msg_v01 *req);
int ipa3_qmi_disable_force_clear_datapath_send(
struct ipa_disable_force_clear_datapath_req_msg_v01 *req);
int ipa3_generate_tag_process(void);
int ipa3_disable_sps_pipe(enum ipa_client_type client);
int ipa3_mhi_reset_channel_internal(enum ipa_client_type client);

View file

@ -35,6 +35,12 @@
#include <linux/of_irq.h>
#include <linux/ctype.h>
#include "gsi.h"
#include <linux/sched.h>
#include <asm/arch_timer.h>
#include <linux/sched/clock.h>
#include <linux/jiffies.h>
#include <linux/delay.h>
#include <linux/wait.h>
#ifdef CONFIG_ARM64
@ -1866,7 +1872,16 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
if (!ipa3_is_ready()) {
IPAERR("IPA not ready, waiting for init completion\n");
wait_for_completion(&ipa3_ctx->init_completion_obj);
if (ipa3_ctx->manual_fw_load) {
if (!wait_for_completion_timeout(
&ipa3_ctx->init_completion_obj,
msecs_to_jiffies(1000))) {
IPAERR("IPA not ready, return\n");
return -ETIME;
}
} else {
wait_for_completion(&ipa3_ctx->init_completion_obj);
}
}
IPA_ACTIVE_CLIENTS_INC_SIMPLE();
@ -5285,13 +5300,14 @@ static void ipa3_active_clients_log_mod(
}
if (id->type != SIMPLE) {
t = local_clock();
t = sched_clock();
nanosec_rem = do_div(t, 1000000000) / 1000;
snprintf(temp_str, IPA3_ACTIVE_CLIENTS_LOG_LINE_LEN,
inc ? "[%5lu.%06lu] ^ %s, %s: %d" :
"[%5lu.%06lu] v %s, %s: %d",
inc ? "[%5lu.%06lu] ^ %s, %s: %d cnt = %d" :
"[%5lu.%06lu] v %s, %s: %d cnt = %d",
(unsigned long)t, nanosec_rem,
id->id_string, id->file, id->line);
id->id_string, id->file, id->line,
atomic_read(&ipa3_ctx->ipa3_active_clients.cnt));
ipa3_active_clients_log_insert(temp_str);
}
spin_unlock_irqrestore(&ipa3_ctx->ipa3_active_clients_logging.lock,
@ -7034,6 +7050,9 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
ipa3_ctx->tx_wrapper_cache_max_size = get_tx_wrapper_cache_size(
resource_p->tx_wrapper_cache_max_size);
ipa3_ctx->gsi_wdi_db_polling = resource_p->gsi_wdi_db_polling;
ipa3_ctx->ipa_config_is_auto = resource_p->ipa_config_is_auto;
ipa3_ctx->manual_fw_load = resource_p->manual_fw_load;
ipa3_ctx->max_num_smmu_cb = resource_p->max_num_smmu_cb;
if (resource_p->gsi_fw_file_name) {
ipa3_ctx->gsi_fw_file_name =
@ -7499,20 +7518,21 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
/* Create the dummy netdev for LAN RX NAPI*/
ipa3_enable_napi_netdev();
result = ipa3_wwan_init();
if (result) {
IPAERR(":ipa3_wwan_init err=%d\n", -result);
result = -ENODEV;
goto fail_wwan_init;
}
if (ipa3_ctx->platform_type != IPA_PLAT_TYPE_APQ) {
result = ipa3_wwan_init();
if (result) {
IPAERR(":ipa3_wwan_init err=%d\n", -result);
result = -ENODEV;
goto fail_wwan_init;
}
result = ipa3_rmnet_ctl_init();
if (result) {
IPAERR(":ipa3_rmnet_ctl_init err=%d\n", -result);
result = -ENODEV;
goto fail_rmnet_ctl_init;
result = ipa3_rmnet_ctl_init();
if (result) {
IPAERR(":ipa3_rmnet_ctl_init err=%d\n", -result);
result = -ENODEV;
goto fail_rmnet_ctl_init;
}
}
mutex_init(&ipa3_ctx->app_clock_vote.mutex);
return 0;
@ -7828,6 +7848,10 @@ static int get_ipa_dts_configuration(struct platform_device *pdev,
ipa_drv_res->skip_ieob_mask_wa = false;
ipa_drv_res->ipa_gpi_event_rp_ddr = false;
ipa_drv_res->gsi_wdi_db_polling = false;
ipa_drv_res->ipa_config_is_auto = false;
ipa_drv_res->manual_fw_load = false;
ipa_drv_res->max_num_smmu_cb = IPA_SMMU_CB_MAX;
/* Get IPA HW Version */
result = of_property_read_u32(pdev->dev.of_node, "qcom,ipa-hw-ver",
&ipa_drv_res->ipa_hw_type);
@ -7933,6 +7957,13 @@ static int get_ipa_dts_configuration(struct platform_device *pdev,
ipa_drv_res->ipa_wdi2
? "True" : "False");
ipa_drv_res->ipa_config_is_auto =
of_property_read_bool(pdev->dev.of_node,
"qcom,ipa-config-is-auto");
IPADBG(": ipa-config-is-auto = %s\n",
ipa_drv_res->ipa_config_is_auto
? "True" : "False");
ipa_drv_res->ipa_wan_skb_page =
of_property_read_bool(pdev->dev.of_node,
"qcom,wan-use-skb-page");
@ -8357,6 +8388,22 @@ static int get_ipa_dts_configuration(struct platform_device *pdev,
get_dts_tx_wrapper_cache_size(pdev, ipa_drv_res);
ipa_drv_res->manual_fw_load =
of_property_read_bool(pdev->dev.of_node,
"qcom,manual-fw-load");
IPADBG(": manual-fw-load (%s)\n",
ipa_drv_res->manual_fw_load? "True" : "False");
result = of_property_read_u32(pdev->dev.of_node,
"qcom,max_num_smmu_cb",
&ipa_drv_res->max_num_smmu_cb);
if (result)
IPADBG(": using default max number of cb = %d\n",
ipa_drv_res->max_num_smmu_cb);
else
IPADBG(": found ipa_drv_res->max_num_smmu_cb = %d\n",
ipa_drv_res->max_num_smmu_cb);
return 0;
}
@ -8862,7 +8909,8 @@ static void ipa_smmu_update_fw_loader(void)
break;
}
}
if (i == IPA_SMMU_CB_MAX) {
if (i == IPA_SMMU_CB_MAX ||
ipa3_ctx->num_smmu_cb_probed == ipa3_ctx->max_num_smmu_cb) {
IPADBG("All %d CBs probed\n", IPA_SMMU_CB_MAX);
ipa_fw_load_sm_handle_event(IPA_FW_LOAD_EVNT_SMMU_DONE);
}
@ -8922,6 +8970,7 @@ int ipa3_plat_drv_probe(struct platform_device *pdev_p)
cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_AP);
cb->dev = dev;
smmu_info.present[IPA_SMMU_CB_AP] = true;
ipa3_ctx->num_smmu_cb_probed++;
ipa_smmu_update_fw_loader();
return 0;
@ -8935,6 +8984,7 @@ int ipa3_plat_drv_probe(struct platform_device *pdev_p)
cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_WLAN);
cb->dev = dev;
smmu_info.present[IPA_SMMU_CB_WLAN] = true;
ipa3_ctx->num_smmu_cb_probed++;
ipa_smmu_update_fw_loader();
return 0;
@ -8948,6 +8998,7 @@ int ipa3_plat_drv_probe(struct platform_device *pdev_p)
cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_UC);
cb->dev = dev;
smmu_info.present[IPA_SMMU_CB_UC] = true;
ipa3_ctx->num_smmu_cb_probed++;
ipa_smmu_update_fw_loader();
return 0;
@ -8961,6 +9012,7 @@ int ipa3_plat_drv_probe(struct platform_device *pdev_p)
cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_11AD);
cb->dev = dev;
smmu_info.present[IPA_SMMU_CB_11AD] = true;
ipa3_ctx->num_smmu_cb_probed++;
ipa_smmu_update_fw_loader();
return 0;

View file

@ -454,6 +454,51 @@ int ipa3_smmu_map_peer_buff(u64 iova, u32 size, bool map, struct sg_table *sgt,
}
EXPORT_SYMBOL(ipa3_smmu_map_peer_buff);
int ipa3_smmu_map_ctg(u64 iova, u32 size, bool map, phys_addr_t pa,
enum ipa_smmu_cb_type cb_type)
{
struct iommu_domain *smmu_domain;
int res;
phys_addr_t phys;
unsigned long va;
size_t len;
if (cb_type >= IPA_SMMU_CB_MAX) {
IPAERR("invalid cb_type\n");
return -EINVAL;
}
if (ipa3_ctx->s1_bypass_arr[cb_type]) {
IPADBG("CB# %d is set to s1 bypass\n", cb_type);
return 0;
}
smmu_domain = ipa3_get_smmu_domain_by_type(cb_type);
if (!smmu_domain) {
IPAERR("invalid smmu domain\n");
return -EINVAL;
}
if (map) {
va = rounddown(iova, PAGE_SIZE);
phys = rounddown(pa, PAGE_SIZE);
len = size + ((iova - va > pa - phys) ?
(iova-va) : (pa - phys));
res = ipa3_iommu_map(smmu_domain, va, phys,
roundup(len, PAGE_SIZE),
IOMMU_READ | IOMMU_WRITE);
} else {
va = rounddown(iova, PAGE_SIZE);
phys = rounddown(pa, PAGE_SIZE);
len = size + ((iova - va > pa - phys) ?
(iova-va) : (pa - phys));
res = iommu_unmap(smmu_domain, va,
roundup(len, PAGE_SIZE));
}
IPADBG("ctg %s 0x%llx to 0x%llx\n", map ? "map" : "unmap", pa, iova);
return 0;
}
static enum ipa_client_cb_type ipa_get_client_cb_type(
enum ipa_client_type client_type)
{

View file

@ -75,6 +75,7 @@ const char *ipa3_event_name[IPA_EVENT_MAX_NUM] = {
__stringify(IPA_GSB_DISCONNECT),
__stringify(IPA_COALESCE_ENABLE),
__stringify(IPA_COALESCE_DISABLE),
__stringify(IPA_SET_MTU),
__stringify_1(WIGIG_CLIENT_CONNECT),
__stringify_1(WIGIG_FST_SWITCH),
};
@ -95,6 +96,7 @@ const char *ipa3_hdr_proc_type_name[] = {
__stringify(IPA_HDR_PROC_L2TP_HEADER_ADD),
__stringify(IPA_HDR_PROC_L2TP_HEADER_REMOVE),
__stringify(IPA_HDR_PROC_ETHII_TO_ETHII_EX),
__stringify(IPA_HDR_PROC_SET_DSCP),
};
static struct dentry *dent;

View file

@ -1762,6 +1762,7 @@ int ipa3_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
goto fail_pipe_not_valid;
}
trace_ipa3_tx_dp(skb,sys->ep->client);
num_frags = skb_shinfo(skb)->nr_frags;
/*
* make sure TLV FIFO supports the needed frags.
@ -1914,6 +1915,7 @@ int ipa3_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
IPA_STATS_INC_CNT(ipa3_ctx->stats.tx_hw_pkts);
}
trace_ipa3_tx_done(sys->ep->client);
if (num_frags) {
kfree(desc);
IPA_STATS_INC_CNT(ipa3_ctx->stats.tx_non_linear);
@ -4606,6 +4608,7 @@ void __ipa_gsi_irq_rx_scedule_poll(struct ipa3_sys_context *sys)
*/
clk_off = ipa_pm_activate(sys->pm_hdl);
if (!clk_off && sys->napi_obj) {
trace_ipa3_napi_schedule(sys->ep->client);
napi_schedule(sys->napi_obj);
IPA_STATS_INC_CNT(sys->napi_sch_cnt);
} else if (!clk_off &&
@ -5285,6 +5288,9 @@ int ipa3_rx_poll(u32 clnt_hdl, int weight)
IPAERR("Invalid client.\n");
return cnt;
}
ep = &ipa3_ctx->ep[clnt_hdl];
trace_ipa3_napi_poll_entry(ep->client);
wan_def_sys = ipa3_ctx->ep[ipa_ep_idx].sys;
remain_aggr_weight = weight / ipa3_ctx->ipa_wan_aggr_pkt_cnt;
@ -5295,7 +5301,6 @@ int ipa3_rx_poll(u32 clnt_hdl, int weight)
return -EINVAL;
}
ep = &ipa3_ctx->ep[clnt_hdl];
start_poll:
while (remain_aggr_weight > 0 &&
atomic_read(&ep->sys->curr_polling_state)) {
@ -5341,6 +5346,7 @@ start_poll:
IPADBG_LOW("Client = %d not replenished free descripotrs\n",
ep->client);
}
trace_ipa3_napi_poll_exit(ep->client);
return cnt;
}

View file

@ -1793,9 +1793,9 @@ enum ipa_client_cb_type {
*/
struct ipa_flt_rt_counter {
struct idr hdl;
spinlock_t hdl_lock;
bool used_hw[IPA_FLT_RT_HW_COUNTER];
bool used_sw[IPA_FLT_RT_SW_COUNTER];
spinlock_t hdl_lock;
};
/**
@ -1946,6 +1946,9 @@ struct ipa3_app_clock_vote {
* @rmnet_ctl_enable: enable pipe support fow low latency data
* @gsi_fw_file_name: GSI IPA fw file name
* @uc_fw_file_name: uC IPA fw file name
* @manual_fw_load: bool,if fw load is done manually
* @max_num_smmu_cb: number of smmu s1 cb supported
* @ipa_config_is_auto: flag to indicate auto config
*/
struct ipa3_context {
struct ipa3_char_device_context cdev;
@ -2024,6 +2027,7 @@ struct ipa3_context {
enum gsi_ver gsi_ver;
enum ipa3_platform_type platform_type;
bool ipa_config_is_mhi;
bool ipa_config_is_auto;
bool use_ipa_teth_bridge;
bool modem_cfg_emb_pipe_flt;
bool ipa_wdi2;
@ -2137,6 +2141,9 @@ struct ipa3_context {
char *uc_fw_file_name;
bool gsi_wdi_db_polling;
u32 ipa_wan_aggr_pkt_cnt;
bool manual_fw_load;
u32 num_smmu_cb_probed;
u32 max_num_smmu_cb;
};
struct ipa3_plat_drv_res {
@ -2202,6 +2209,9 @@ struct ipa3_plat_drv_res {
u32 tx_wrapper_cache_max_size;
bool gsi_wdi_db_polling;
u32 ipa_wan_aggr_pkt_cnt;
bool manual_fw_load;
bool ipa_config_is_auto;
u32 max_num_smmu_cb;
};
/**
@ -3084,6 +3094,8 @@ int ipa3_smmu_map_peer_reg(phys_addr_t phys_addr, bool map,
enum ipa_smmu_cb_type cb_type);
int ipa3_smmu_map_peer_buff(u64 iova, u32 size, bool map, struct sg_table *sgt,
enum ipa_smmu_cb_type cb_type);
int ipa3_smmu_map_ctg(u64 iova, u32 size, bool map, phys_addr_t pa,
enum ipa_smmu_cb_type cb_type);
void ipa3_reset_freeze_vote(void);
int ipa3_ntn_init(void);
int ipa3_get_ntn_stats(struct Ipa3HwStatsNTNInfoData_t *stats);

View file

@ -1512,11 +1512,14 @@ static void ipa3_q6_clnt_svc_arrive(struct work_struct *work)
IPAWANERR(
"ipa3_qmi_init_modem_send_sync_msg failed due to SSR!\n");
/* Cleanup when ipa3_wwan_remove is called */
mutex_lock(&ipa3_qmi_lock);
qmi_handle_release(ipa_q6_clnt);
vfree(ipa_q6_clnt);
ipa_q6_clnt = NULL;
mutex_unlock(&ipa3_qmi_lock);
if (ipa_q6_clnt != NULL) {
mutex_lock(&ipa3_qmi_lock);
qmi_handle_release(ipa_q6_clnt);
vfree(ipa_q6_clnt);
ipa_q6_clnt = NULL;
mutex_unlock(&ipa3_qmi_lock);
}
IPAWANERR("Exit from service arrive fun\n");
return;
}
@ -2143,6 +2146,8 @@ int ipa3_qmi_enable_per_client_stats(
IPAWANDBG("Sending QMI_IPA_ENABLE_PER_CLIENT_STATS_REQ_V01\n");
if (unlikely(!ipa_q6_clnt))
return -ETIMEDOUT;
rc = ipa3_qmi_send_req_wait(ipa_q6_clnt,
&req_desc, req,
&resp_desc, resp,
@ -2180,6 +2185,8 @@ int ipa3_qmi_get_per_client_packet_stats(
IPAWANDBG("Sending QMI_IPA_GET_STATS_PER_CLIENT_REQ_V01\n");
if (unlikely(!ipa_q6_clnt))
return -ETIMEDOUT;
rc = ipa3_qmi_send_req_wait(ipa_q6_clnt,
&req_desc, req,
&resp_desc, resp,
@ -2237,6 +2244,8 @@ int ipa3_qmi_send_mhi_cleanup_request(struct ipa_mhi_cleanup_req_msg_v01 *req)
resp_desc.msg_id = QMI_IPA_MHI_CLEANUP_RESP_V01;
resp_desc.ei_array = ipa_mhi_cleanup_resp_msg_v01_ei;
if (unlikely(!ipa_q6_clnt))
return -ETIMEDOUT;
rc = ipa3_qmi_send_req_wait(ipa_q6_clnt,
&req_desc, req,
&resp_desc, &resp,

View file

@ -121,6 +121,8 @@ struct ipa3_rmnet_mux_val {
bool ul_flt_reg;
bool mux_hdr_set;
uint32_t hdr_hdl;
uint16_t mtu_v4;
uint16_t mtu_v6;
};
extern struct qmi_elem_info
@ -305,6 +307,9 @@ int rmnet_ipa3_enable_per_client_stats(bool *data);
int rmnet_ipa3_query_per_client_stats(
struct wan_ioctl_query_per_client_stats *data);
int rmnet_ipa3_get_wan_mtu(
struct ipa_mtu_info *data);
int ipa3_qmi_get_data_stats(struct ipa_get_data_stats_req_msg_v01 *req,
struct ipa_get_data_stats_resp_msg_v01 *resp);

View file

@ -123,19 +123,35 @@ TRACE_EVENT(
TRACE_EVENT(
rmnet_ipa_netif_rcv_skb3,
TP_PROTO(unsigned long rx_pkt_cnt),
TP_PROTO(const struct sk_buff *skb, unsigned long rx_pkt_cnt),
TP_ARGS(rx_pkt_cnt),
TP_ARGS(skb, rx_pkt_cnt),
TP_STRUCT__entry(
__string(name, skb->dev->name)
__field(const void *, skbaddr)
__field(u16, protocol)
__field(unsigned int, len)
__field(unsigned int, data_len)
__field(unsigned long, rx_pkt_cnt)
),
TP_fast_assign(
__assign_str(name, skb->dev->name);
__entry->skbaddr = skb;
__entry->protocol = ntohs(skb->protocol);
__entry->len = skb->len;
__entry->data_len = skb->data_len;
__entry->rx_pkt_cnt = rx_pkt_cnt;
),
TP_printk("rx_pkt_cnt=%lu", __entry->rx_pkt_cnt)
TP_printk("dev=%s skbaddr=%p protocol=0x%04x len=%u data_len=%u rx_pkt_cnt=%lu",
__get_str(name),
__entry->skbaddr,
__entry->protocol,
__entry->len,
__entry->data_len,
__entry->rx_pkt_cnt)
);
TRACE_EVENT(
@ -174,6 +190,112 @@ TRACE_EVENT(
TP_printk("napi_overall_poll_pkt_cnt=%d", __entry->poll_num)
);
TRACE_EVENT(
ipa3_napi_schedule,
TP_PROTO(unsigned long client),
TP_ARGS(client),
TP_STRUCT__entry(
__field(unsigned long, client)
),
TP_fast_assign(
__entry->client = client;
),
TP_printk("client=%lu", __entry->client)
);
TRACE_EVENT(
ipa3_napi_poll_entry,
TP_PROTO(unsigned long client),
TP_ARGS(client),
TP_STRUCT__entry(
__field(unsigned long, client)
),
TP_fast_assign(
__entry->client = client;
),
TP_printk("client=%lu", __entry->client)
);
TRACE_EVENT(
ipa3_napi_poll_exit,
TP_PROTO(unsigned long client),
TP_ARGS(client),
TP_STRUCT__entry(
__field(unsigned long, client)
),
TP_fast_assign(
__entry->client = client;
),
TP_printk("client=%lu", __entry->client)
);
TRACE_EVENT(
ipa3_tx_dp,
TP_PROTO(const struct sk_buff *skb, unsigned long client),
TP_ARGS(skb, client),
TP_STRUCT__entry(
__string(name, skb->dev->name)
__field(const void *, skbaddr)
__field(u16, protocol)
__field(unsigned int, len)
__field(unsigned int, data_len)
__field(unsigned long, client)
),
TP_fast_assign(
__assign_str(name, skb->dev->name);
__entry->skbaddr = skb;
__entry->protocol = ntohs(skb->protocol);
__entry->len = skb->len;
__entry->data_len = skb->data_len;
__entry->client = client;
),
TP_printk("dev=%s skbaddr=%p protocol=0x%04x len=%u data_len=%u client=%lu",
__get_str(name),
__entry->skbaddr,
__entry->protocol,
__entry->len,
__entry->data_len,
__entry->client)
);
TRACE_EVENT(
ipa3_tx_done,
TP_PROTO(unsigned long client),
TP_ARGS(client),
TP_STRUCT__entry(
__field(unsigned long, client)
),
TP_fast_assign(
__entry->client = client;
),
TP_printk("client=%lu", __entry->client)
);
#endif /* _IPA_TRACE_H */

View file

@ -7,6 +7,7 @@
#define IPA_UC_NTN_DB_PA_TX 0x79620DC
#define IPA_UC_NTN_DB_PA_RX 0x79620D8
#define IPA_UC_RING_ELEM_SZ 16
static void ipa3_uc_ntn_event_log_info_handler(
struct IpaHwEventLogInfoData_t *uc_event_top_mmio)
@ -287,13 +288,31 @@ static int ipa3_smmu_map_uc_ntn_pipes(struct ipa_ntn_setup_info *params,
}
if (params->smmu_enabled) {
IPADBG("smmu is enabled on EMAC\n");
result = ipa3_smmu_map_peer_buff((u64)params->ring_base_iova,
params->ntn_ring_size, map, params->ring_base_sgt,
IPA_SMMU_CB_UC);
if (result) {
IPAERR("failed to %s ntn ring %d\n",
map ? "map" : "unmap", result);
goto fail_map_ring;
if (params->ring_base_sgt) {
result = ipa3_smmu_map_peer_buff(
(u64)params->ring_base_iova,
params->ntn_ring_size, map,
params->ring_base_sgt,
IPA_SMMU_CB_UC);
if (result) {
IPAERR("failed to %s ntn ring %d\n",
map ? "map" : "unmap", result);
goto fail_map_ring;
}
} else {
/* Eth driver passes # of elements instead of sz
* Calc & pass the ring size to map contigous mem
*/
result = ipa3_smmu_map_ctg(
(u64)params->ring_base_iova,
params->ntn_ring_size*IPA_UC_RING_ELEM_SZ,
map, params->ring_base_pa,
IPA_SMMU_CB_UC);
if (result) {
IPAERR("failed to %s ntn ring %d\n",
map ? "map" : "unmap", result);
goto fail_map_ring;
}
}
result = ipa3_smmu_map_peer_buff(
(u64)params->buff_pool_base_iova,
@ -367,9 +386,15 @@ fail_map_data_buff_smmu_disabled:
params->num_buffers * 4, !map, NULL, IPA_SMMU_CB_UC);
goto fail_map_buffer_smmu_disabled;
fail_map_buffer_smmu_enabled:
ipa3_smmu_map_peer_buff((u64)params->ring_base_iova,
params->ntn_ring_size, !map, params->ring_base_sgt,
IPA_SMMU_CB_UC);
if (params->ring_base_sgt) {
ipa3_smmu_map_peer_buff((u64)params->ring_base_iova,
params->ntn_ring_size, !map, params->ring_base_sgt,
IPA_SMMU_CB_UC);
} else {
ipa3_smmu_map_ctg((u64)params->ring_base_iova,
params->ntn_ring_size*IPA_UC_RING_ELEM_SZ, !map,
params->ring_base_pa, IPA_SMMU_CB_UC);
}
goto fail_map_ring;
fail_map_buffer_smmu_disabled:
ipa3_smmu_map_peer_buff((u64)params->ring_base_pa,
@ -475,6 +500,8 @@ int ipa3_setup_uc_ntn_pipes(struct ipa_ntn_conn_in_params *in,
/* setup dl ep cfg */
ep_dl->valid = 1;
ep_dl->client = in->dl.client;
ep_dl->client_notify = notify;
ep_dl->priv = priv;
memset(&ep_dl->cfg, 0, sizeof(ep_ul->cfg));
ep_dl->cfg.nat.nat_en = IPA_BYPASS_NAT;
ep_dl->cfg.hdr.hdr_len = hdr_len;

View file

@ -3001,7 +3001,7 @@ int ipa3_uc_dereg_rdyCB(void)
return 0;
}
EXPORT_SYMBOL(ipa3_uc_dereg_rdyCB);
/**
* ipa3_uc_wdi_get_dbpa() - To retrieve

View file

@ -263,6 +263,7 @@ enum ipa_ver {
IPA_4_0_MHI,
IPA_4_1,
IPA_4_1_APQ,
IPA_4_1_APQ_AUTO,
IPA_4_2,
IPA_4_5,
IPA_4_5_MHI,
@ -374,6 +375,19 @@ static const struct rsrc_min_max ipa3_rsrc_src_grp_config
[IPA_v4_0_RSRC_GRP_TYPE_SRC_ACK_ENTRIES] = {
{14, 14}, {20, 20}, {0, 0}, {14, 14}, {0, 0}, {0, 0} },
},
[IPA_4_1_APQ_AUTO] = {
/* LWA_DL UL_DL unused UC_RX_Q, other are invalid */
[IPA_v4_0_RSRC_GRP_TYPE_SRC_PKT_CONTEXTS] = {
{1, 63}, {1, 63}, {0, 0}, {1, 63}, {0, 0}, {0, 0} },
[IPA_v4_0_RSRC_GRP_TYPE_SRC_DESCRIPTOR_LISTS] = {
{10, 10}, {10, 10}, {0, 0}, {8, 8}, {0, 0}, {0, 0} },
[IPA_v4_0_RSRC_GRP_TYPE_SRC_DESCRIPTOR_BUFF] = {
{12, 12}, {14, 14}, {0, 0}, {8, 8}, {0, 0}, {0, 0} },
[IPA_v4_0_RSRC_GRP_TYPE_SRC_HPS_DMARS] = {
{0, 63}, {0, 63}, {0, 63}, {0, 63}, {0, 0}, {0, 0} },
[IPA_v4_0_RSRC_GRP_TYPE_SRC_ACK_ENTRIES] = {
{14, 14}, {20, 20}, {0, 0}, {14, 14}, {0, 0}, {0, 0} },
},
[IPA_4_2] = {
/* UL_DL other are invalid */
[IPA_v4_0_RSRC_GRP_TYPE_SRC_PKT_CONTEXTS] = {
@ -521,6 +535,13 @@ static const struct rsrc_min_max ipa3_rsrc_dst_grp_config
[IPA_v4_0_RSRC_GRP_TYPE_DST_DPS_DMARS] = {
{2, 63}, {1, 63}, {1, 2}, {0, 2}, {0, 0}, {0, 0} },
},
[IPA_4_1_APQ_AUTO] = {
/* LWA_DL UL/DL/DPL uC, other are invalid */
[IPA_v4_0_RSRC_GRP_TYPE_DST_DATA_SECTORS] = {
{4, 4}, {4, 4}, {3, 3}, {2, 2}, {0, 0}, {0, 0} },
[IPA_v4_0_RSRC_GRP_TYPE_DST_DPS_DMARS] = {
{2, 63}, {1, 63}, {1, 2}, {0, 2}, {0, 0}, {0, 0} },
},
[IPA_4_2] = {
/* UL/DL/DPL, other are invalid */
[IPA_v4_0_RSRC_GRP_TYPE_DST_DATA_SECTORS] = {
@ -610,6 +631,11 @@ static const struct rsrc_min_max ipa3_rsrc_rx_grp_config
[IPA_RSRC_GRP_TYPE_RX_HPS_CMDQ] = {
{3, 3}, {7, 7}, {0, 0}, {2, 2}, {0, 0}, {0, 0} },
},
[IPA_4_1_APQ_AUTO] = {
/* LWA_DL UL_DL unused UC_RX_Q, other are invalid */
[IPA_RSRC_GRP_TYPE_RX_HPS_CMDQ] = {
{3, 3}, {7, 7}, {0, 0}, {2, 2}, {0, 0}, {0, 0} },
},
[IPA_4_2] = {
/* UL_DL, other are invalid */
[IPA_RSRC_GRP_TYPE_RX_HPS_CMDQ] = {
@ -713,6 +739,8 @@ static const struct ipa_qmb_outstanding ipa3_qmb_outstanding
[IPA_4_0_MHI][IPA_QMB_INSTANCE_PCIE] = {12, 4, 0},
[IPA_4_1][IPA_QMB_INSTANCE_DDR] = {12, 8, 120},
[IPA_4_1][IPA_QMB_INSTANCE_PCIE] = {12, 4, 0},
[IPA_4_1_APQ_AUTO][IPA_QMB_INSTANCE_DDR] = {12, 8, 120},
[IPA_4_1_APQ_AUTO][IPA_QMB_INSTANCE_PCIE] = {12, 4, 0},
[IPA_4_2][IPA_QMB_INSTANCE_DDR] = {12, 8, 0},
[IPA_4_5][IPA_QMB_INSTANCE_DDR] = {16, 8, 120},
[IPA_4_5][IPA_QMB_INSTANCE_PCIE] = {12, 8, 0},
@ -2033,6 +2061,126 @@ static const struct ipa_ep_configuration ipa3_ep_mapping
QMB_MASTER_SELECT_DDR,
{ 17, 14, 9, 9, IPA_EE_AP } },
[IPA_4_1_APQ_AUTO][IPA_CLIENT_WLAN2_PROD] = {
true, IPA_v4_0_GROUP_UL_DL,
true,
IPA_DPS_HPS_REP_SEQ_TYPE_2PKT_PROC_PASS_NO_DEC_UCP_DMAP,
QMB_MASTER_SELECT_DDR,
{ 6, 11, 8, 16, IPA_EE_AP } },
[IPA_4_1_APQ_AUTO][IPA_CLIENT_USB_PROD] = {
true, IPA_v4_0_GROUP_UL_DL,
true,
IPA_DPS_HPS_REP_SEQ_TYPE_2PKT_PROC_PASS_NO_DEC_UCP_DMAP,
QMB_MASTER_SELECT_DDR,
{ 0, 8, 8, 16, IPA_EE_AP } },
[IPA_4_1_APQ_AUTO][IPA_CLIENT_APPS_LAN_PROD] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
QMB_MASTER_SELECT_DDR,
{ 8, 10, 8, 16, IPA_EE_AP } },
[IPA_4_1_APQ_AUTO][IPA_CLIENT_APPS_CMD_PROD] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
QMB_MASTER_SELECT_DDR,
{ 5, 4, 20, 24, IPA_EE_AP } },
[IPA_4_1_APQ_AUTO][IPA_CLIENT_ETHERNET_PROD] = {
true, IPA_v4_0_GROUP_UL_DL,
true,
IPA_DPS_HPS_REP_SEQ_TYPE_2PKT_PROC_PASS_NO_DEC_UCP_DMAP,
QMB_MASTER_SELECT_DDR,
{ 9, 0, 8, 16, IPA_EE_UC } },
/* Only for test purpose */
[IPA_4_1_APQ_AUTO][IPA_CLIENT_TEST_PROD] = {
true, IPA_v4_0_GROUP_UL_DL,
true,
IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
QMB_MASTER_SELECT_DDR,
{0, 8, 8, 16, IPA_EE_AP } },
[IPA_4_1_APQ_AUTO][IPA_CLIENT_TEST1_PROD] = {
true, IPA_v4_0_GROUP_UL_DL,
true,
IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
QMB_MASTER_SELECT_DDR,
{ 0, 8, 8, 16, IPA_EE_AP } },
[IPA_4_1_APQ_AUTO][IPA_CLIENT_TEST2_PROD] = {
true, IPA_v4_0_GROUP_UL_DL,
true,
IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
QMB_MASTER_SELECT_DDR,
{ 6, 2, 8, 16, IPA_EE_AP } },
[IPA_4_1_APQ_AUTO][IPA_CLIENT_WLAN2_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
{ 18, 15, 8, 13, IPA_EE_AP } },
[IPA_4_1_APQ_AUTO][IPA_CLIENT_USB_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
{ 19, 12, 9, 9, IPA_EE_AP } },
[IPA_4_1_APQ_AUTO][IPA_CLIENT_USB_DPL_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
{ 15, 7, 5, 5, IPA_EE_AP } },
[IPA_4_1_APQ_AUTO][IPA_CLIENT_APPS_LAN_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
{ 10, 5, 9, 9, IPA_EE_AP } },
[IPA_4_1_APQ_AUTO][IPA_CLIENT_ODL_DPL_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
{ 12, 2, 9, 9, IPA_EE_AP } },
[IPA_4_1_APQ_AUTO][IPA_CLIENT_ETHERNET_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
{ 22, 1, 9, 9, IPA_EE_UC } },
/* Only for test purpose */
/* MBIM aggregation test pipes should have the same QMB as USB_CONS */
[IPA_4_1_APQ_AUTO][IPA_CLIENT_TEST_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
{ 19, 12, 9, 9, IPA_EE_AP } },
[IPA_4_1_APQ_AUTO][IPA_CLIENT_TEST1_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
{ 19, 12, 9, 9, IPA_EE_AP } },
[IPA_4_1_APQ_AUTO][IPA_CLIENT_TEST2_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
{ 18, 3, 9, 9, IPA_EE_AP } },
[IPA_4_1_APQ_AUTO][IPA_CLIENT_TEST3_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
{ 15, 7, 5, 5, IPA_EE_AP } },
/* Dummy consumer (pipe 31) is used in L2TP rt rule */
[IPA_4_1_APQ_AUTO][IPA_CLIENT_DUMMY_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
{ 31, 31, 8, 8, IPA_EE_AP } },
/* IPA_4_2 */
[IPA_4_2][IPA_CLIENT_WLAN1_PROD] = {
true, IPA_v4_2_GROUP_UL_DL,
@ -4459,6 +4607,12 @@ u8 ipa3_get_hw_type_index(void)
break;
case IPA_HW_v4_1:
hw_type_index = IPA_4_1;
if (ipa3_ctx->platform_type == IPA_PLAT_TYPE_APQ) {
hw_type_index = IPA_4_1_APQ;
if (ipa3_ctx->ipa_config_is_auto) {
hw_type_index = IPA_4_1_APQ_AUTO;
}
}
break;
case IPA_HW_v4_2:
hw_type_index = IPA_4_2;
@ -7888,6 +8042,8 @@ static void ipa3_write_rsrc_grp_type_reg(int group_index,
case IPA_4_0:
case IPA_4_0_MHI:
case IPA_4_1:
case IPA_4_1_APQ:
case IPA_4_1_APQ_AUTO:
if (src) {
switch (group_index) {
case IPA_v4_0_GROUP_LWA_DL:
@ -8253,6 +8409,8 @@ void ipa3_set_resorce_groups_min_max_limits(void)
case IPA_4_0:
case IPA_4_0_MHI:
case IPA_4_1:
case IPA_4_1_APQ:
case IPA_4_1_APQ_AUTO:
src_rsrc_type_max = IPA_v4_0_RSRC_GRP_TYPE_SRC_MAX;
dst_rsrc_type_max = IPA_v4_0_RSRC_GRP_TYPE_DST_MAX;
src_grp_idx_max = IPA_v4_0_SRC_GROUP_MAX;

View file

@ -1477,6 +1477,9 @@ static int ipahal_cp_proc_ctx_to_hw_buff_v3(enum ipa_hdr_proc_type type,
case IPA_HDR_PROC_802_3_TO_802_3:
ctx->cmd.value = IPA_HDR_UCP_802_3_TO_802_3;
break;
case IPA_HDR_PROC_SET_DSCP:
ctx->cmd.value = IPA_HDR_UCP_SET_DSCP;
break;
default:
IPAHAL_ERR("unknown ipa_hdr_proc_type %d", type);
WARN_ON(1);
@ -1522,6 +1525,9 @@ static int ipahal_get_proc_ctx_needed_len_v3(enum ipa_hdr_proc_type type)
case IPA_HDR_PROC_ETHII_TO_ETHII_EX:
ret = sizeof(struct ipa_hw_hdr_proc_ctx_add_hdr_cmd_seq_ex);
break;
case IPA_HDR_PROC_SET_DSCP:
ret = sizeof(struct ipa_hw_hdr_proc_ctx_add_hdr_cmd_seq);
break;
default:
/* invalid value to make sure failure */
IPAHAL_ERR_RL("invalid ipa_hdr_proc_type %d\n", type);

View file

@ -675,6 +675,7 @@ union ipa_pkt_status_hw {
#define IPA_HDR_UCP_L2TP_UDP_HEADER_ADD 12
#define IPA_HDR_UCP_L2TP_UDP_HEADER_REMOVE 13
#define IPA_HDR_UCP_ETHII_TO_ETHII_EX 14
#define IPA_HDR_UCP_SET_DSCP 16
/* Processing context TLV type */
#define IPA_PROC_CTX_TLV_TYPE_END 0

View file

@ -90,6 +90,10 @@ static DECLARE_DELAYED_WORK(ipa_tether_stats_poll_wakequeue_work,
static int rmnet_ipa_send_coalesce_notification(uint8_t qmap_id, bool enable,
bool tcp, bool udp);
static int rmnet_ipa_send_set_mtu_notification(char *if_name,
uint16_t mtu_v4, uint16_t mtu_v6, enum ipa_ip_type ip);
enum ipa3_wwan_device_status {
WWAN_DEVICE_INACTIVE = 0,
WWAN_DEVICE_ACTIVE = 1
@ -1395,7 +1399,7 @@ static void apps_ipa_packet_receive_notify(void *priv,
skb_set_mac_header(skb, 0);
if (ipa3_rmnet_res.ipa_napi_enable) {
trace_rmnet_ipa_netif_rcv_skb3(dev->stats.rx_packets);
trace_rmnet_ipa_netif_rcv_skb3(skb, dev->stats.rx_packets);
result = netif_receive_skb(skb);
} else {
if (dev->stats.rx_packets % IPA_WWAN_RX_SOFTIRQ_THRESH
@ -1756,6 +1760,8 @@ static int ipa3_wwan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
struct mutex *mux_mutex_ptr;
int wan_ep;
bool tcp_en = false, udp_en = false;
bool mtu_v4_set = false, mtu_v6_set = false;
enum ipa_ip_type iptype;
IPAWANDBG("rmnet_ipa got ioctl number 0x%08x", cmd);
switch (cmd) {
@ -2086,6 +2092,65 @@ static int ipa3_wwan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
}
mutex_unlock(&rmnet_ipa3_ctx->clock_vote.mutex);
break;
/* Get MTU */
case RMNET_IOCTL_GET_MTU:
mux_channel = rmnet_ipa3_ctx->mux_channel;
rmnet_index =
find_vchannel_name_index(ext_ioctl_data.u.mtu_params.if_name);
if (rmnet_index == MAX_NUM_OF_MUX_CHANNEL) {
IPAWANERR("%s is an invalid iface name\n",
ext_ioctl_data.u.mtu_params.if_name);
return -ENODEV;
}
IPAWANDBG("getting v4 MTU = %d\n", mux_channel[rmnet_index].mtu_v4);
ext_ioctl_data.u.mtu_params.mtu_v4 =
mux_channel[rmnet_index].mtu_v4;
IPAWANDBG("getting v6 MTU = %d\n", mux_channel[rmnet_index].mtu_v6);
ext_ioctl_data.u.mtu_params.mtu_v6 =
mux_channel[rmnet_index].mtu_v6;
break;
/* Set MTU */
case RMNET_IOCTL_SET_MTU:
mux_channel = rmnet_ipa3_ctx->mux_channel;
rmnet_index =
find_vchannel_name_index(ext_ioctl_data.u.mtu_params.if_name);
if (rmnet_index == MAX_NUM_OF_MUX_CHANNEL) {
IPAWANERR("%s is an invalid iface name\n",
ext_ioctl_data.u.mtu_params.if_name);
return -ENODEV;
}
/* V4 case */
if (ext_ioctl_data.u.mtu_params.mtu_v4 > 0) {
mux_channel[rmnet_index].mtu_v4 =
ext_ioctl_data.u.mtu_params.mtu_v4;
mtu_v4_set = true;
IPAWANDBG("Set v4 MTU = %d\n", mux_channel[rmnet_index].mtu_v4);
iptype = IPA_IP_v4;
}
/* V6 case */
if (ext_ioctl_data.u.mtu_params.mtu_v6 > 0) {
mux_channel[rmnet_index].mtu_v6 =
ext_ioctl_data.u.mtu_params.mtu_v6;
mtu_v6_set = true;
IPAWANDBG("Set v6 MTU = %d\n", mux_channel[rmnet_index].mtu_v6);
iptype = IPA_IP_v6;
}
if (mtu_v4_set && mtu_v6_set)
iptype = IPA_IP_MAX;
rc = rmnet_ipa_send_set_mtu_notification(
ext_ioctl_data.u.mtu_params.if_name,
mux_channel[rmnet_index].mtu_v4,
mux_channel[rmnet_index].mtu_v6,
iptype);
break;
default:
IPAWANERR("[%s] unsupported extended cmd[%d]",
dev->name,
@ -2179,6 +2244,37 @@ static int rmnet_ipa_send_coalesce_notification(uint8_t qmap_id,
return 0;
}
static int rmnet_ipa_send_set_mtu_notification(char *if_name,
uint16_t mtu_v4, uint16_t mtu_v6, enum ipa_ip_type ip)
{
struct ipa_msg_meta msg_meta;
struct ipa_mtu_info *mtu_info;
int rc;
memset(&msg_meta, 0, sizeof(struct ipa_msg_meta));
mtu_info = kzalloc(sizeof(*mtu_info), GFP_KERNEL);
if (!mtu_info)
return -ENOMEM;
strlcpy(mtu_info->if_name, if_name, IPA_RESOURCE_NAME_MAX);
mtu_info->mtu_v4 = mtu_v4;
mtu_info->mtu_v6 = mtu_v6;
mtu_info->ip_type = ip;
msg_meta.msg_type = IPA_SET_MTU;
msg_meta.msg_len = sizeof(struct ipa_mtu_info);
rc = ipa_send_msg(&msg_meta, mtu_info, ipa3_wwan_msg_free_cb);
if (rc) {
IPAWANERR("ipa_send_msg failed: %d\n", rc);
return -EFAULT;
}
IPAWANDBG(
"sent new mtu_v4(%d)/mtu_v6(%d) with iptype(%d) for iface(%s) to IPACM",
mtu_v4, mtu_v6, ip, if_name);
return 0;
}
int ipa3_wwan_set_modem_state(struct wan_ioctl_notify_wan_state *state)
{
uint32_t bw_mbps = 0;
@ -4785,13 +4881,118 @@ int rmnet_ipa3_query_per_client_stats(
return 0;
}
/* rmnet_ipa3_get_wan_mtu() -
* @data - IOCTL data
*
* This function handles WAN_IOC_GET_WAN_MTU.
* It is used to send WAN MTU information to IPACM.
*
* Return codes:
* 0: Success
* -EINVAL: Invalid args provided
*/
int rmnet_ipa3_get_wan_mtu(
struct ipa_mtu_info *data)
{
struct ipa3_rmnet_mux_val *mux_channel;
int rmnet_index;
mux_channel = rmnet_ipa3_ctx->mux_channel;
rmnet_index =
find_vchannel_name_index(data->if_name);
if (rmnet_index == MAX_NUM_OF_MUX_CHANNEL) {
IPAWANERR("%s is an invalid iface name\n",
data->if_name);
return -ENODEV;
}
IPAWANDBG("getting v4 MTU = %d\n", mux_channel[rmnet_index].mtu_v4);
data->mtu_v4 =
mux_channel[rmnet_index].mtu_v4;
IPAWANDBG("getting v6 MTU = %d\n", mux_channel[rmnet_index].mtu_v6);
data->mtu_v6 =
mux_channel[rmnet_index].mtu_v6;
return 0;
}
#ifdef CONFIG_DEBUG_FS
static char dbg_buff[4096];
static ssize_t rmnet_ipa_set_mtu(struct file *file,
const char __user *buf, size_t count, loff_t *ppos)
{
__s8 if_name[IFNAMSIZ];
uint16_t mtu_v4 = 0, mtu_v6 = 0;
unsigned long missing;
char *sptr, *token;
if (count >= sizeof(dbg_buff))
return -EFAULT;
missing = copy_from_user(dbg_buff, buf, count);
if (missing)
return -EFAULT;
dbg_buff[count] = '\0';
sptr = dbg_buff;
memset(if_name, 0, IFNAMSIZ);
token = strsep(&sptr, " ");
if (!token)
return -EINVAL;
strlcpy(if_name, token, IFNAMSIZ);
token = strsep(&sptr, " ");
if (!token)
return -EINVAL;
if (kstrtou16(token, 0, &mtu_v4))
return -EINVAL;
token = strsep(&sptr, " ");
if (!token)
return -EINVAL;
if (kstrtou16(token, 0, &mtu_v6))
return -EINVAL;
rmnet_ipa_send_set_mtu_notification(
if_name,
mtu_v4,
mtu_v6, IPA_IP_MAX);
return count;
}
#define RMNET_IPA_WRITE_ONLY_MODE 0220
struct rmnet_ipa_debugfs_file {
const char *name;
umode_t mode;
void *data;
const struct file_operations fops;
};
static const struct rmnet_ipa_debugfs_file debugfs_files[] = {
{
"mtu", RMNET_IPA_WRITE_ONLY_MODE, NULL, {
.write = rmnet_ipa_set_mtu,
}
},
};
static void rmnet_ipa_debugfs_init(void)
{
const mode_t read_write_mode = 0664;
int i = 0;
struct dentry *file;
struct rmnet_ipa_debugfs *dbgfs = &rmnet_ipa3_ctx->dbgfs;
const size_t debugfs_files_num =
sizeof(debugfs_files) / sizeof(struct rmnet_ipa_debugfs_file);
dbgfs->dent = debugfs_create_dir("rmnet_ipa", 0);
@ -4800,6 +5001,18 @@ static void rmnet_ipa_debugfs_init(void)
return;
}
for (i = 0; i < debugfs_files_num; ++i) {
const struct rmnet_ipa_debugfs_file *curr = &debugfs_files[i];
file = debugfs_create_file(curr->name, curr->mode, dbgfs->dent,
curr->data, &curr->fops);
if (!file || IS_ERR(file)) {
IPAERR("fail to create file for debug_fs %s\n",
curr->name);
goto fail;
}
}
dbgfs->dfile_outstanding_high = debugfs_create_u32("outstanding_high",
read_write_mode, dbgfs->dent,
&rmnet_ipa3_ctx->outstanding_high);

View file

@ -475,6 +475,28 @@ static long ipa3_wan_ioctl(struct file *filp,
}
break;
case WAN_IOC_GET_WAN_MTU:
IPAWANDBG_LOW("got WAN_IOC_GET_WAN_MTU :>>>\n");
pyld_sz = sizeof(struct ipa_mtu_info);
param = memdup_user((const void __user *)arg, pyld_sz);
if (IS_ERR(param)) {
retval = PTR_ERR(param);
break;
}
if (rmnet_ipa3_get_wan_mtu(
(struct ipa_mtu_info *)
param)) {
IPAWANERR("WAN_IOC_GET_WAN_MTU failed\n");
retval = -EFAULT;
break;
}
if (copy_to_user((void __user *)arg, param, pyld_sz)) {
retval = -EFAULT;
break;
}
break;
default:
retval = -ENOTTY;
}