From 4dcae9f2d57d204df008d9bd81fb8fae2a64ff05 Mon Sep 17 00:00:00 2001 From: Amir Levy Date: Sun, 14 Jul 2019 10:10:33 +0300 Subject: [PATCH] msm: ipa4: add ipa_wigig debugfs Add debugging capabilities to ipa_wigig. Change-Id: I41ce94bbb2af597aa11848869261d8d432fa0e04 Signed-off-by: Arnav Sharma --- ipa/ipa_api.c | 15 +-- ipa/ipa_api.h | 5 +- ipa/ipa_clients/ipa_wigig.c | 181 +++++++++++++++++++++++++++++++++++- ipa/ipa_common_i.h | 5 +- ipa/ipa_v3/ipa_debugfs.c | 2 + ipa/ipa_v3/ipa_i.h | 7 +- ipa/ipa_v3/ipa_utils.c | 2 +- ipa/ipa_v3/ipa_wigig_i.c | 77 +++++++++++++-- 8 files changed, 271 insertions(+), 23 deletions(-) diff --git a/ipa/ipa_api.c b/ipa/ipa_api.c index f5560e9c93ec..28a2fc67f05c 100644 --- a/ipa/ipa_api.c +++ b/ipa/ipa_api.c @@ -2071,29 +2071,29 @@ int ipa_uc_reg_rdyCB( EXPORT_SYMBOL(ipa_uc_reg_rdyCB); /** -* ipa_wigig_uc_init() - get uc db and register uC +* ipa_wigig_internal_init() - get uc db and register uC * ready CB if uC not ready, wigig only. * @inout: [in/out] uc ready input/output parameters * from/to client * @int_notify: [in] wigig misc interrupt handler function +* @uc_db_pa: [out] uC db physical address * * Returns: 0 on success, negative on failure * */ - -int ipa_wigig_uc_init( +int ipa_wigig_internal_init( struct ipa_wdi_uc_ready_params *inout, ipa_wigig_misc_int_cb int_notify, phys_addr_t *uc_db_pa) { int ret; - IPA_API_DISPATCH_RETURN(ipa_wigig_uc_init, inout, + IPA_API_DISPATCH_RETURN(ipa_wigig_internal_init, inout, int_notify, uc_db_pa); return ret; } -EXPORT_SYMBOL(ipa_wigig_uc_init); +EXPORT_SYMBOL(ipa_wigig_internal_init); /** * ipa_uc_dereg_rdyCB() - To de-register uC ready CB @@ -3549,11 +3549,12 @@ EXPORT_SYMBOL(ipa_wigig_uc_msi_init); /** * ipa_conn_wigig_rx_pipe_i() - connect wigig rx pipe */ -int ipa_conn_wigig_rx_pipe_i(void *in, struct ipa_wigig_conn_out_params *out) +int ipa_conn_wigig_rx_pipe_i(void *in, struct ipa_wigig_conn_out_params *out, + struct dentry **parent) { int ret; - IPA_API_DISPATCH_RETURN(ipa_conn_wigig_rx_pipe_i, in, out); + IPA_API_DISPATCH_RETURN(ipa_conn_wigig_rx_pipe_i, in, out, parent); return ret; } diff --git a/ipa/ipa_api.h b/ipa/ipa_api.h index db98b5ec4ea6..1f8a4033e7e7 100644 --- a/ipa/ipa_api.h +++ b/ipa/ipa_api.h @@ -432,13 +432,14 @@ struct ipa_api_controller { struct ipa_smmu_out_params *out); int (*ipa_is_vlan_mode)(enum ipa_vlan_ifaces iface, bool *res); - int (*ipa_wigig_uc_init)( + int (*ipa_wigig_internal_init)( struct ipa_wdi_uc_ready_params *inout, ipa_wigig_misc_int_cb int_notify, phys_addr_t *uc_db_pa); int (*ipa_conn_wigig_rx_pipe_i)(void *in, - struct ipa_wigig_conn_out_params *out); + struct ipa_wigig_conn_out_params *out, + struct dentry **parent); int (*ipa_conn_wigig_client_i)(void *in, struct ipa_wigig_conn_out_params *out, diff --git a/ipa/ipa_clients/ipa_wigig.c b/ipa/ipa_clients/ipa_wigig.c index 7f0036df5e15..6bcb502103da 100644 --- a/ipa/ipa_clients/ipa_wigig.c +++ b/ipa/ipa_clients/ipa_wigig.c @@ -4,6 +4,7 @@ */ #include +#include #include #include "../ipa_common_i.h" #include "../ipa_v3/ipa_pm.h" @@ -105,10 +106,21 @@ struct ipa_wigig_context { bool smmu_en; bool shared_cb; u8 conn_pipes; + struct dentry *parent; + struct dentry *dent_conn_clients; + struct dentry *dent_smmu; }; static struct ipa_wigig_context *ipa_wigig_ctx; +#ifdef CONFIG_DEBUG_FS +static int ipa_wigig_init_debugfs(struct dentry *parent); +static inline void ipa_wigig_deinit_debugfs(void); +#else +static int ipa_wigig_init_debugfs(struct dentry *parent) { return 0; } +static inline void ipa_wigig_deinit_debugfs(void) { } +#endif + int ipa_wigig_init(struct ipa_wigig_init_in_params *in, struct ipa_wigig_init_out_params *out) { @@ -148,7 +160,8 @@ int ipa_wigig_init(struct ipa_wigig_init_in_params *in, inout.notify = in->notify; inout.priv = in->priv; - if (ipa_wigig_uc_init(&inout, in->int_notify, &out->uc_db_pa)) { + if (ipa_wigig_internal_init(&inout, in->int_notify, + &out->uc_db_pa)) { kfree(ipa_wigig_ctx); ipa_wigig_ctx = NULL; return -EFAULT; @@ -182,6 +195,9 @@ int ipa_wigig_cleanup(void) } mutex_destroy(&ipa_wigig_ctx->lock); + + ipa_wigig_deinit_debugfs(); + kfree(ipa_wigig_ctx); ipa_wigig_ctx = NULL; @@ -708,7 +724,7 @@ int ipa_wigig_conn_rx_pipe(struct ipa_wigig_conn_rx_in_params *in, goto fail_msi; } - if (ipa_conn_wigig_rx_pipe_i(in, out)) { + if (ipa_conn_wigig_rx_pipe_i(in, out, &ipa_wigig_ctx->parent)) { IPA_WIGIG_ERR("fail to connect rx pipe\n"); ret = -EFAULT; goto fail_connect_pipe; @@ -717,6 +733,9 @@ int ipa_wigig_conn_rx_pipe(struct ipa_wigig_conn_rx_in_params *in, ipa_wigig_ctx->tx_notify = in->notify; ipa_wigig_ctx->priv = in->priv; + if (ipa_wigig_ctx->parent) + ipa_wigig_init_debugfs(ipa_wigig_ctx->parent); + ipa_wigig_store_pipe_info(ipa_wigig_ctx->pipes.flat, IPA_CLIENT_WIGIG_PROD_IDX); @@ -1453,12 +1472,15 @@ int ipa_wigig_conn_rx_pipe_smmu( goto fail_msi; } - if (ipa_conn_wigig_rx_pipe_i(in, out)) { + if (ipa_conn_wigig_rx_pipe_i(in, out, &ipa_wigig_ctx->parent)) { IPA_WIGIG_ERR("fail to connect rx pipe\n"); ret = -EFAULT; goto fail_connect_pipe; } + if (ipa_wigig_ctx->parent) + ipa_wigig_init_debugfs(ipa_wigig_ctx->parent); + if (ipa_wigig_store_rx_smmu_info(in)) { IPA_WIGIG_ERR("fail to store smmu data for rx pipe\n"); ret = -EFAULT; @@ -1913,3 +1935,156 @@ int ipa_wigig_tx_dp(enum ipa_client_type dst, struct sk_buff *skb) return 0; } EXPORT_SYMBOL(ipa_wigig_tx_dp); + + +#ifdef CONFIG_DEBUG_FS +#define IPA_MAX_MSG_LEN 4096 + +static ssize_t ipa_wigig_read_conn_clients(struct file *file, + char __user *ubuf, size_t count, loff_t *ppos) +{ + int i; + int nbytes = 0; + u8 pipe_connected; + char *dbg_buff; + ssize_t ret; + + dbg_buff = kzalloc(IPA_MAX_MSG_LEN, GFP_KERNEL); + if (!dbg_buff) + return -ENOMEM; + + if (!ipa_wigig_ctx) { + nbytes += scnprintf(dbg_buff + nbytes, + IPA_MAX_MSG_LEN - nbytes, + "IPA WIGIG not initialized\n"); + goto finish; + } + + if (!ipa_wigig_ctx->conn_pipes) { + nbytes += scnprintf(dbg_buff + nbytes, + IPA_MAX_MSG_LEN - nbytes, + "no WIGIG pipes connected\n"); + goto finish; + } + + for (i = 0; i < IPA_WIGIG_MAX_PIPES; i++) { + pipe_connected = (ipa_wigig_ctx->conn_pipes & (0x1 << i)); + switch (i) { + case 0: + nbytes += scnprintf(dbg_buff + nbytes, + IPA_MAX_MSG_LEN - nbytes, + "IPA_CLIENT_WIGIG_PROD"); + break; + case 1: + case 2: + case 3: + case 4: + nbytes += scnprintf(dbg_buff + nbytes, + IPA_MAX_MSG_LEN - nbytes, + "IPA_CLIENT_WIGIG%d_CONS", + i); + break; + default: + IPA_WIGIG_ERR("invalid pipe %d\n", i); + nbytes += scnprintf(dbg_buff + nbytes, + IPA_MAX_MSG_LEN - nbytes, + "invalid pipe %d", + i); + break; + } + nbytes += scnprintf(dbg_buff + nbytes, + IPA_MAX_MSG_LEN - nbytes, + " %s connected\n", pipe_connected ? "is" : "not"); + } + +finish: + ret = simple_read_from_buffer( + ubuf, count, ppos, dbg_buff, nbytes); + kfree(dbg_buff); + return ret; +} + +static ssize_t ipa_wigig_read_smmu_status(struct file *file, + char __user *ubuf, size_t count, loff_t *ppos) +{ + int nbytes = 0; + char *dbg_buff; + ssize_t ret; + + dbg_buff = kzalloc(IPA_MAX_MSG_LEN, GFP_KERNEL); + if (!dbg_buff) + return -ENOMEM; + + if (!ipa_wigig_ctx) { + nbytes += scnprintf(dbg_buff + nbytes, + IPA_MAX_MSG_LEN - nbytes, + "IPA WIGIG not initialized\n"); + goto finish; + } + + if (ipa_wigig_ctx->smmu_en) { + nbytes += scnprintf(dbg_buff + nbytes, + IPA_MAX_MSG_LEN - nbytes, + "SMMU enabled\n"); + + if (ipa_wigig_ctx->shared_cb) { + nbytes += scnprintf(dbg_buff + nbytes, + IPA_MAX_MSG_LEN - nbytes, + "CB shared\n"); + } else { + nbytes += scnprintf(dbg_buff + nbytes, + IPA_MAX_MSG_LEN - nbytes, + "CB not shared\n"); + } + } else { + nbytes += scnprintf(dbg_buff + nbytes, + IPA_MAX_MSG_LEN - nbytes, + "SMMU in S1 bypass\n"); + } +finish: + ret = simple_read_from_buffer( + ubuf, count, ppos, dbg_buff, nbytes); + kfree(dbg_buff); + return ret; +} +static const struct file_operations ipa_wigig_conn_clients_ops = { + .read = ipa_wigig_read_conn_clients, +}; + +static const struct file_operations ipa_wigig_smmu_ops = { + .read = ipa_wigig_read_smmu_status, +}; + +static inline void ipa_wigig_deinit_debugfs(void) +{ + debugfs_remove(ipa_wigig_ctx->dent_conn_clients); + debugfs_remove(ipa_wigig_ctx->dent_smmu); +} + +static int ipa_wigig_init_debugfs(struct dentry *parent) +{ + const mode_t read_only_mode = 0444; + + ipa_wigig_ctx->dent_conn_clients = + debugfs_create_file("conn_clients", read_only_mode, parent, + NULL, &ipa_wigig_conn_clients_ops); + if (IS_ERR_OR_NULL(ipa_wigig_ctx->dent_conn_clients)) { + IPA_WIGIG_ERR("fail to create file %s\n", "conn_clients"); + goto fail_conn_clients; + } + + ipa_wigig_ctx->dent_smmu = + debugfs_create_file("smmu", read_only_mode, parent, NULL, + &ipa_wigig_smmu_ops); + if (IS_ERR_OR_NULL(ipa_wigig_ctx->dent_smmu)) { + IPA_WIGIG_ERR("fail to create file %s\n", "smmu"); + goto fail_smmu; + } + + return 0; +fail_smmu: + debugfs_remove(ipa_wigig_ctx->dent_conn_clients); +fail_conn_clients: + return -EFAULT; +} +#endif diff --git a/ipa/ipa_common_i.h b/ipa/ipa_common_i.h index b8d5a4aa5ea0..88e361997697 100644 --- a/ipa/ipa_common_i.h +++ b/ipa/ipa_common_i.h @@ -435,12 +435,13 @@ int ipa_smmu_free_sgt(struct sg_table **out_sgt_ptr); int ipa_ut_module_init(void); void ipa_ut_module_exit(void); -int ipa_wigig_uc_init( +int ipa_wigig_internal_init( struct ipa_wdi_uc_ready_params *inout, ipa_wigig_misc_int_cb int_notify, phys_addr_t *uc_db_pa); -int ipa_conn_wigig_rx_pipe_i(void *in, struct ipa_wigig_conn_out_params *out); +int ipa_conn_wigig_rx_pipe_i(void *in, struct ipa_wigig_conn_out_params *out, + struct dentry **parent); int ipa_conn_wigig_client_i(void *in, struct ipa_wigig_conn_out_params *out, ipa_notify_cb tx_notify, diff --git a/ipa/ipa_v3/ipa_debugfs.c b/ipa/ipa_v3/ipa_debugfs.c index 107df555a1de..adb0c99801d6 100644 --- a/ipa/ipa_v3/ipa_debugfs.c +++ b/ipa/ipa_v3/ipa_debugfs.c @@ -2524,6 +2524,8 @@ void ipa3_debugfs_init(void) ipa_debugfs_init_stats(dent); + ipa3_wigig_init_debugfs_i(dent); + return; fail: diff --git a/ipa/ipa_v3/ipa_i.h b/ipa/ipa_v3/ipa_i.h index e0cea1f0b2f1..fb07ba5dc7c1 100644 --- a/ipa/ipa_v3/ipa_i.h +++ b/ipa/ipa_v3/ipa_i.h @@ -2490,7 +2490,8 @@ int ipa3_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx); int ipa3_disable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx); int ipa3_conn_wigig_rx_pipe_i(void *in, - struct ipa_wigig_conn_out_params *out); + struct ipa_wigig_conn_out_params *out, + struct dentry **parent); int ipa3_conn_wigig_client_i(void *in, struct ipa_wigig_conn_out_params *out, @@ -2512,6 +2513,8 @@ int ipa3_enable_wigig_pipe_i(enum ipa_client_type client); int ipa3_disable_wigig_pipe_i(enum ipa_client_type client); +int ipa3_wigig_init_debugfs_i(struct dentry *dent); + /* * To retrieve doorbell physical address of * wlan pipes @@ -2834,7 +2837,7 @@ const struct ipa_gsi_ep_config *ipa3_get_gsi_ep_info (enum ipa_client_type client); int ipa3_wigig_init_i(void); -int ipa3_wigig_uc_init( +int ipa3_wigig_internal_init( struct ipa_wdi_uc_ready_params *inout, ipa_wigig_misc_int_cb int_notify, phys_addr_t *uc_db_pa); diff --git a/ipa/ipa_v3/ipa_utils.c b/ipa/ipa_v3/ipa_utils.c index 7d9b68f74b88..7c80164dae5b 100644 --- a/ipa/ipa_v3/ipa_utils.c +++ b/ipa/ipa_v3/ipa_utils.c @@ -6974,7 +6974,7 @@ int ipa3_bind_api_controller(enum ipa_hw_type ipa_hw_type, api_ctrl->ipa_tz_unlock_reg = ipa3_tz_unlock_reg; api_ctrl->ipa_get_smmu_params = ipa3_get_smmu_params; api_ctrl->ipa_is_vlan_mode = ipa3_is_vlan_mode; - api_ctrl->ipa_wigig_uc_init = ipa3_wigig_uc_init; + api_ctrl->ipa_wigig_internal_init = ipa3_wigig_internal_init; api_ctrl->ipa_conn_wigig_rx_pipe_i = ipa3_conn_wigig_rx_pipe_i; api_ctrl->ipa_conn_wigig_client_i = ipa3_conn_wigig_client_i; api_ctrl->ipa_disconn_wigig_pipe_i = ipa3_disconn_wigig_pipe_i; diff --git a/ipa/ipa_v3/ipa_wigig_i.c b/ipa/ipa_v3/ipa_wigig_i.c index aef24f5d7aa0..52546bd0374b 100644 --- a/ipa/ipa_v3/ipa_wigig_i.c +++ b/ipa/ipa_v3/ipa_wigig_i.c @@ -6,6 +6,7 @@ #include "ipa_i.h" #include #include +#include #include #define IPA_WIGIG_DESC_RING_EL_SIZE 32 @@ -30,6 +31,7 @@ static LIST_HEAD(smmu_reg_addr_list); static LIST_HEAD(smmu_ring_addr_list); static DEFINE_MUTEX(smmu_lock); +struct dentry *wigig_dent; struct ipa_wigig_smmu_reg_addr { struct list_head link; @@ -86,7 +88,7 @@ int ipa3_wigig_init_i(void) return 0; } -int ipa3_wigig_uc_init( +int ipa3_wigig_internal_init( struct ipa_wdi_uc_ready_params *inout, ipa_wigig_misc_int_cb int_notify, phys_addr_t *uc_db_pa) @@ -587,6 +589,11 @@ static void ipa_gsi_evt_ring_err_cb(struct gsi_evt_err_notify *notify) ipa_assert(); } +static uint16_t int_modt = 15; +static uint8_t int_modc = 200; +static uint8_t tx_hwtail_mod_threshold = 200; +static uint8_t rx_hwtail_mod_threshold = 200; + static int ipa3_wigig_config_gsi(bool Rx, bool smmu_en, void *pipe_info, @@ -616,8 +623,8 @@ static int ipa3_wigig_config_gsi(bool Rx, evt_props.exclusive = true; evt_props.err_cb = ipa_gsi_evt_ring_err_cb; evt_props.user_data = NULL; - evt_props.int_modc = 200; - evt_props.int_modt = 15; + evt_props.int_modc = int_modc; + evt_props.int_modt = int_modt; evt_props.ring_base_vaddr = NULL; if (smmu_en) { @@ -646,7 +653,8 @@ static int ipa3_wigig_config_gsi(bool Rx, union __packed gsi_evt_scratch evt_scratch; memset(&evt_scratch, 0, sizeof(evt_scratch)); - evt_scratch.w11ad.update_status_hwtail_mod_threshold = 200; + evt_scratch.w11ad.update_status_hwtail_mod_threshold = + rx_hwtail_mod_threshold; gsi_res = gsi_write_evt_ring_scratch(ep->gsi_evt_ring_hdl, evt_scratch); if (gsi_res != GSI_STATUS_SUCCESS) { @@ -792,7 +800,8 @@ static int ipa3_wigig_config_gsi(bool Rx, gsi_scratch.tx_11ad.fixed_data_buffer_size_pow_2 = ilog2(tx_dbuff->data_buffer_size); } - gsi_scratch.tx_11ad.update_status_hwtail_mod_threshold = 200; + gsi_scratch.tx_11ad.update_status_hwtail_mod_threshold = + tx_hwtail_mod_threshold; IPADBG("tx scratch: status_ring_hwtail_address_lsb 0x%X\n", gsi_scratch.tx_11ad.status_ring_hwtail_address_lsb); IPADBG("tx scratch: status_ring_hwhead_address_lsb 0x%X\n", @@ -926,7 +935,8 @@ static int ipa3_wigig_config_uc(bool init, return result; } -int ipa3_conn_wigig_rx_pipe_i(void *in, struct ipa_wigig_conn_out_params *out) +int ipa3_conn_wigig_rx_pipe_i(void *in, struct ipa_wigig_conn_out_params *out, + struct dentry **parent) { int ipa_ep_idx; struct ipa3_ep_context *ep; @@ -943,6 +953,8 @@ int ipa3_conn_wigig_rx_pipe_i(void *in, struct ipa_wigig_conn_out_params *out) IPADBG("\n"); + *parent = wigig_dent; + ipa_ep_idx = ipa_get_ep_mapping(rx_client); if (ipa_ep_idx == IPA_EP_NOT_ALLOCATED || ipa_ep_idx >= IPA3_MAX_NUM_PIPES) { @@ -1847,3 +1859,56 @@ fail_stop_channel: ipa_assert(); return res; } + +#ifndef CONFIG_DEBUG_FS +int ipa3_wigig_init_debugfs_i(struct dentry *parent) { return 0; } +#else +int ipa3_wigig_init_debugfs_i(struct dentry *parent) +{ + const mode_t read_write_mode = 0664; + struct dentry *file = NULL; + struct dentry *dent; + + dent = debugfs_create_dir("ipa_wigig", parent); + if (IS_ERR_OR_NULL(dent)) { + IPAERR("fail to create folder in debug_fs\n"); + return -EFAULT; + } + + wigig_dent = dent; + + file = debugfs_create_u8("modc", read_write_mode, dent, + &int_modc); + if (IS_ERR_OR_NULL(file)) { + IPAERR("fail to create file modc\n"); + goto fail; + } + + file = debugfs_create_u16("modt", read_write_mode, dent, + &int_modt); + if (IS_ERR_OR_NULL(file)) { + IPAERR("fail to create file modt\n"); + goto fail; + } + + file = debugfs_create_u8("rx_mod_th", read_write_mode, dent, + &rx_hwtail_mod_threshold); + if (IS_ERR_OR_NULL(file)) { + IPAERR("fail to create file rx_mod_th\n"); + goto fail; + } + + file = debugfs_create_u8("tx_mod_th", read_write_mode, dent, + &tx_hwtail_mod_threshold); + if (IS_ERR_OR_NULL(file)) { + IPAERR("fail to create file tx_mod_th\n"); + goto fail; + } + + return 0; +fail: + debugfs_remove_recursive(dent); + wigig_dent = NULL; + return -EFAULT; +} +#endif